Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
third-party/rust: bindgen: patch in PR 2772
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