musli_zerocopy/stack/
array_stack.rs1use 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 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}