Skip to main content

compio_buf/
uninit.rs

1use std::mem::MaybeUninit;
2
3use crate::*;
4
5/// A [`Slice`] that only exposes uninitialized bytes.
6///
7/// [`Uninit`] can be created with [`IoBufMutExt::uninit`].
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct Uninit<T>(Slice<T>);
10
11impl<T: IoBufMut> Uninit<T> {
12    pub(crate) fn new(buffer: T) -> Self {
13        let len = buffer.buf_len();
14        Self(buffer.slice(len..))
15    }
16}
17
18impl<T> Uninit<T> {
19    /// Offset in the underlying buffer at which uninitialized bytes starts.
20    pub fn begin(&self) -> usize {
21        self.0.begin()
22    }
23
24    /// Gets a reference to the underlying buffer.
25    ///
26    /// This method escapes the slice's view.
27    pub fn as_inner(&self) -> &T {
28        self.0.as_inner()
29    }
30
31    /// Gets a mutable reference to the underlying buffer.
32    ///
33    /// This method escapes the slice's view.
34    pub fn as_inner_mut(&mut self) -> &mut T {
35        self.0.as_inner_mut()
36    }
37}
38
39impl<T: IoBuf> IoBuf for Uninit<T> {
40    fn as_init(&self) -> &[u8] {
41        self.0.as_init() // this is always &[] but we can't return &[] since the pointer will be different
42    }
43}
44
45impl<T: IoBufMut> IoBufMut for Uninit<T> {
46    unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
47        let len = (*self).buf_len();
48        // SAFETY: The initialized prefix `..len` is sliced off.
49        let slice = unsafe { self.0.as_uninit() };
50        &mut slice[len..]
51    }
52
53    fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
54        IoBufMut::reserve(self.0.as_inner_mut(), len)
55    }
56
57    fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
58        IoBufMut::reserve_exact(self.0.as_inner_mut(), len)
59    }
60}
61
62impl<T: SetLen + IoBuf> SetLen for Uninit<T> {
63    unsafe fn set_len(&mut self, len: usize) {
64        let begin = self.0.begin() + len;
65        unsafe {
66            self.0.set_len(len);
67        }
68        // Re-anchor the view, otherwise `as_init` and `as_uninit` would start
69        // at different offsets.
70        // SAFETY: `begin` is the new length of the underlying view.
71        unsafe {
72            self.0.set_begin_unchecked(begin);
73        }
74    }
75}
76
77impl<T> IntoInner for Uninit<T> {
78    type Inner = T;
79
80    fn into_inner(self) -> Self::Inner {
81        self.0.into_inner()
82    }
83}