1#[cfg(feature = "alloc")]
2use alloc::vec::Vec;
3use core::{
4 borrow::Borrow,
5 fmt,
6 hash::{Hash, Hasher},
7 mem::MaybeUninit,
8 ops::{Deref, DerefMut},
9 slice,
10};
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub struct CapacityError;
14
15pub struct InlineArray<T, const N: usize> {
16 buf: [MaybeUninit<T>; N],
17 len: usize,
18}
19
20impl<T, const N: usize> InlineArray<T, N> {
21 #[inline]
22 pub const fn new() -> Self {
23 Self {
24 buf: [const { MaybeUninit::uninit() }; N],
25 len: 0,
26 }
27 }
28
29 #[inline]
30 pub const fn capacity(&self) -> usize {
31 N
32 }
33
34 #[inline]
35 pub const fn len(&self) -> usize {
36 self.len
37 }
38
39 #[inline]
40 pub const fn is_empty(&self) -> bool {
41 self.len == 0
42 }
43
44 #[inline]
45 pub const fn is_full(&self) -> bool {
46 self.len == N
47 }
48
49 #[inline]
50 pub fn as_slice(&self) -> &[T] {
51 unsafe { slice::from_raw_parts(self.buf.as_ptr().cast::<T>(), self.len) }
53 }
54
55 #[inline]
56 pub fn as_mut_slice(&mut self) -> &mut [T] {
57 unsafe { slice::from_raw_parts_mut(self.buf.as_mut_ptr().cast::<T>(), self.len) }
59 }
60
61 #[inline]
62 pub fn push(&mut self, value: T) -> Result<(), T> {
63 if self.len == N {
64 return Err(value);
65 }
66
67 self.buf[self.len].write(value);
68 self.len += 1;
69 Ok(())
70 }
71
72 #[inline]
73 pub fn pop(&mut self) -> Option<T> {
74 if self.len == 0 {
75 return None;
76 }
77
78 self.len -= 1;
79 Some(unsafe { self.buf[self.len].assume_init_read() })
81 }
82
83 #[inline]
84 pub fn clear(&mut self) {
85 self.truncate(0);
86 }
87
88 #[inline]
89 pub fn truncate(&mut self, new_len: usize) {
90 let new_len = new_len.min(self.len);
91 while self.len > new_len {
92 self.len -= 1;
93 unsafe { self.buf[self.len].assume_init_drop() };
95 }
96 }
97
98 #[inline]
99 pub fn try_extend<I>(&mut self, iter: I) -> Result<(), CapacityError>
100 where
101 I: IntoIterator<Item = T>,
102 {
103 for item in iter {
104 if self.push(item).is_err() {
105 return Err(CapacityError);
106 }
107 }
108
109 Ok(())
110 }
111
112 #[inline]
113 pub fn try_from_iter<I>(iter: I) -> Result<Self, CapacityError>
114 where
115 I: IntoIterator<Item = T>,
116 {
117 let mut out = Self::new();
118 out.try_extend(iter)?;
119 Ok(out)
120 }
121}
122
123impl<T, const N: usize> Default for InlineArray<T, N> {
124 #[inline]
125 fn default() -> Self {
126 Self::new()
127 }
128}
129
130impl<T, const N: usize> Drop for InlineArray<T, N> {
131 fn drop(&mut self) {
132 self.clear();
133 }
134}
135
136impl<T: Clone, const N: usize> Clone for InlineArray<T, N> {
137 fn clone(&self) -> Self {
138 let mut out = Self::new();
139 for item in self.as_slice() {
140 assert!(
141 out.push(item.clone()).is_ok(),
142 "stx::InlineArray clone capacity exceeded"
143 );
144 }
145 out
146 }
147}
148
149impl<T: fmt::Debug, const N: usize> fmt::Debug for InlineArray<T, N> {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 f.debug_list().entries(self.as_slice()).finish()
152 }
153}
154
155impl<T: PartialEq, const N: usize> PartialEq for InlineArray<T, N> {
156 fn eq(&self, other: &Self) -> bool {
157 self.as_slice() == other.as_slice()
158 }
159}
160
161impl<T: Eq, const N: usize> Eq for InlineArray<T, N> {}
162
163impl<T: PartialOrd, const N: usize> PartialOrd for InlineArray<T, N> {
164 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
165 self.as_slice().partial_cmp(other.as_slice())
166 }
167}
168
169impl<T: Ord, const N: usize> Ord for InlineArray<T, N> {
170 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
171 self.as_slice().cmp(other.as_slice())
172 }
173}
174
175impl<T: Hash, const N: usize> Hash for InlineArray<T, N> {
176 fn hash<H: Hasher>(&self, state: &mut H) {
177 self.as_slice().hash(state);
178 }
179}
180
181impl<T, const N: usize> Borrow<[T]> for InlineArray<T, N> {
182 fn borrow(&self) -> &[T] {
183 self.as_slice()
184 }
185}
186
187impl<T, const N: usize> AsRef<[T]> for InlineArray<T, N> {
188 fn as_ref(&self) -> &[T] {
189 self.as_slice()
190 }
191}
192
193impl<T, const N: usize> AsMut<[T]> for InlineArray<T, N> {
194 fn as_mut(&mut self) -> &mut [T] {
195 self.as_mut_slice()
196 }
197}
198
199impl<T, const N: usize> Deref for InlineArray<T, N> {
200 type Target = [T];
201
202 fn deref(&self) -> &Self::Target {
203 self.as_slice()
204 }
205}
206
207impl<T, const N: usize> DerefMut for InlineArray<T, N> {
208 fn deref_mut(&mut self) -> &mut Self::Target {
209 self.as_mut_slice()
210 }
211}
212
213impl<'a, T, const N: usize> IntoIterator for &'a InlineArray<T, N> {
214 type Item = &'a T;
215 type IntoIter = slice::Iter<'a, T>;
216
217 fn into_iter(self) -> Self::IntoIter {
218 self.as_slice().iter()
219 }
220}
221
222impl<'a, T, const N: usize> IntoIterator for &'a mut InlineArray<T, N> {
223 type Item = &'a mut T;
224 type IntoIter = slice::IterMut<'a, T>;
225
226 fn into_iter(self) -> Self::IntoIter {
227 self.as_mut_slice().iter_mut()
228 }
229}
230
231impl<T, const N: usize> Extend<T> for InlineArray<T, N> {
232 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
233 for item in iter {
234 assert!(
235 self.push(item).is_ok(),
236 "stx::InlineArray capacity exceeded"
237 );
238 }
239 }
240}
241
242impl<T, const N: usize> FromIterator<T> for InlineArray<T, N> {
243 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
244 let mut out = Self::new();
245 out.extend(iter);
246 out
247 }
248}
249
250impl<T: Clone, const N: usize> TryFrom<&[T]> for InlineArray<T, N> {
251 type Error = CapacityError;
252
253 fn try_from(slice: &[T]) -> Result<Self, Self::Error> {
254 Self::try_from_iter(slice.iter().cloned())
255 }
256}
257
258#[cfg(feature = "alloc")]
259impl<T, const N: usize> TryFrom<Vec<T>> for InlineArray<T, N> {
260 type Error = CapacityError;
261
262 fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
263 Self::try_from_iter(value)
264 }
265}
266
267#[cfg(test)]
268mod tests;