1use std::fmt;
15use std::mem::MaybeUninit;
16use std::ops::{Deref, DerefMut, Index, IndexMut};
17
18enum Storage<T, const N: usize> {
26 Inline {
27 data: [MaybeUninit<T>; N],
28 len: usize,
29 },
30 Heap(Vec<T>),
31}
32
33pub struct TinyVec<T, const N: usize> {
55 storage: Storage<T, N>,
56}
57
58impl<T, const N: usize> TinyVec<T, N> {
59 pub fn new() -> Self {
61 TinyVec {
62 storage: Storage::Inline {
64 data: unsafe { MaybeUninit::uninit().assume_init() },
65 len: 0,
66 },
67 }
68 }
69
70 pub fn from_vec(v: Vec<T>) -> Self {
72 TinyVec {
73 storage: Storage::Heap(v),
74 }
75 }
76
77 pub fn len(&self) -> usize {
79 match &self.storage {
80 Storage::Inline { len, .. } => *len,
81 Storage::Heap(v) => v.len(),
82 }
83 }
84
85 pub fn is_empty(&self) -> bool {
87 self.len() == 0
88 }
89
90 pub fn is_inline(&self) -> bool {
92 matches!(&self.storage, Storage::Inline { .. })
93 }
94
95 pub fn push(&mut self, value: T) {
99 match &mut self.storage {
100 Storage::Inline { data, len } => {
101 if *len < N {
102 unsafe {
104 data[*len].as_mut_ptr().write(value);
105 }
106 *len += 1;
107 } else {
108 self.spill_to_heap(value);
110 }
111 }
112 Storage::Heap(v) => v.push(value),
113 }
114 }
115
116 pub fn pop(&mut self) -> Option<T> {
118 match &mut self.storage {
119 Storage::Inline { data, len } => {
120 if *len == 0 {
121 return None;
122 }
123 *len -= 1;
124 let value = unsafe { data[*len].as_ptr().read() };
126 Some(value)
127 }
128 Storage::Heap(v) => v.pop(),
129 }
130 }
131
132 pub fn get(&self, index: usize) -> Option<&T> {
134 if index >= self.len() {
135 return None;
136 }
137 match &self.storage {
138 Storage::Inline { data, .. } => Some(unsafe { &*data[index].as_ptr() }),
140 Storage::Heap(v) => v.get(index),
141 }
142 }
143
144 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
146 if index >= self.len() {
147 return None;
148 }
149 match &mut self.storage {
150 Storage::Inline { data, .. } => Some(unsafe { &mut *data[index].as_mut_ptr() }),
152 Storage::Heap(v) => v.get_mut(index),
153 }
154 }
155
156 pub fn as_slice(&self) -> &[T] {
158 match &self.storage {
159 Storage::Inline { data, len } => unsafe {
161 std::slice::from_raw_parts(data.as_ptr() as *const T, *len)
162 },
163 Storage::Heap(v) => v.as_slice(),
164 }
165 }
166
167 pub fn as_mut_slice(&mut self) -> &mut [T] {
169 match &mut self.storage {
170 Storage::Inline { data, len } => unsafe {
172 std::slice::from_raw_parts_mut(data.as_mut_ptr() as *mut T, *len)
173 },
174 Storage::Heap(v) => v.as_mut_slice(),
175 }
176 }
177
178 pub fn clear(&mut self) {
180 match &mut self.storage {
181 Storage::Inline { data, len } => {
182 for i in 0..*len {
184 unsafe { data[i].as_mut_ptr().drop_in_place() };
186 }
187 *len = 0;
188 }
189 Storage::Heap(v) => v.clear(),
190 }
191 }
192
193 pub fn into_vec(mut self) -> Vec<T> {
196 let storage = unsafe { std::ptr::read(&self.storage) };
199 std::mem::forget(self);
201
202 match storage {
203 Storage::Inline { data, len } => {
204 let mut v = Vec::with_capacity(len);
205 for i in 0..len {
206 v.push(unsafe { data[i].as_ptr().read() });
208 }
209 v
212 }
213 Storage::Heap(v) => v,
214 }
215 }
216
217 fn spill_to_heap(&mut self, extra: T) {
223 let old_storage = std::mem::replace(
226 &mut self.storage,
227 Storage::Heap(Vec::new()),
229 );
230
231 if let Storage::Inline { data, len } = old_storage {
232 let mut v = Vec::with_capacity(len + 1);
233 for i in 0..len {
234 v.push(unsafe { data[i].as_ptr().read() });
236 }
237 v.push(extra);
239 self.storage = Storage::Heap(v);
240 }
241 }
243}
244
245impl<T, const N: usize> Drop for TinyVec<T, N> {
250 fn drop(&mut self) {
251 if let Storage::Inline { data, len } = &mut self.storage {
254 for i in 0..*len {
255 unsafe { data[i].as_mut_ptr().drop_in_place() };
257 }
258 *len = 0;
260 }
261 }
262}
263
264impl<T, const N: usize> Deref for TinyVec<T, N> {
269 type Target = [T];
270 fn deref(&self) -> &[T] {
271 self.as_slice()
272 }
273}
274
275impl<T, const N: usize> DerefMut for TinyVec<T, N> {
276 fn deref_mut(&mut self) -> &mut [T] {
277 self.as_mut_slice()
278 }
279}
280
281impl<T, const N: usize> Index<usize> for TinyVec<T, N> {
282 type Output = T;
283 fn index(&self, index: usize) -> &T {
284 self.get(index).expect("TinyVec: index out of bounds")
285 }
286}
287
288impl<T, const N: usize> IndexMut<usize> for TinyVec<T, N> {
289 fn index_mut(&mut self, index: usize) -> &mut T {
290 self.get_mut(index).expect("TinyVec: index out of bounds")
291 }
292}
293
294impl<T: Clone, const N: usize> Clone for TinyVec<T, N> {
295 fn clone(&self) -> Self {
296 let mut out = TinyVec::new();
297 for elem in self.as_slice() {
298 out.push(elem.clone());
299 }
300 out
301 }
302}
303
304impl<T: fmt::Debug, const N: usize> fmt::Debug for TinyVec<T, N> {
305 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
306 fmt::Debug::fmt(self.as_slice(), f)
307 }
308}
309
310impl<T: PartialEq, const N: usize> PartialEq for TinyVec<T, N> {
311 fn eq(&self, other: &Self) -> bool {
312 self.as_slice() == other.as_slice()
313 }
314}
315
316impl<T: Eq, const N: usize> Eq for TinyVec<T, N> {}
317
318impl<T, const N: usize> FromIterator<T> for TinyVec<T, N> {
319 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
320 let mut v = TinyVec::new();
321 for item in iter {
322 v.push(item);
323 }
324 v
325 }
326}
327
328impl<T, const N: usize> IntoIterator for TinyVec<T, N> {
329 type Item = T;
330 type IntoIter = std::vec::IntoIter<T>;
331 fn into_iter(self) -> Self::IntoIter {
332 self.into_vec().into_iter()
333 }
334}
335
336impl<'a, T, const N: usize> IntoIterator for &'a TinyVec<T, N> {
337 type Item = &'a T;
338 type IntoIter = std::slice::Iter<'a, T>;
339 fn into_iter(self) -> Self::IntoIter {
340 self.as_slice().iter()
341 }
342}
343
344#[cfg(test)]
349mod tests {
350 use super::*;
351
352 #[test]
353 fn test_push_within_inline() {
354 let mut v: TinyVec<i32, 4> = TinyVec::new();
355 v.push(10);
356 v.push(20);
357 v.push(30);
358 assert!(v.is_inline());
359 assert_eq!(v.len(), 3);
360 assert_eq!(v[0], 10);
361 assert_eq!(v[2], 30);
362 }
363
364 #[test]
365 fn test_spill_to_heap() {
366 let mut v: TinyVec<i32, 2> = TinyVec::new();
367 v.push(1);
368 v.push(2);
369 assert!(v.is_inline());
370 v.push(3); assert!(!v.is_inline());
372 assert_eq!(v.len(), 3);
373 assert_eq!(v[0], 1);
374 assert_eq!(v[1], 2);
375 assert_eq!(v[2], 3);
376 }
377
378 #[test]
379 fn test_pop() {
380 let mut v: TinyVec<i32, 4> = TinyVec::new();
381 v.push(42);
382 assert_eq!(v.pop(), Some(42));
383 assert_eq!(v.pop(), None);
384 }
385
386 #[test]
387 fn test_pop_after_spill() {
388 let mut v: TinyVec<i32, 1> = TinyVec::new();
389 v.push(1);
390 v.push(2);
391 assert_eq!(v.pop(), Some(2));
392 assert_eq!(v.pop(), Some(1));
393 assert_eq!(v.pop(), None);
394 }
395
396 #[test]
397 fn test_clear() {
398 let mut v: TinyVec<String, 4> = TinyVec::new();
399 v.push("hello".to_string());
400 v.push("world".to_string());
401 v.clear();
402 assert!(v.is_empty());
403 }
404
405 #[test]
406 fn test_drop_non_copy() {
407 let mut v: TinyVec<String, 2> = TinyVec::new();
409 v.push("a".to_string());
410 v.push("b".to_string());
411 v.push("c".to_string()); drop(v);
413 }
414
415 #[test]
416 fn test_iter() {
417 let mut v: TinyVec<i32, 4> = TinyVec::new();
418 for i in 0..6 {
419 v.push(i);
420 }
421 let collected: Vec<_> = v.iter().copied().collect();
422 assert_eq!(collected, vec![0, 1, 2, 3, 4, 5]);
423 }
424
425 #[test]
426 fn test_from_iter() {
427 let v: TinyVec<i32, 4> = (0..8).collect();
428 assert_eq!(v.len(), 8);
429 for (i, &x) in v.iter().enumerate() {
430 assert_eq!(x, i as i32);
431 }
432 }
433
434 #[test]
435 fn test_clone() {
436 let mut v: TinyVec<i32, 4> = TinyVec::new();
437 v.push(1);
438 v.push(2);
439 let w = v.clone();
440 assert_eq!(v, w);
441 }
442
443 #[test]
444 fn test_zero_capacity() {
445 let mut v: TinyVec<i32, 0> = TinyVec::new();
447 v.push(99);
448 assert_eq!(v.len(), 1);
449 assert_eq!(v[0], 99);
450 }
451}