Skip to content

Commit

Permalink
third-party/rust: bindgen: patch in PR 2772
Browse files Browse the repository at this point in the history
Summary:
[PR 2772](rust-lang/rust-bindgen#2772) adds the --flexarray-dst option to handle C Flexible Array Members as Rust dynamically sized types. Still pending review, but discussion has been positive.

Full details:

Add `--flexarray-dst` option to allow use of a dynamically sized struct to model a C flexible array member. For example, given the C struct:
```
struct msg {
    unsigned int tag;
    unsigned int len;
    char payload[];
};
```
generate the corresponding Rust type:
```rust
#[repr(C)]
#[derive(Debug)]
pub struct msg<FAM: ?Sized = [::std::os::raw::c_char; 0]> {
    pub tag: ::std::os::raw::c_uint,
    pub len: ::std::os::raw::c_uint,
    pub payload: FAM,
}
```
This single definition is used for both Sized (with a zero-length array as the FAM type) and DST (with a slice).

This also generates the helper methods to convert a raw pointer into a Rust view of the C type, with a given length.
```rust
// Sized implementations
impl msg<[::std::os::raw::c_char; 0]> {
    // Construct a DST reference from a Sized object.
    // SAFETY: there must be at least `len` initialized elements in the underlying storage
    pub unsafe fn flex_ref(
        &self,
        len: usize,
    ) -> &msg<[::std::os::raw::c_char]> {
        unsafe { Self::flex_ptr(self, len) }
    }

    // Same, but mutable
    pub unsafe fn flex_mut_ref(
        &mut self,
        len: usize,
    ) -> &mut msg<[::std::os::raw::c_char]> {
        unsafe { Self::flex_ptr_mut(self, len).assume_init() }
    }

    // Raw pointer variants
    pub unsafe fn flex_ptr<'unbounded>(
        ptr: *const Self,
        len: usize,
    ) -> &'unbounded msg<[::std::os::raw::c_char]> {
        unsafe { &*::std::ptr::from_raw_parts(ptr as *const (), len) }
    }

    pub unsafe fn flex_ptr_mut<'unbounded>(
        ptr: *mut Self,
        len: usize,
    ) -> ::std::mem::MaybeUninit<&'unbounded mut msg<[::std::os::raw::c_char]>>
    {
        unsafe {
            let mut uninit = ::std::mem::MaybeUninit::<
                &mut msg<[::std::os::raw::c_char]>,
            >::uninit();
            (uninit.as_mut_ptr() as *mut *mut msg<[::std::os::raw::c_char]>)
                .write(::std::ptr::from_raw_parts_mut(ptr as *mut (), len));
            uninit
        }
    }
}

// DST implementations
impl msg<[::std::os::raw::c_char]> {
    // Memory size & alignment for allocation
    pub fn layout(len: usize) -> ::std::alloc::Layout {
        unsafe {
            let p: *const Self =
                ::std::ptr::from_raw_parts(::std::ptr::null(), len);
            ::std::alloc::Layout::for_value_raw(p)
        }
    }
    // return the Sized variant along with the length
    pub fn fixed(&self) -> (&msg<[::std::os::raw::c_char; 0]>, usize) {
        unsafe {
            let (ptr, len) = (self as *const Self).to_raw_parts();
            (&*(ptr as *const msg<[::std::os::raw::c_char; 0]>), len)
        }
    }
    pub fn fixed_mut(
        &mut self,
    ) -> (&mut msg<[::std::os::raw::c_char; 0]>, usize) {
        unsafe {
            let (ptr, len) = (self as *mut Self).to_raw_parts();
            (&mut *(ptr as *mut msg<[::std::os::raw::c_char; 0]>), len)
        }
    }
}
```

Upside:
- The flexible array member is directly expressed in a fairly conventional Rust type, with no need to interact with the bindgen-specific `__IncompleteArrayField` type
  - In particular, normal `size_of` will work, taking into account the dynamically sized extension

Problems/TODO:
- depends on unstable `ptr_metadata` and `layout_for_ptr` features
- `from_ptr(_mut)` return references with unbounded lifetimes - it would be up to the caller to constrain them to the underlying storage's lifetime
  - I experimented with a variant which also takes a "lifetime witness" parameter `_lt: &'a LT` which can be used to bound the returned lifetime, but I'll need to try it in practice to see if it works.

This is a prototype for #2771

Reviewed By: dtolnay

Differential Revision: D54605921

fbshipit-source-id: 929ec448b758975ce736c21fde6b805e3d297bb7
  • Loading branch information
Jeremy Fitzhardinge authored and facebook-github-bot committed Apr 2, 2024
1 parent eb75c87 commit c4f47e9
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 4 deletions.
4 changes: 2 additions & 2 deletions eden/fs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[patch.crates-io]
abomonation = { git = "https://github.com/markbt/abomonation", rev = "0f43346d2afa2aedc64d61f3f4273e8d1e454642" }
base64urlsafedata = { git = "https://github.com/kanidm/webauthn-rs.git", rev = "d278c56adfa39a0723c79bdcd461644194bc5138" }
bindgen = { git = "https://github.com/rust-lang/rust-bindgen", rev = "2997017b5a3065b83e9d76f0080d6cb99c94c0c1" }
bindgen-cli = { git = "https://github.com/rust-lang/rust-bindgen", rev = "2997017b5a3065b83e9d76f0080d6cb99c94c0c1" }
bindgen = { git = "https://github.com/rust-lang/rust-bindgen", rev = "7e9043497297e04e91ae76dfe0d2e7998828e529" }
bindgen-cli = { git = "https://github.com/rust-lang/rust-bindgen", rev = "7e9043497297e04e91ae76dfe0d2e7998828e529" }
cxx = { package = "cxx", git = "https://github.com/facebookexperimental/cxx.git", rev = "69a4f12f40d99284ebda58f33602ab60b70624d7" }
cxx-build = { package = "cxx-build", git = "https://github.com/facebookexperimental/cxx.git", rev = "69a4f12f40d99284ebda58f33602ab60b70624d7" }
graphql-parser = { git = "https://github.com/graphql-rust//graphql-parser", rev = "8d76425d83c40670570cc325f57c730262f07456" }
Expand Down
4 changes: 2 additions & 2 deletions eden/mononoke/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ toml = "0.8.4"
[patch.crates-io]
abomonation = { git = "https://github.com/markbt/abomonation", rev = "0f43346d2afa2aedc64d61f3f4273e8d1e454642" }
base64urlsafedata = { git = "https://github.com/kanidm/webauthn-rs.git", rev = "d278c56adfa39a0723c79bdcd461644194bc5138" }
bindgen = { git = "https://github.com/rust-lang/rust-bindgen", rev = "2997017b5a3065b83e9d76f0080d6cb99c94c0c1" }
bindgen-cli = { git = "https://github.com/rust-lang/rust-bindgen", rev = "2997017b5a3065b83e9d76f0080d6cb99c94c0c1" }
bindgen = { git = "https://github.com/rust-lang/rust-bindgen", rev = "7e9043497297e04e91ae76dfe0d2e7998828e529" }
bindgen-cli = { git = "https://github.com/rust-lang/rust-bindgen", rev = "7e9043497297e04e91ae76dfe0d2e7998828e529" }
cxx = { package = "cxx", git = "https://github.com/facebookexperimental/cxx.git", rev = "69a4f12f40d99284ebda58f33602ab60b70624d7" }
cxx-build = { package = "cxx-build", git = "https://github.com/facebookexperimental/cxx.git", rev = "69a4f12f40d99284ebda58f33602ab60b70624d7" }
graphql-parser = { git = "https://github.com/graphql-rust//graphql-parser", rev = "8d76425d83c40670570cc325f57c730262f07456" }
Expand Down

0 comments on commit c4f47e9

Please sign in to comment.