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