musli_core/internal/
fixed.rs

1use core::fmt;
2use core::mem::{self, ManuallyDrop, MaybeUninit};
3use core::ops::{Deref, DerefMut};
4use core::ptr;
5use core::slice;
6
7/// An error raised when we are at capacity.
8#[derive(Debug)]
9#[non_exhaustive]
10pub(crate) struct CapacityError;
11
12impl fmt::Display for CapacityError {
13    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14        f.write_str("Out of capacity when constructing array")
15    }
16}
17
18impl core::error::Error for CapacityError {}
19
20/// A fixed capacity vector allocated on the stack.
21pub(crate) struct FixedVec<T, const N: usize> {
22    data: [MaybeUninit<T>; N],
23    len: usize,
24}
25
26impl<T, const N: usize> FixedVec<T, N> {
27    /// Construct a new empty fixed vector.
28    pub(crate) const fn new() -> FixedVec<T, N> {
29        unsafe {
30            FixedVec {
31                data: MaybeUninit::uninit().assume_init(),
32                len: 0,
33            }
34        }
35    }
36
37    #[inline]
38    pub(crate) fn as_ptr(&self) -> *const T {
39        self.data.as_ptr() as *const T
40    }
41
42    #[inline]
43    pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
44        self.data.as_mut_ptr() as *mut T
45    }
46
47    #[inline]
48    pub(crate) fn as_slice(&self) -> &[T] {
49        unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
50    }
51
52    #[inline]
53    pub(crate) fn as_mut_slice(&mut self) -> &mut [T] {
54        unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
55    }
56
57    /// Try to push an element onto the fixed vector.
58    pub(crate) fn try_push(&mut self, element: T) -> Result<(), CapacityError> {
59        if self.len >= N {
60            return Err(CapacityError);
61        }
62
63        unsafe {
64            ptr::write(self.as_mut_ptr().wrapping_add(self.len), element);
65            self.len += 1;
66        }
67
68        Ok(())
69    }
70
71    pub(crate) fn clear(&mut self) {
72        if self.len == 0 {
73            return;
74        }
75
76        let len = mem::take(&mut self.len);
77
78        if mem::needs_drop::<T>() {
79            unsafe {
80                let tail = slice::from_raw_parts_mut(self.as_mut_ptr(), len);
81                ptr::drop_in_place(tail);
82            }
83        }
84    }
85
86    pub(crate) fn into_inner(self) -> [T; N] {
87        assert!(
88            self.len == N,
89            "into_inner: length mismatch, expected {N} but got {}",
90            self.len
91        );
92
93        // SAFETY: We've asserted that the length is initialized just above.
94        unsafe {
95            let this = ManuallyDrop::new(self);
96            ptr::read(this.data.as_ptr() as *const [T; N])
97        }
98    }
99}
100
101impl<T, const N: usize> Deref for FixedVec<T, N> {
102    type Target = [T];
103
104    #[inline]
105    fn deref(&self) -> &Self::Target {
106        self.as_slice()
107    }
108}
109
110impl<T, const N: usize> DerefMut for FixedVec<T, N> {
111    #[inline]
112    fn deref_mut(&mut self) -> &mut Self::Target {
113        self.as_mut_slice()
114    }
115}
116
117impl<T, const N: usize> Drop for FixedVec<T, N> {
118    #[inline]
119    fn drop(&mut self) {
120        self.clear()
121    }
122}