xref: /qemu/rust/qemu-api/src/uninit.rs (revision 43ba160cb4bbb193560eb0d2d7decc4b5fc599fe)
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)]
new(parent: &'a mut MaybeUninit<T>, child: *mut U) -> Self15     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.
parent(f: &Self) -> *const T24     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.
parent_mut(f: &mut Self) -> *mut T33     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 
deref(&self) -> &MaybeUninit<U>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> {
deref_mut(&mut self) -> &mut MaybeUninit<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