1use core::fmt::{Debug, Formatter};
2use core::mem::MaybeUninit;
3use core::ops::Index;
4use core::ptr;
5
6use crate::ParseError;
7
8#[derive(Debug, Clone)]
10pub struct InlineVec<T, const N: usize>(InlineVecInner<T, N>);
11
12impl<T, const N: usize> InlineVec<T, N> {
13 #[inline]
15 pub(crate) fn new() -> Self {
16 Self(InlineVecInner::new())
17 }
18
19 #[inline]
21 pub fn len(&self) -> usize {
22 self.0.len()
23 }
24
25 #[inline]
27 pub fn is_empty(&self) -> bool {
28 self.len() == 0
29 }
30
31 #[inline]
33 pub fn is_heap_allocated(&self) -> bool {
34 self.0.is_heap_allocated()
35 }
36
37 #[inline]
41 pub fn inline_parts_mut(&mut self) -> Option<(&mut [MaybeUninit<T>; N], usize)> {
42 self.0.inline_parts_mut()
43 }
44
45 #[inline]
47 #[cfg(feature = "std")]
48 pub fn to_vec(&self) -> Vec<T>
49 where
50 T: Clone,
51 {
52 self.0.to_vec()
53 }
54
55 #[inline]
57 pub fn push(&mut self, value: T) -> Result<(), ParseError> {
58 self.0.push(value)
59 }
60
61 #[inline]
63 pub fn get(&self, index: usize) -> Option<&T> {
64 self.0.get(index)
65 }
66
67 #[inline]
69 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
70 self.0.get_mut(index)
71 }
72
73 #[inline]
75 pub fn last(&self) -> Option<&T> {
76 self.as_slice().last()
77 }
78
79 #[inline]
81 pub fn pop(&mut self) -> Option<T> {
82 if self.is_empty() {
83 None
84 } else {
85 Some(self.remove(self.len() - 1))
86 }
87 }
88
89 #[inline]
94 pub fn remove(&mut self, index: usize) -> T {
95 self.0.remove(index)
96 }
97
98 #[inline]
100 pub fn iter(&self) -> InlineVecIter<'_, T, N> {
101 self.0.iter()
102 }
103
104 #[inline]
106 pub fn as_slice(&self) -> &[T] {
107 self.0.as_slice()
108 }
109
110 #[inline]
112 pub fn as_mut_slice(&mut self) -> &mut [T] {
113 self.0.as_mut_slice()
114 }
115}
116
117enum InlineVecInner<T, const N: usize> {
118 Inline {
119 len: usize,
120 data: [MaybeUninit<T>; N],
121 },
122 #[cfg(feature = "std")]
123 Heap(Vec<T>),
124}
125
126impl<T, const N: usize> Debug for InlineVecInner<T, N>
127where
128 T: Debug,
129{
130 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
131 write!(f, "InlineVec<{} items>", self.len())
132 }
133}
134
135impl<T, const N: usize> Clone for InlineVecInner<T, N>
136where
137 T: Clone,
138{
139 fn clone(&self) -> Self {
140 match self {
141 #[cfg(feature = "std")]
142 Self::Heap(m) => Self::Heap(m.clone()),
143 Self::Inline { len, data } => {
144 let mut new_data = super::uninit_array();
145
146 let iter = data.iter().take(*len).enumerate();
147
148 for (idx, element) in iter {
149 let element = unsafe { &*element.as_ptr() };
150 new_data[idx] = MaybeUninit::new(T::clone(element));
151 }
152
153 Self::Inline {
154 len: *len,
155 data: new_data,
156 }
157 }
158 }
159 }
160}
161
162impl<T, const N: usize> InlineVecInner<T, N> {
163 #[inline]
164 pub(crate) fn new() -> Self {
165 Self::Inline {
166 len: 0,
167 data: super::uninit_array(),
168 }
169 }
170
171 pub fn as_slice(&self) -> &[T] {
172 match self {
173 Self::Inline { len, data } => unsafe {
174 core::slice::from_raw_parts(data.as_ptr() as *const T, *len)
175 },
176 #[cfg(feature = "std")]
177 Self::Heap(v) => v.as_slice(),
178 }
179 }
180
181 pub fn as_mut_slice(&mut self) -> &mut [T] {
182 match self {
183 Self::Inline { len, data } => unsafe {
184 core::slice::from_raw_parts_mut(data.as_mut_ptr() as *mut T, *len)
185 },
186 #[cfg(feature = "std")]
187 Self::Heap(v) => v.as_mut_slice(),
188 }
189 }
190
191 #[inline]
192 pub fn inline_parts_mut(&mut self) -> Option<(&mut [MaybeUninit<T>; N], usize)> {
193 match self {
194 #[cfg(feature = "std")]
195 Self::Heap(_) => None,
196 Self::Inline { len, data } => Some((data, *len)),
197 }
198 }
199
200 #[cfg(feature = "std")]
201 pub fn to_vec(&self) -> Vec<T>
202 where
203 T: Clone,
204 {
205 match &self {
206 InlineVecInner::Heap(m) => m.to_vec(),
207 InlineVecInner::Inline { len, data } => {
208 let mut new_data = Vec::with_capacity(*len);
209
210 let iter = data.iter().take(*len);
211
212 for element in iter {
213 new_data.push(unsafe { T::clone(&*element.as_ptr()) });
214 }
215
216 new_data
217 }
218 }
219 }
220
221 #[inline]
222 pub fn iter(&self) -> InlineVecIter<'_, T, N> {
223 InlineVecIter { idx: 0, vec: self }
224 }
225
226 #[inline]
227 pub fn len(&self) -> usize {
228 match self {
229 Self::Inline { len, .. } => *len,
230 #[cfg(feature = "std")]
231 Self::Heap(vec) => vec.len(),
232 }
233 }
234
235 pub fn get(&self, idx: usize) -> Option<&T> {
236 match self {
237 Self::Inline { data, len } => {
238 if idx < *len {
239 Some(unsafe { &*data.get_unchecked(idx).as_ptr() })
240 } else {
241 None
242 }
243 }
244 #[cfg(feature = "std")]
245 Self::Heap(vec) => vec.get(idx),
246 }
247 }
248
249 pub fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
250 match self {
251 Self::Inline { data, len } => {
252 if idx < *len {
253 Some(unsafe { &mut *data.get_unchecked_mut(idx).as_mut_ptr() })
254 } else {
255 None
256 }
257 }
258 #[cfg(feature = "std")]
259 Self::Heap(vec) => vec.get_mut(idx),
260 }
261 }
262
263 pub fn remove(&mut self, idx: usize) -> T {
264 match self {
265 Self::Inline { data, len } => {
266 assert!(idx < *len);
267
268 let element = unsafe {
271 core::mem::replace(data.get_unchecked_mut(idx), MaybeUninit::uninit())
272 };
273
274 for i in idx + 1..*len {
275 data.swap(i, i - 1);
277 }
278
279 *len -= 1;
280
281 unsafe { element.assume_init() }
283 }
284 #[cfg(feature = "std")]
285 Self::Heap(h) => h.remove(idx),
286 }
287 }
288
289 pub fn push(&mut self, value: T) -> Result<(), ParseError> {
290 let (array, len) = match self {
291 Self::Inline { data, len } => (data, len),
292 #[cfg(feature = "std")]
293 Self::Heap(vec) => {
294 vec.push(value);
295 return Ok(());
296 }
297 };
298
299 if *len >= N {
300 #[cfg(not(feature = "std"))]
301 {
302 return Err(ParseError::ChildCapacityExceeded);
303 }
304
305 #[cfg(feature = "std")]
306 {
307 let mut vec = Vec::with_capacity(*len + 1);
308
309 for element in array.iter_mut().take(*len) {
311 let element = core::mem::replace(element, MaybeUninit::uninit());
312
313 vec.push(unsafe { element.assume_init() });
314 }
315
316 vec.push(value);
318 let new_heap = InlineVecInner::Heap(vec);
319
320 unsafe { ptr::write(self, new_heap) };
322 }
323 } else {
324 array[*len].write(value);
325 *len += 1;
326 }
327
328 Ok(())
329 }
330
331 #[inline]
332 pub fn is_heap_allocated(&self) -> bool {
333 #[cfg(feature = "std")]
334 {
335 matches!(self, Self::Heap(_))
336 }
337 #[cfg(not(feature = "std"))]
338 {
339 false
340 }
341 }
342}
343
344impl<T, const N: usize> Index<usize> for InlineVec<T, N> {
345 type Output = T;
346
347 fn index(&self, idx: usize) -> &Self::Output {
348 self.0.get(idx).expect("index out of bounds")
349 }
350}
351
352pub struct InlineVecIter<'a, T, const N: usize> {
354 vec: &'a InlineVecInner<T, N>,
355 idx: usize,
356}
357
358impl<'a, T, const N: usize> Iterator for InlineVecIter<'a, T, N> {
359 type Item = &'a T;
360
361 fn next(&mut self) -> Option<Self::Item> {
362 self.idx += 1;
363 self.vec.get(self.idx - 1)
364 }
365}
366
367impl<T, const N: usize> Drop for InlineVecInner<T, N> {
368 fn drop(&mut self) {
369 if let Some((data, len)) = self.inline_parts_mut() {
370 for element in data.iter_mut().take(len) {
371 unsafe { ptr::drop_in_place(element.as_mut_ptr()) };
372 }
373 }
374 }
375}
376
377#[cfg(all(test, feature = "std"))]
378mod tests {
379 #![allow(unused_must_use)]
380
381 use super::*;
382
383 #[test]
384 fn inlinevec_to_vec_stack() {
385 let mut x = InlineVec::<usize, 4>::new();
386
387 for i in 0..4 {
388 x.push(i * 2);
389 }
390
391 assert!(!x.is_heap_allocated());
392 assert_eq!(x.len(), 4);
393
394 let xx = x.to_vec();
395 assert_eq!(xx.as_slice(), &[0, 2, 4, 6]);
396
397 x.push(42);
398 assert!(x.is_heap_allocated());
399 assert_eq!(x.as_slice(), &[0, 2, 4, 6, 42]);
400 assert_eq!(x.get(4), Some(&42));
401
402 let xx = x.to_vec();
403 assert_eq!(xx.as_slice(), &[0, 2, 4, 6, 42]);
404 }
405
406 #[test]
407 fn inlinevec_to_vec_heap() {
408 let mut x = InlineVec::<String, 4>::new();
409
410 for i in 0..4u8 {
411 x.push(i.to_string());
412 }
413
414 assert!(!x.is_heap_allocated());
415 assert_eq!(x.len(), 4);
416
417 let xx = x.to_vec();
418 assert_eq!(xx.as_slice(), &["0", "1", "2", "3"]);
419
420 x.push("1337".into());
421 assert!(x.is_heap_allocated());
422 assert_eq!(x.as_slice(), &["0", "1", "2", "3", "1337"]);
423 assert_eq!(x.get(4).map(|x| &**x), Some("1337"));
424
425 let xx = x.to_vec();
426 assert_eq!(xx.as_slice(), &["0", "1", "2", "3", "1337"]);
427 }
428
429 #[test]
430 fn inlinevec_drop_stack() {
431 let mut x = InlineVec::<String, 4>::new();
432
433 for i in 0..3u8 {
434 x.push(i.to_string());
435 }
436
437 assert_eq!(x.as_slice(), &["0", "1", "2"]);
438 assert!(!x.is_heap_allocated());
439 }
440
441 #[test]
442 fn inlinehashmap_drop_heap() {
443 let mut x = InlineVec::<String, 4>::new();
444
445 for i in 0..8u8 {
446 x.push(i.to_string());
447 }
448
449 assert_eq!(x.as_slice(), &["0", "1", "2", "3", "4", "5", "6", "7"]);
450 assert!(x.is_heap_allocated());
451 }
452
453 #[test]
454 fn inlinevec_iter() {
455 let mut x = InlineVecInner::<usize, 2>::new();
456 x.push(13);
457 x.push(42);
458 x.push(17);
459 x.push(19);
460 let mut iter = x.iter();
461 assert_eq!(iter.next(), Some(&13));
462 assert_eq!(iter.next(), Some(&42));
463 assert_eq!(iter.next(), Some(&17));
464 assert_eq!(iter.next(), Some(&19));
465 assert_eq!(iter.next(), None);
466 }
467
468 #[test]
469 fn inlinevec_remove() {
470 let mut x = InlineVecInner::<usize, 4>::new();
471 x.push(789);
472 assert_eq!(x.len(), 1);
473 assert_eq!(x.get(0), Some(&789));
474 assert_eq!(x.remove(0), 789);
475 assert_eq!(x.len(), 0);
476
477 {
478 let mut xc = x.clone();
479 assert!(std::panic::catch_unwind(move || xc.remove(0)).is_err());
481 }
482
483 for i in 0..4 {
484 x.push(i * 2);
485 }
486
487 assert!(!x.is_heap_allocated());
488 assert_eq!(x.as_slice(), &[0, 2, 4, 6]);
489
490 assert_eq!(x.remove(2), 4);
491 assert_eq!(x.as_slice(), &[0, 2, 6]);
492
493 assert_eq!(x.remove(2), 6);
494 assert_eq!(x.as_slice(), &[0, 2]);
495
496 assert_eq!(x.remove(1), 2);
497 assert_eq!(x.as_slice(), &[0]);
498
499 assert_eq!(x.remove(0), 0);
500 assert_eq!(x.as_slice(), &[]);
501 assert!(!x.is_heap_allocated());
502
503 for i in 0..8 {
505 x.push(i * 2);
506 }
507 assert!(x.is_heap_allocated());
508 assert_eq!(x.as_slice(), &[0, 2, 4, 6, 8, 10, 12, 14]);
509
510 assert_eq!(x.remove(7), 14);
511 assert_eq!(x.remove(0), 0);
512 }
513
514 #[test]
515 fn inlinevec_remove_heap() {
516 let mut x = InlineVecInner::<String, 4>::new();
517 x.push("test".into());
518 assert_eq!(x.len(), 1);
519 assert_eq!(x.remove(0), "test");
520 assert_eq!(x.len(), 0);
521 }
522
523 #[test]
524 fn inlinevec() {
525 let mut x = InlineVecInner::<usize, 4>::new();
526 assert_eq!(x.len(), 0);
527 assert_eq!(x.get(0), None);
528 assert!(!x.is_heap_allocated());
529
530 x.push(1337);
531 assert_eq!(x.len(), 1);
532 assert_eq!(x.get(0), Some(&1337));
533 assert!(!x.is_heap_allocated());
534
535 for v in 0..3 {
536 x.push(v);
537 }
538
539 assert_eq!(x.len(), 4);
540
541 x.push(42);
543 assert_eq!(x.len(), 5);
544 assert!(x.is_heap_allocated());
545
546 assert_eq!(x.get(0), Some(&1337));
548
549 for v in 0..500 {
550 x.push(v);
551 }
552
553 assert_eq!(x.len(), 505);
554 assert!(x.is_heap_allocated());
555
556 assert_eq!(x.get(1337), None);
557
558 *x.get_mut(0).unwrap() = 444;
559 assert_eq!(x.get(0), Some(&444));
560 assert_eq!(x.get_mut(99999 ), None);
561 }
562
563 #[test]
564 fn inlinevec_as_slice() {
565 let mut x = InlineVecInner::<usize, 4>::new();
566 x.push(1337);
567 x.push(42);
568 x.push(17);
569 assert_eq!(x.as_slice(), &[1337, 42, 17]);
570 x.push(19);
571 x.push(34);
572 assert_eq!(x.as_slice(), &[1337, 42, 17, 19, 34]);
573 }
574}