uninit_tools/
traits.rs

1use core::mem::MaybeUninit;
2
3use crate::wrappers::AssertInit;
4
5#[cfg(feature = "alloc")]
6use alloc::{boxed::Box, rc::Rc, string::String, sync::Arc, vec::Vec};
7
8/// A trait for mutable initializable slices, that provide access to all the data required for
9/// initialization, before the data can be assumed to be fully initialized.
10///
11/// # Safety
12///
13/// This trait is unsafe to implement since whatever slices are returned from the casts here,
14/// __must have the same length and point to the same memory as before__. This is to allow safer
15/// abstractions to assume that there are has not unexpectedly appeared additional items that must
16/// be initialized.
17pub unsafe trait Initialize {
18    type Item;
19
20    /// Retrieve an immutable slice pointing to possibly uninitialized memory. __This must be
21    /// exactly the same slice as the one from [`as_maybe_uninit_slice_mut`], or the trait
22    /// implementation as a whole, gets incorrect.__
23    ///
24    /// [`as_maybe_uninit_slice_mut`]: Self::as_maybe_uninit_slice_mut
25    fn as_maybe_uninit_slice(&self) -> &[MaybeUninit<Self::Item>];
26
27    /// Retrieve a mutable slice pointing to possibly uninitialized memory. __This must always
28    /// point to the same slice as with previous invocations__.
29    ///
30    /// # Safety
31    ///
32    /// The caller must not use the resulting slice to de-initialize the data.
33    unsafe fn as_maybe_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<Self::Item>];
34}
35
36/// A trait for slices (or owned memory) that contain possibly uninitialized slices themselves.
37/// That is, the [`Initialize`] trait but for singly-indirect slices.
38///
39/// # Safety
40///
41/// For this trait to be implemented correctly, [`as_maybe_uninit_vectors`] and
42/// [`as_maybe_uninit_vectors_mut`] must always return the same slices (albeit with different
43/// aliasing rules as they take `&self` and `&mut self` respectively).
44///
45/// [`as_maybe_uninit_vectors`]: InitializeVectored::as_maybe_uninit_vectors
46/// [`as_maybe_uninit_vectors_mut`]: InitializeVectored::as_maybe_uninit_vectors_mut
47pub unsafe trait InitializeVectored {
48    /// The possibly uninitialized vector type, which must implement [`Initialize`]. Note that this
49    /// does not necessarily need to deref into [`MaybeUninit<Item>`], but can be anything that is
50    /// convertible to it.
51    type UninitVector: Initialize;
52
53    /// Get the uninitialized version of all vectors. This slice must always be exactly equal to
54    /// the slice returned by
55    /// [`as_maybe_uninit_vectors_mut`](InitializeVectored::as_maybe_uninit_vectors_mut), except
56    /// being borrowed differently, or the trait is unsoundly implemented.
57    ///
58    /// [`as_maybe_uninit_slice_mut`]: InitializeVectored::as_maybe_uninit_slice_mut
59    fn as_maybe_uninit_vectors(&self) -> &[Self::UninitVector];
60
61    /// Get the uninitialized version of all vectors, mutably. This slice must always be exactly
62    /// equal to the slice returned by [`as_maybe_uninit_vectors`](Self::as_maybe_uninit_vectors),
63    /// or the trait is unsoundly implemented.
64    ///
65    /// # Safety
66    ///
67    /// For the user of this trait, the resulting slice returned from this method _must not_ be
68    /// used to de-initialize the vectors by overwriting their contents with
69    /// [`MaybeUninit::uninit`] if they were already initialized.
70    ///
71    /// [`as_maybe_uninit_slice`]: InitializeVectored::as_maybe_uninit_slice
72    unsafe fn as_maybe_uninit_vectors_mut(&mut self) -> &mut [Self::UninitVector];
73}
74pub trait InitializeExt: private2::Sealed + Initialize + Sized {
75    /// Assume that the type is already initialized. This is equivalent of calling
76    /// [`AssertInit::new_unchecked`].
77    ///
78    /// # Safety
79    ///
80    /// The initialization invariant must be upheld for this to be safe.
81    unsafe fn assume_init(self) -> AssertInit<Self> {
82        AssertInit::new_unchecked(self)
83    }
84}
85mod private2 {
86    pub trait Sealed {}
87}
88mod private3 {
89    pub trait Sealed {}
90}
91mod private4 {
92    pub trait Sealed {}
93}
94mod private5 {
95    pub trait Sealed {}
96}
97
98impl<T> private2::Sealed for T where T: Initialize {}
99impl<T> InitializeExt for T where T: Initialize {}
100
101unsafe impl<'a, T> Initialize for &'a mut [MaybeUninit<T>] {
102    type Item = T;
103
104    #[inline]
105    fn as_maybe_uninit_slice(&self) -> &[MaybeUninit<T>] {
106        self
107    }
108    #[inline]
109    unsafe fn as_maybe_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<T>] {
110        self
111    }
112}
113impl<'a, T> From<AssertInit<&'a mut [MaybeUninit<T>]>> for &'a mut [T] {
114    #[inline]
115    fn from(init_slice: AssertInit<&'a mut [MaybeUninit<T>]>) -> &'a mut [T] {
116        unsafe { crate::cast_uninit_to_init_slice_mut(init_slice.into_inner()) }
117    }
118}
119/*unsafe impl<T> InitializeVectored for T
120where
121    T: Initialize,
122{
123    type UninitVector = Self;
124
125    #[inline]
126    fn as_maybe_uninit_vectors(&self) -> &[Self::UninitVector] {
127        core::slice::from_ref(self)
128    }
129    #[inline]
130    unsafe fn as_maybe_uninit_vectors_mut(&mut self) -> &mut [Self::UninitVector] {
131        core::slice::from_mut(self)
132    }
133}*/
134unsafe impl<'a, 'b, T> InitializeVectored for &'a mut [&'b mut [MaybeUninit<T>]] {
135    type UninitVector = &'b mut [MaybeUninit<T>];
136
137    fn as_maybe_uninit_vectors(&self) -> &[Self::UninitVector] {
138        self
139    }
140    unsafe fn as_maybe_uninit_vectors_mut(&mut self) -> &mut [Self::UninitVector] {
141        self
142    }
143}
144#[cfg(feature = "alloc")]
145unsafe impl<T> Initialize for Box<[MaybeUninit<T>]> {
146    type Item = T;
147
148    #[inline]
149    fn as_maybe_uninit_slice(&self) -> &[MaybeUninit<T>] {
150        self
151    }
152    #[inline]
153    unsafe fn as_maybe_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<T>] {
154        self
155    }
156}
157#[cfg(feature = "alloc")]
158impl<T> From<AssertInit<Box<[MaybeUninit<T>]>>> for Box<[T]> {
159    #[inline]
160    fn from(init_box: AssertInit<Box<[MaybeUninit<T>]>>) -> Box<[T]> {
161        #[cfg(feature = "nightly")]
162        unsafe {
163            #[forbid(unconditional_recursion)]
164            Box::<[MaybeUninit<T>]>::assume_init(init_box.into_inner())
165        }
166        #[cfg(not(feature = "nightly"))]
167        unsafe {
168            let slice_ptr = Box::into_raw(init_box.into_inner());
169            Box::from_raw(crate::cast_uninit_to_init_slice_mut(&mut *slice_ptr))
170        }
171    }
172}
173/*
174#[cfg(feature = "alloc")]
175unsafe impl Initialize for Vec<Item> {
176    #[inline]
177    fn as_maybe_uninit_slice(&self) -> &[MaybeUninit<u8>] {
178        crate::cast_init_to_uninit_slice(&*self)
179    }
180    #[inline]
181    unsafe fn as_maybe_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<u8>] {
182        // TODO: Give the whole allocation, and not just the length set? With MaybeUninit, calling
183        // set_len is safe.
184        crate::cast_init_to_uninit_slice_mut(&mut *self)
185    }
186}
187#[cfg(feature = "alloc")]
188unsafe impl Initialize for Vec<MaybeUninit<u8>> {
189    #[inline]
190    fn as_maybe_uninit_slice(&self) -> &[MaybeUninit<u8>] {
191        &*self
192    }
193    #[inline]
194    unsafe fn as_maybe_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<u8>] {
195        &mut *self
196    }
197}*/
198#[cfg(feature = "alloc")]
199impl<T> From<AssertInit<Vec<MaybeUninit<T>>>> for Vec<T> {
200    #[inline]
201    fn from(init_vec: AssertInit<Vec<MaybeUninit<T>>>) -> Vec<T> {
202        unsafe {
203            let mut vec = init_vec.into_inner();
204            //let (ptr, cap, len) = Vec::into_raw_parts(self);
205
206            let (ptr, cap, len) = {
207                let ptr = vec.as_mut_ptr();
208                let cap = vec.capacity();
209                let len = vec.len();
210
211                core::mem::forget(vec);
212
213                (ptr, cap, len)
214            };
215
216            Vec::from_raw_parts(ptr as *mut T, cap, len)
217        }
218    }
219}
220unsafe impl<T, const N: usize> Initialize for [MaybeUninit<T>; N] {
221    type Item = T;
222
223    #[inline]
224    fn as_maybe_uninit_slice(&self) -> &[MaybeUninit<T>] {
225        self
226    }
227    #[inline]
228    unsafe fn as_maybe_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<T>] {
229        self
230    }
231}
232impl<T, const N: usize> From<AssertInit<[MaybeUninit<T>; N]>> for [T; N] {
233    #[inline]
234    fn from(init: AssertInit<[MaybeUninit<T>; N]>) -> [T; N] {
235        #[cfg(feature = "nightly")]
236        unsafe {
237            MaybeUninit::array_assume_init(init.into_inner())
238        }
239        #[cfg(not(feature = "nightly"))]
240        unsafe {
241            let inner = init.into_inner();
242            let init: [T; N] = core::mem::transmute_copy(&inner);
243            init
244        }
245    }
246}
247
248/// A marker trait for implementations of [`Deref`](core::ops::Deref) that come with the additional
249/// guarantee that:
250///
251/// 1. The [`Deref::deref`] method will always return a slice with the same length, if the
252///    dereference target happens to a slice (`[T]`);
253/// 2. The [`DerefMut::deref_mut`] method, like [`Deref::deref`] will also always return a slice
254///    with the same length, and that it cannot change the length in any way when calling this
255///    trait method;
256/// 3. The target slice must always point to the same memory, although the address is allowed to
257///    change. In other words, any modifications to the target type, must be visible when calling
258///    the dereference methods again.
259///
260/// This is implemented for most of the familiar types in the standard library, e.g. [`Box`],
261/// [`Vec`], [`Ref`], etc.
262///
263/// This comes with some exceptions: for example do note that this only affects the [`Deref`] and
264/// [`DerefMut`] trait methods. There can still be ways to modify the length of the slice, either
265/// via interior mutability or via mutable references, accessible to safe code, so long as this
266/// is not in the dereference traits.
267///
268/// The aim of this trait is to force that when using whatever slice a [`BufferInitializer`] backs,
269/// it can be confident that the initializedness counter it stores will always be equal to the
270/// total length when the initializer is full. A [`Deref`] implementation that lacks the guarantee
271/// of this trait, would cause Undefined Behavior in the very building blocks of this library,
272/// otherwise.
273///
274/// Note that this is also fully orthogonal to `StableDeref`. So long as [`BufferInitializer`] can
275/// make assumptions about the length always being correct, the actual address of the memory is of
276/// no importance. However, implementing `StableDeref` means that invariant 3 is always upheld, but
277/// it is not clear at the moment whether that also applies to invariant 1 and 2.
278pub unsafe trait TrustedDeref: core::ops::Deref {}
279
280// TODO: Respect the allocator type of must liballoc collections, at least under #[cfg(feature =
281// "nightly")].
282
283// SAFETY: Deref for references is always a no-op, and always returns `self`. Unless the caller
284// changes the length of it beforehand, nothing bad will happen.
285unsafe impl<'a, T: ?Sized> TrustedDeref for &'a T {}
286
287// SAFETY: DerefMut for references is always a no-op.
288unsafe impl<'a, T: ?Sized> TrustedDeref for &'a mut T {}
289
290// SAFETY: The resulting slice is determined by the internal `len` field of the vector. The
291// dereference impls will not change this.
292#[cfg(feature = "alloc")]
293unsafe impl<T> TrustedDeref for Vec<T> {}
294
295// SAFETY: Deref and DerefMut are implemented as a raw pointer dereference by Box. No side effects.
296#[cfg(feature = "alloc")]
297unsafe impl<T: ?Sized> TrustedDeref for Box<T> {}
298
299// SAFETY: Arc is not particularly interesting as it cannot implement DerefMut, but it still
300// upholds the guarantee for Deref.
301#[cfg(feature = "alloc")]
302unsafe impl<T: ?Sized> TrustedDeref for Arc<T> {}
303
304// SAFETY: Same goes for Rc.
305#[cfg(feature = "alloc")]
306unsafe impl<T: ?Sized> TrustedDeref for Rc<T> {}
307
308// SAFETY: While RefCell allows inner types to utilize interior mutability, the actual RAII guard
309// will not do anything wrong.
310unsafe impl<'a, T: ?Sized> TrustedDeref for core::cell::Ref<'a, T> {}
311
312// SAFETY: Same goes for RefMut.
313unsafe impl<'a, T: ?Sized> TrustedDeref for core::cell::RefMut<'a, T> {}
314
315// SAFETY: Same goes for all lock guards.
316#[cfg(feature = "std")]
317unsafe impl<'a, T: ?Sized> TrustedDeref for std::sync::MutexGuard<'a, T> {}
318
319#[cfg(feature = "std")]
320unsafe impl<'a, T: ?Sized> TrustedDeref for std::sync::RwLockReadGuard<'a, T> {}
321
322#[cfg(feature = "std")]
323unsafe impl<'a, T: ?Sized> TrustedDeref for std::sync::RwLockWriteGuard<'a, T> {}
324
325#[cfg(feature = "alloc")]
326unsafe impl TrustedDeref for String {}
327
328// TODO: These are correct, right? Explain why.
329#[cfg(feature = "std")]
330unsafe impl TrustedDeref for std::ffi::CString {}
331#[cfg(feature = "std")]
332unsafe impl TrustedDeref for std::ffi::OsString {}
333#[cfg(feature = "std")]
334unsafe impl TrustedDeref for std::path::PathBuf {}
335
336// SAFETY: As Pin is merely a thin wrapper that in a way works like StableDeref, it will not have
337// any side effects.
338unsafe impl<T: core::ops::Deref> TrustedDeref for core::pin::Pin<T> {}
339
340// SAFETY: While Cow is allowed to change its Deref address, as it will copy when made mutable, its
341// Deref impl will only match the enum and propagate the dereference.
342#[cfg(feature = "alloc")]
343unsafe impl<'a, T: alloc::borrow::ToOwned> TrustedDeref for alloc::borrow::Cow<'a, T> {}
344
345// TODO: binary_heap PeekMut, Lazy, VaList, ManuallyDrop, AssertUnwindSafe, SyncLazy, std ioslices.
346
347/// A marker trait which indicates that two different implementations of [`Initialize`] have the
348/// same memory layout, and behave equivalently with respect to their implementations of
349/// [`Initialize`] and [`AssertInit`].
350///
351/// A usecase for this, is e.g. if you need [`InitializeVectored`]`<Item = IoSliceMut>` for system
352/// call ABI reasons, but you have a different type which still has the same layout, e.g.
353/// [`SingleVector`](crate::wrappers::SingleVector)`<`[`AsUninit`](crate::wrappers::AsUninit)`<IoSliceMut>>`.
354/// In general, it also allows changing the inner T, while still tracking the initializedness
355/// properly. For single-buffer I/O, this allows converting between any [`Equivalent`] types, where
356/// for vectored I/O, it allows a more restricted type of conversion, where they also need to be
357/// slice-castable.
358pub unsafe trait Equivalent<T>
359where
360    T: Initialize,
361    Self: Initialize<Item = <T as Initialize>::Item>,
362{
363}