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