musli_zerocopy/stack/
array_stack.rs

1use core::mem::MaybeUninit;
2use core::ptr;
3use core::slice;
4
5use super::Stack;
6
7pub(crate) struct ArrayStack<T, const N: usize> {
8    data: [MaybeUninit<T>; N],
9    len: usize,
10}
11
12impl<T, const N: usize> ArrayStack<T, N> {
13    const fn new() -> Self {
14        Self {
15            data: unsafe { MaybeUninit::uninit().assume_init() },
16            len: 0,
17        }
18    }
19
20    fn len(&self) -> usize {
21        self.len
22    }
23
24    fn clear(&mut self) {
25        self.truncate(0);
26    }
27
28    pub(crate) fn try_push(&mut self, value: T) -> bool {
29        if self.len == N {
30            return false;
31        }
32
33        unsafe {
34            self.as_mut_ptr().add(self.len).write(value);
35            self.len += 1;
36        }
37
38        true
39    }
40
41    pub(crate) fn pop(&mut self) -> Option<T> {
42        if self.len == 0 {
43            return None;
44        }
45
46        unsafe {
47            let new_len = self.len - 1;
48            self.len = new_len;
49            Some(ptr::read(self.as_ptr().add(new_len)))
50        }
51    }
52
53    fn truncate(&mut self, new_len: usize) {
54        // SAFETY: `len` defines the initialized length of the array vector.
55        unsafe {
56            let len = self.len();
57
58            if new_len < len {
59                self.len = new_len;
60                let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len);
61                ptr::drop_in_place(tail);
62            }
63        }
64    }
65
66    fn as_ptr(&self) -> *const T {
67        self.data.as_ptr() as _
68    }
69
70    fn as_mut_ptr(&mut self) -> *mut T {
71        self.data.as_mut_ptr() as _
72    }
73}
74
75impl<T, const N: usize> Drop for ArrayStack<T, N> {
76    #[inline]
77    fn drop(&mut self) {
78        self.clear();
79    }
80}
81
82impl<T, const N: usize> Stack<T> for ArrayStack<T, N> {
83    const CAPACITY: usize = N;
84
85    #[inline]
86    fn new() -> Self {
87        ArrayStack::new()
88    }
89
90    #[inline]
91    fn try_push(&mut self, value: T) -> bool {
92        ArrayStack::try_push(self, value)
93    }
94
95    #[inline]
96    fn pop(&mut self) -> Option<T> {
97        ArrayStack::pop(self)
98    }
99}