1 //! Access fields of a [`MaybeUninit`] 2 3 use std::{ 4 mem::MaybeUninit, 5 ops::{Deref, DerefMut}, 6 }; 7 8 pub struct MaybeUninitField<'a, T, U> { 9 parent: &'a mut MaybeUninit<T>, 10 child: *mut U, 11 } 12 13 impl<'a, T, U> MaybeUninitField<'a, T, U> { 14 #[doc(hidden)] 15 pub fn new(parent: &'a mut MaybeUninit<T>, child: *mut U) -> Self { 16 MaybeUninitField { parent, child } 17 } 18 19 /// Return a constant pointer to the containing object of the field. 20 /// 21 /// Because the `MaybeUninitField` remembers the containing object, 22 /// it is possible to use it in foreign APIs that initialize the 23 /// child. 24 pub fn parent(f: &Self) -> *const T { 25 f.parent.as_ptr() 26 } 27 28 /// Return a mutable pointer to the containing object. 29 /// 30 /// Because the `MaybeUninitField` remembers the containing object, 31 /// it is possible to use it in foreign APIs that initialize the 32 /// child. 33 pub fn parent_mut(f: &mut Self) -> *mut T { 34 f.parent.as_mut_ptr() 35 } 36 } 37 38 impl<'a, T, U> Deref for MaybeUninitField<'a, T, U> { 39 type Target = MaybeUninit<U>; 40 41 fn deref(&self) -> &MaybeUninit<U> { 42 // SAFETY: self.child was obtained by dereferencing a valid mutable 43 // reference; the content of the memory may be invalid or uninitialized 44 // but MaybeUninit<_> makes no assumption on it 45 unsafe { &*(self.child.cast()) } 46 } 47 } 48 49 impl<'a, T, U> DerefMut for MaybeUninitField<'a, T, U> { 50 fn deref_mut(&mut self) -> &mut MaybeUninit<U> { 51 // SAFETY: self.child was obtained by dereferencing a valid mutable 52 // reference; the content of the memory may be invalid or uninitialized 53 // but MaybeUninit<_> makes no assumption on it 54 unsafe { &mut *(self.child.cast()) } 55 } 56 } 57 58 /// ``` 59 /// #[derive(Debug)] 60 /// struct S { 61 /// x: u32, 62 /// y: u32, 63 /// } 64 /// 65 /// # use std::mem::MaybeUninit; 66 /// # use qemu_api::{assert_match, uninit_field_mut}; 67 /// 68 /// let mut s: MaybeUninit<S> = MaybeUninit::zeroed(); 69 /// uninit_field_mut!(s, x).write(5); 70 /// let s = unsafe { s.assume_init() }; 71 /// assert_match!(s, S { x: 5, y: 0 }); 72 /// ``` 73 #[macro_export] 74 macro_rules! uninit_field_mut { 75 ($container:expr, $($field:tt)+) => {{ 76 let container__: &mut ::std::mem::MaybeUninit<_> = &mut $container; 77 let container_ptr__ = container__.as_mut_ptr(); 78 79 // SAFETY: the container is not used directly, only through a MaybeUninit<>, 80 // so the safety is delegated to the caller and to final invocation of 81 // assume_init() 82 let target__ = unsafe { std::ptr::addr_of_mut!((*container_ptr__).$($field)+) }; 83 $crate::uninit::MaybeUninitField::new(container__, target__) 84 }}; 85 } 86