From 1306b1163ce7de06af91db002229e56f52280a4e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 2 Apr 2024 13:49:46 -0700 Subject: [PATCH] third-party/rust: bindgen: patch in PR 2772 Summary: [PR 2772](https://github.com/rust-lang/rust-bindgen/pull/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 { 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 --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bc3914f65..473824a91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" }