1use alloc::vec::Vec;
21use core::fmt;
22use core::ops::{Deref, DerefMut};
23
24pub struct InlineVec<T>(Repr<T>);
34
35#[derive(Clone)]
36enum Repr<T> {
37 Empty,
38 One(T),
39 Spilled(Vec<T>),
40}
41
42impl<T> InlineVec<T> {
43 pub const fn new() -> Self {
45 Self(Repr::Empty)
46 }
47
48 pub const fn one(value: T) -> Self {
50 Self(Repr::One(value))
51 }
52
53 #[cfg(test)]
55 pub(crate) fn spilled(&self) -> bool {
56 matches!(self.0, Repr::Spilled(_))
57 }
58
59 pub fn as_slice(&self) -> &[T] {
61 match &self.0 {
62 Repr::Empty => &[],
63 Repr::One(value) => core::slice::from_ref(value),
64 Repr::Spilled(values) => values,
65 }
66 }
67
68 pub fn as_mut_slice(&mut self) -> &mut [T] {
70 match &mut self.0 {
71 Repr::Empty => &mut [],
72 Repr::One(value) => core::slice::from_mut(value),
73 Repr::Spilled(values) => values,
74 }
75 }
76
77 pub fn push(&mut self, value: T) {
79 match &mut self.0 {
80 Repr::Empty => self.0 = Repr::One(value),
81 Repr::Spilled(values) => values.push(value),
82 Repr::One(_) => {
83 let Repr::One(first) = core::mem::replace(&mut self.0, Repr::Empty) else {
84 unreachable!("the arm above matched One")
85 };
86 self.0 = Repr::Spilled(alloc::vec![first, value]);
87 }
88 }
89 }
90
91 pub fn pop(&mut self) -> Option<T> {
93 match &mut self.0 {
94 Repr::Empty => None,
95 Repr::Spilled(values) => values.pop(),
96 Repr::One(_) => match core::mem::replace(&mut self.0, Repr::Empty) {
97 Repr::One(value) => Some(value),
98 _ => unreachable!("the arm above matched One"),
99 },
100 }
101 }
102
103 pub fn retain(&mut self, mut keep: impl FnMut(&T) -> bool) {
105 match &mut self.0 {
106 Repr::Empty => {}
107 Repr::Spilled(values) => values.retain(|value| keep(value)),
108 Repr::One(value) => {
109 if !keep(value) {
110 self.0 = Repr::Empty;
111 }
112 }
113 }
114 }
115
116 pub fn clear(&mut self) {
118 self.0 = Repr::Empty;
119 }
120
121 pub(crate) fn into_vec(self) -> Vec<T> {
123 match self.0 {
124 Repr::Empty => Vec::new(),
125 Repr::One(value) => alloc::vec![value],
126 Repr::Spilled(values) => values,
127 }
128 }
129}
130
131impl<T> Default for InlineVec<T> {
132 fn default() -> Self {
133 Self::new()
134 }
135}
136
137impl<T: Clone> Clone for InlineVec<T> {
138 fn clone(&self) -> Self {
139 Self(self.0.clone())
140 }
141}
142
143impl<T> Deref for InlineVec<T> {
144 type Target = [T];
145
146 fn deref(&self) -> &[T] {
147 self.as_slice()
148 }
149}
150
151impl<T> DerefMut for InlineVec<T> {
152 fn deref_mut(&mut self) -> &mut [T] {
153 self.as_mut_slice()
154 }
155}
156
157impl<T: PartialEq> PartialEq for InlineVec<T> {
160 fn eq(&self, other: &Self) -> bool {
161 self.as_slice() == other.as_slice()
162 }
163}
164
165impl<T: Eq> Eq for InlineVec<T> {}
166
167impl<T: PartialEq<U>, U, const N: usize> PartialEq<[U; N]> for InlineVec<T> {
168 fn eq(&self, other: &[U; N]) -> bool {
169 self.as_slice() == other.as_slice()
170 }
171}
172
173impl<T: PartialEq<U>, U> PartialEq<[U]> for InlineVec<T> {
174 fn eq(&self, other: &[U]) -> bool {
175 self.as_slice() == other
176 }
177}
178
179impl<T: PartialEq<U>, U> PartialEq<Vec<U>> for InlineVec<T> {
180 fn eq(&self, other: &Vec<U>) -> bool {
181 self.as_slice() == other.as_slice()
182 }
183}
184
185impl<T: fmt::Debug> fmt::Debug for InlineVec<T> {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 self.as_slice().fmt(f)
188 }
189}
190
191impl<T> From<Vec<T>> for InlineVec<T> {
192 fn from(values: Vec<T>) -> Self {
194 let mut values = values;
195 match values.len() {
196 0 => Self::new(),
197 1 => Self(Repr::One(values.pop().expect("length is one"))),
198 _ => Self(Repr::Spilled(values)),
199 }
200 }
201}
202
203impl<T, const N: usize> From<[T; N]> for InlineVec<T> {
204 fn from(values: [T; N]) -> Self {
205 values.into_iter().collect()
206 }
207}
208
209impl<T> From<InlineVec<T>> for Vec<T> {
210 fn from(inline: InlineVec<T>) -> Self {
211 inline.into_vec()
212 }
213}
214
215impl<T> FromIterator<T> for InlineVec<T> {
216 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
217 let mut iter = iter.into_iter();
218 let Some(first) = iter.next() else {
219 return Self::new();
220 };
221 let Some(second) = iter.next() else {
222 return Self(Repr::One(first));
223 };
224 let mut values = Vec::with_capacity(iter.size_hint().0 + 2);
225 values.push(first);
226 values.push(second);
227 values.extend(iter);
228 Self(Repr::Spilled(values))
229 }
230}
231
232impl<T> Extend<T> for InlineVec<T> {
233 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
234 for value in iter {
235 self.push(value);
236 }
237 }
238}
239
240pub enum IntoIter<T> {
242 #[doc(hidden)]
243 Inline(core::option::IntoIter<T>),
244 #[doc(hidden)]
245 Spilled(alloc::vec::IntoIter<T>),
246}
247
248impl<T> Iterator for IntoIter<T> {
249 type Item = T;
250
251 fn next(&mut self) -> Option<T> {
252 match self {
253 Self::Inline(iter) => iter.next(),
254 Self::Spilled(iter) => iter.next(),
255 }
256 }
257
258 fn size_hint(&self) -> (usize, Option<usize>) {
259 match self {
260 Self::Inline(iter) => iter.size_hint(),
261 Self::Spilled(iter) => iter.size_hint(),
262 }
263 }
264}
265
266impl<T> ExactSizeIterator for IntoIter<T> {}
267
268impl<T> IntoIterator for InlineVec<T> {
269 type Item = T;
270 type IntoIter = IntoIter<T>;
271
272 fn into_iter(self) -> IntoIter<T> {
273 match self.0 {
274 Repr::Empty => IntoIter::Inline(None.into_iter()),
275 Repr::One(value) => IntoIter::Inline(Some(value).into_iter()),
276 Repr::Spilled(values) => IntoIter::Spilled(values.into_iter()),
277 }
278 }
279}
280
281impl<'a, T> IntoIterator for &'a InlineVec<T> {
282 type Item = &'a T;
283 type IntoIter = core::slice::Iter<'a, T>;
284
285 fn into_iter(self) -> core::slice::Iter<'a, T> {
286 self.as_slice().iter()
287 }
288}
289
290impl<'a, T> IntoIterator for &'a mut InlineVec<T> {
291 type Item = &'a mut T;
292 type IntoIter = core::slice::IterMut<'a, T>;
293
294 fn into_iter(self) -> core::slice::IterMut<'a, T> {
295 self.as_mut_slice().iter_mut()
296 }
297}
298
299#[cfg(test)]
300mod tests {
301 use super::*;
302 use alloc::vec;
303
304 #[test]
305 fn an_empty_value_holds_nothing_inline() {
306 let empty = InlineVec::<u32>::new();
307 assert!(empty.is_empty());
308 assert_eq!(empty.len(), 0);
309 assert!(!empty.spilled());
310 assert_eq!(empty.as_slice(), &[] as &[u32]);
311 }
312
313 #[test]
315 fn a_single_element_stays_inline() {
316 let mut one = InlineVec::new();
317 one.push(7u32);
318 assert!(!one.spilled(), "one element must not allocate");
319 assert_eq!(one.as_slice(), [7]);
320 assert_eq!(InlineVec::one(7u32).as_slice(), [7]);
321 }
322
323 #[test]
324 fn a_second_element_spills_to_the_heap_in_order() {
325 let mut many = InlineVec::new();
326 many.push(1u32);
327 many.push(2);
328 many.push(3);
329 assert!(many.spilled());
330 assert_eq!(many.as_slice(), [1, 2, 3]);
331 }
332
333 #[test]
334 fn collecting_picks_the_representation_from_the_length() {
335 let none: InlineVec<u32> = core::iter::empty().collect();
336 assert!(none.is_empty() && !none.spilled());
337
338 let one: InlineVec<u32> = core::iter::once(5).collect();
339 assert!(!one.spilled());
340 assert_eq!(one.as_slice(), [5]);
341
342 let many: InlineVec<u32> = (0..4).collect();
343 assert!(many.spilled());
344 assert_eq!(many.as_slice(), [0, 1, 2, 3]);
345 }
346
347 #[test]
350 fn a_short_vec_gives_up_its_allocation() {
351 assert!(!InlineVec::from(vec![9u32]).spilled());
352 assert!(InlineVec::from(vec![9u32, 10]).spilled());
353 assert!(!InlineVec::<u32>::from(vec![]).spilled());
354 assert_eq!(InlineVec::from(vec![9u32, 10]).as_slice(), [9, 10]);
355 }
356
357 #[test]
360 fn the_two_representations_compare_equal_on_equal_contents() {
361 let inline = InlineVec::one(4u32);
362 let mut spilled = InlineVec::new();
363 spilled.push(4u32);
364 spilled.push(5);
365 spilled.pop();
366
367 assert!(spilled.spilled() && !inline.spilled());
368 assert_eq!(inline, spilled);
369 assert_eq!(
370 alloc::format!("{inline:?}"),
371 alloc::format!("{spilled:?}"),
372 "the representation must not show in Debug"
373 );
374 }
375
376 #[test]
377 fn retain_drops_the_inline_element_and_filters_the_spilled_one() {
378 let mut one = InlineVec::one(1u32);
379 one.retain(|&v| v != 1);
380 assert!(one.is_empty());
381
382 let mut many: InlineVec<u32> = (0..6).collect();
383 many.retain(|v| v % 2 == 0);
384 assert_eq!(many.as_slice(), [0, 2, 4]);
385 }
386
387 #[test]
389 fn a_shrunk_value_keeps_its_heap_storage_until_cleared() {
390 let mut many: InlineVec<u32> = (0..3).collect();
391 many.retain(|&v| v == 0);
392 assert!(many.spilled());
393 assert_eq!(many.as_slice(), [0]);
394
395 many.clear();
396 assert!(!many.spilled());
397 assert!(many.is_empty());
398 }
399
400 #[test]
401 fn pop_returns_elements_from_the_end_of_both_representations() {
402 let mut one = InlineVec::one(1u32);
403 assert_eq!(one.pop(), Some(1));
404 assert_eq!(one.pop(), None);
405
406 let mut many: InlineVec<u32> = (0..3).collect();
407 assert_eq!(many.pop(), Some(2));
408 assert_eq!(many.pop(), Some(1));
409 assert_eq!(many.pop(), Some(0));
410 assert_eq!(many.pop(), None);
411 }
412
413 #[test]
414 fn iteration_covers_every_representation() {
415 let cases = [
416 InlineVec::<u32>::new(),
417 InlineVec::one(1),
418 (1..4).collect::<InlineVec<u32>>(),
419 ];
420 let expected: [&[u32]; 3] = [&[], &[1], &[1, 2, 3]];
421
422 for (case, want) in cases.into_iter().zip(expected) {
423 assert_eq!(case.iter().copied().collect::<Vec<_>>(), want);
424 assert_eq!((&case).into_iter().copied().collect::<Vec<_>>(), want);
425 assert_eq!(case.clone().into_vec(), want);
426 assert_eq!(case.into_iter().collect::<Vec<_>>(), want);
427 }
428 }
429
430 #[test]
431 fn mutable_access_reaches_both_representations() {
432 let mut one = InlineVec::one(1u32);
433 for value in &mut one {
434 *value += 1;
435 }
436 assert_eq!(one.as_slice(), [2]);
437
438 let mut many: InlineVec<u32> = (0..3).collect();
439 many.as_mut_slice()[1] = 9;
440 assert_eq!(many.as_slice(), [0, 9, 2]);
441 }
442
443 #[test]
444 fn extend_grows_through_the_same_spill_rule() {
445 let mut values = InlineVec::new();
446 values.extend([1u32]);
447 assert!(!values.spilled());
448 values.extend([2u32, 3]);
449 assert_eq!(values.as_slice(), [1, 2, 3]);
450 }
451
452 #[test]
457 fn the_inline_element_costs_no_more_than_the_vec_it_replaces() {
458 assert_eq!(
459 size_of::<InlineVec<u32>>(),
460 size_of::<Vec<u32>>(),
461 "the inline case must ride in the Vec's niche"
462 );
463 assert_eq!(size_of::<InlineVec<u64>>(), size_of::<Vec<u64>>());
464 assert_eq!(
465 size_of::<InlineVec<(u32, u32)>>(),
466 size_of::<Vec<(u32, u32)>>()
467 );
468 }
469
470 #[test]
473 fn arrays_and_vecs_convert_and_compare_across_both_representations() {
474 let one: InlineVec<u32> = [1].into();
475 let many: InlineVec<u32> = [1, 2].into();
476 assert!(!one.spilled() && many.spilled());
477
478 assert_eq!(one, [1]);
479 assert_eq!(many, [1, 2]);
480 assert_eq!(many, vec![1u32, 2]);
481 assert_eq!(many, *[1u32, 2].as_slice());
482 assert_ne!(one, [2]);
483 assert_ne!(one, [1, 2]);
484 }
485
486 #[test]
489 fn slice_methods_are_available_through_deref() {
490 let values: InlineVec<u32> = (10..13).collect();
491 assert!(values.contains(&11));
492 assert_eq!(values[2], 12);
493 assert_eq!(values.first(), Some(&10));
494 assert_eq!(values.to_vec(), vec![10, 11, 12]);
495 }
496
497 #[test]
500 fn dropping_runs_element_destructors_once() {
501 use alloc::rc::Rc;
502
503 let witness = Rc::new(());
504 let mut values = InlineVec::new();
505 values.push(Rc::clone(&witness));
506 assert_eq!(Rc::strong_count(&witness), 2);
507
508 values.push(Rc::clone(&witness));
509 assert_eq!(Rc::strong_count(&witness), 3, "the spill must not leak");
510
511 drop(values);
512 assert_eq!(Rc::strong_count(&witness), 1);
513 }
514}