master
rs 85 lines 2.66 KB
Raw
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 const 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 const 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 const fn parent_mut(f: &mut Self) -> *mut T {
34 f.parent.as_mut_ptr()
35 }
36 }
37
38 impl<T, U> Deref for MaybeUninitField<'_, 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<T, U> DerefMut for MaybeUninitField<'_, 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 common::{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 }