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