wordvec/
lib.rs

1//! A [thin][thinvec] and [small][smallvec] vector
2//! that can fit data into a single `usize`.
3//!
4//! See [the readme on GitHub][git-repo]
5//! for detailed explanation of the memory layout.
6//!
7//! ## When to use
8//!
9//! Although the technical limit is `N <= 127`,
10//! it is not meaningful to set `N` such that `align_of::<T>() + N * size_of::<T>()` exceeds 24;
11//! `WordVec` has no advantage over [`SmallVec`][smallvec] if it cannot pack into a smaller struct.
12//!
13//! Thin vectors are significantly (several times) slower than conventional vectors
14//! since reading the length and capacity usually involves accessing memory out of active cache.
15//! Thus, heap layout is supposed to be the cold path.
16//! In other words, `WordVec` is basically
17//! "length should never exceed `N`, but behavior is still correct when it exceeds".
18//!
19//! Since the length encoding in the inlined layout is indirect (involves a bitshift),
20//! raw inlined access also tends to be slower in `WordVec` compared to `SmallVec`,
21//! as a tradeoff of reduced memory footprint of each vector alone.
22//! This may get handy in scenarios with a large array of small vectors,
23//! e.g. as an ECS component.
24//!
25//! [thinvec]: https://docs.rs/thin-vec
26//! [smallvec]: https://docs.rs/smallvec
27//! [git-repo]: https://github.com/SOF3/wordvec
28
29#![no_std]
30#![warn(clippy::pedantic)]
31
32extern crate alloc;
33
34use alloc::alloc::{alloc, dealloc, handle_alloc_error, realloc};
35use core::alloc::Layout;
36use core::hash::{self, Hash};
37use core::hint::assert_unchecked;
38use core::iter::FusedIterator;
39use core::mem::{ManuallyDrop, MaybeUninit, needs_drop};
40use core::ops::{self, Deref, DerefMut};
41use core::ptr::{self, NonNull};
42use core::{array, cmp, fmt, iter, slice};
43
44#[cfg(test)]
45mod tests;
46
47mod polyfill;
48#[allow(
49    clippy::wildcard_imports,
50    reason = "polyfill only contains a small number of unambiguous functions"
51)]
52use polyfill::*;
53
54/// A thin and small vector that can fit data into a single `usize`.
55///
56/// `N` must be less than or equal to 127.
57/// It is advised that `size_of::<T>() * N + align_of::<T>()` does not exceed 20 bytes.
58///
59/// See the [readme](https://github.com/SOF3/wordvec) for more information.
60pub struct WordVec<T, const N: usize>(Inner<T, N>);
61
62union Inner<T, const N: usize> {
63    small: ManuallyDrop<Small<T, N>>,
64    large: ManuallyDrop<Large<T>>,
65}
66
67impl<T, const N: usize> Inner<T, N> {
68    const fn assert_generics() {
69        const {
70            assert!(N <= 127, "N must be less than or equal to 127 to fit in the marker byte");
71            assert!(align_of::<usize>() >= 2, "usize must be aligned to 2 bytes");
72        }
73    }
74
75    fn parse_marker(&self) -> ParsedMarker {
76        Self::assert_generics();
77
78        let marker = unsafe {
79            // SAFETY: the LSB is always initialized in both variants.
80            self.small.marker
81        };
82        if marker % 2 == 0 {
83            ParsedMarker::Large
84        } else {
85            let len = marker >> 1;
86
87            // SAFETY: invariant of `Small` when it is actually small.
88            unsafe {
89                assert_unchecked(usize::from(len) <= N);
90            }
91
92            ParsedMarker::Small(len)
93        }
94    }
95}
96
97#[cfg(target_endian = "little")]
98#[repr(C)]
99struct Small<T, const N: usize> {
100    marker: u8,
101    data:   [MaybeUninit<T>; N],
102}
103
104#[cfg(target_endian = "big")]
105compile_error!("Big-endian targets are not supported yet");
106
107enum ParsedMarker {
108    Small(u8),
109    Large,
110}
111
112struct Large<T>(NonNull<Allocated<T>>);
113
114impl<T> Large<T> {
115    fn new_layout(cap: usize) -> Layout {
116        let additional_size = size_of::<T>().checked_mul(cap).expect("new capacity is too large");
117        let size = size_of::<Allocated<T>>()
118            .checked_add(additional_size)
119            .expect("new capacity is too large");
120        let align = align_of::<Allocated<T>>();
121        // SAFETY: size of Allocated<T> must be a multiple of align of Allocated<T>,
122        // which must be a multiple of align of T due to the `data` field.
123        unsafe { Layout::from_size_align_unchecked(size, align) }
124    }
125
126    fn as_allocated(&self) -> (&Allocated<T>, *const T) {
127        // SAFETY: the pointer is always valid as an invariant of this struct.
128        unsafe { (self.0.as_ref(), Allocated::data_start(self.0)) }
129    }
130
131    fn as_allocated_mut(&mut self) -> (&mut Allocated<T>, *mut T) {
132        // SAFETY: the pointer is always valid as an invariant of this struct.
133        // The `data_start` pointer does not alias the `&mut Allocated`
134        // since `Allocated` only contains an empty array.
135        unsafe { (self.0.as_mut(), Allocated::data_start(self.0)) }
136    }
137
138    fn current_layout(&self) -> Layout {
139        let cap = self.as_allocated().0.cap;
140        Self::new_layout(cap)
141    }
142
143    /// This function never reads or writes `Allocated.len`.
144    /// This allows the local cache of `len` in `extend_large_iter`
145    /// to remain valid when reallocation occurs during growth.
146    fn grow(&mut self, min_new_cap: usize) -> usize {
147        let mut new_cap = min_new_cap;
148
149        let old_cap = self.as_allocated().0.cap;
150        if let Some(double) = old_cap.checked_mul(2) {
151            new_cap = new_cap.max(double);
152        }
153
154        self.grow_exact(new_cap);
155        new_cap
156    }
157
158    fn grow_exact(&mut self, new_cap: usize) {
159        let old_layout = self.current_layout();
160        let new_layout = Self::new_layout(new_cap);
161        // SAFETY: new_layout never returns a zero layout.
162        let new_ptr = unsafe { realloc(self.0.as_ptr().cast(), old_layout, new_layout.size()) };
163        let Some(new_ptr) = NonNull::new(new_ptr) else { handle_alloc_error(new_layout) };
164        self.0 = new_ptr.cast();
165        // SAFETY: the previous `cap` value was initialized to a valid value.
166        unsafe {
167            (*self.0.as_ptr()).cap = new_cap;
168        }
169    }
170
171    /// Create a new `Large` with a new allocation,
172    /// and move the data from `src` to the new allocation.
173    ///
174    /// # Safety
175    /// - `src` has the same invariants as [`ptr::drop_in_place`].
176    /// - The data behind `src` is invalid after this function returns.
177    unsafe fn new(cap: usize, src: *mut [T]) -> Self {
178        let this = Self::new_empty(cap);
179
180        // SAFETY: The underlying `Allocated` is now initialized with the correct capacity.
181        unsafe {
182            Allocated::extend(this.0, src);
183        }
184
185        this
186    }
187
188    /// Create a new `Large` with a new allocation and zero length.
189    fn new_empty(cap: usize) -> Self {
190        let layout = Self::new_layout(cap);
191
192        // SAFETY: new_layout never returns a zero layout.
193        let ptr = unsafe { alloc(layout) };
194        let Some(ptr) = NonNull::new(ptr) else { handle_alloc_error(layout) };
195        let ptr = ptr.cast::<Allocated<T>>();
196
197        // SAFETY: `ptr` can be derefed as an `Allocated<T>` since it was just allocated as such.
198        unsafe {
199            ptr.write(Allocated::<T> { cap, len: 0, data_start: [] });
200        }
201
202        Self(ptr)
203    }
204}
205
206/// This struct only contains the header (and padding) of the heap allocation.
207/// Due to provenance, `_data_start` cannot be directly converted to a slice reference;
208/// the slice must always be derived from the allocation pointer (`NonNull<Allocated<T>>`)
209/// directly.
210#[repr(C)]
211struct Allocated<T> {
212    len:        usize,
213    cap:        usize,
214    data_start: [T; 0], // alignment of T, without the size of T.
215}
216
217impl<T> Allocated<T> {
218    /// Extend the length of this allocation with the new data.
219    ///
220    /// # Safety
221    /// - `src` has the same invariants as [`ptr::drop_in_place`].
222    /// - `(*this)` must be deref-able to a valid `&mut Self`.
223    /// - `(*this).len + src.len() <= self.cap`
224    /// - `src` is invalid after this function returns.
225    /// - `src` must not be derived from `this`.
226    unsafe fn extend(mut this: NonNull<Self>, src: *mut [T]) {
227        let len = unsafe {
228            let this_mut = this.as_mut();
229            let old_len = this_mut.len;
230            this_mut.len = old_len + src.len();
231            old_len
232        };
233        unsafe {
234            Self::extend_data(this, src, len);
235        }
236    }
237
238    /// Like `extend`, but reads the length from a parameter and does not write the new length.
239    unsafe fn extend_data(this: NonNull<Self>, src: *mut [T], old_len: usize) {
240        // SAFETY: length of self.data == self.cap >= new self.len >= old_len
241        let dest_start = unsafe { Self::data_start(this).add(old_len) };
242
243        // SAFETY: function safety invariant.
244        unsafe {
245            let src_start = src.cast::<T>();
246            ptr::copy_nonoverlapping(src_start, dest_start, src.len());
247        }
248    }
249
250    /// # Safety
251    /// `this` must point to a valid header.
252    ///
253    /// The data behind the header are allowed to be uninitialized.
254    unsafe fn data_start(this: NonNull<Self>) -> *mut T {
255        unsafe { (&raw mut (*this.as_ptr()).data_start).cast() }
256    }
257}
258
259struct ReserveArgs {
260    len: usize,
261    cap: usize,
262}
263
264struct ShrinkToArgs {
265    len: usize,
266}
267
268impl<T, const N: usize> WordVec<T, N> {
269    /// Creates an empty vector.
270    #[must_use]
271    pub fn new() -> Self { Self::default() }
272
273    /// Creates an empty vector with the specified capacity.
274    ///
275    /// The resultant capacity is actually `max(N, cap)`.
276    #[must_use]
277    pub fn with_capacity(cap: usize) -> Self {
278        Inner::<T, N>::assert_generics();
279
280        if cap <= N {
281            Self::default()
282        } else {
283            let large = Large::new_empty(cap);
284            Self(Inner { large: ManuallyDrop::new(large) })
285        }
286    }
287
288    /// Returns an immutable slice of all initialized data.
289    pub fn as_slice(&self) -> &[T] {
290        match self.0.parse_marker() {
291            ParsedMarker::Small(len) => {
292                // SAFETY: variant indicated by marker
293                let small = unsafe { &self.0.small };
294                // SAFETY: len must be less than or equal to N
295                let uninit_slice = unsafe { small.data.get_unchecked(..usize::from(len)) };
296                // SAFETY: marker indicates that all first `len` elements are initialized.
297                unsafe { slice_assume_init_ref::<T>(uninit_slice) }
298            }
299            ParsedMarker::Large => {
300                // SAFETY: variant indicated by marker
301                let large = unsafe { &self.0.large };
302                // SAFETY: Large.0 is always a valid reference.
303                let (allocated, data_start) = large.as_allocated();
304                // SAFETY: `allocated.data` is always a valid slice pointer of length `allocated.len`
305                unsafe { slice::from_raw_parts(data_start, allocated.len) }
306            }
307        }
308    }
309
310    /// Returns a mutable slice of all initialized data.
311    pub fn as_mut_slice(&mut self) -> &mut [T] {
312        match self.0.parse_marker() {
313            ParsedMarker::Small(len) => {
314                // SAFETY: variant indicated by marker
315                let small = unsafe { &mut self.0.small };
316                // SAFETY: len must be less than or equal to N
317                let uninit_slice = unsafe { small.data.get_unchecked_mut(..usize::from(len)) };
318                // SAFETY: marker indicates that all first `len` elements are initialized.
319                unsafe { slice_assume_init_mut::<T>(uninit_slice) }
320            }
321            ParsedMarker::Large => {
322                // SAFETY: variant indicated by marker
323                let large = unsafe { &mut self.0.large };
324                // SAFETY: Large.0 is always a valid reference.
325                let (allocated, data_start) = large.as_allocated_mut();
326                // SAFETY: `allocated.data` is always a valid slice pointer of length `allocated.len`
327                unsafe { slice::from_raw_parts_mut(data_start, allocated.len) }
328            }
329        }
330    }
331
332    /// Returns the full capacity of the allocated buffer, which may be partly uninitialized,
333    /// along with the length of the initialized portion.
334    ///
335    /// This is equivalent to `(slice_from_raw_parts(as_mut_ptr(), cap), len)`,
336    /// but with the correct provenance since `as_mut_ptr` only returns provenance up to `len`.
337    pub fn as_uninit_slice_with_length(&mut self) -> (&mut [MaybeUninit<T>], usize) {
338        match self.0.parse_marker() {
339            ParsedMarker::Small(len) => {
340                // SAFETY: variant indicated by marker
341                let small = unsafe { &mut self.0.small };
342                (&mut small.data[..], usize::from(len))
343            }
344            ParsedMarker::Large => {
345                // SAFETY: variant indicated by marker
346                let large = unsafe { &mut self.0.large };
347                // SAFETY: Large.0 is always a valid reference.
348                let (allocated, data_start) = large.as_allocated_mut();
349                // SAFETY: `allocated.data` is always a valid *uninit* slice pointer of length `allocated.cap`
350                let slice = unsafe {
351                    slice::from_raw_parts_mut(data_start.cast::<MaybeUninit<T>>(), allocated.cap)
352                };
353                (slice, allocated.len)
354            }
355        }
356    }
357
358    /// Returns the number of items in this vector.
359    pub fn len(&self) -> usize {
360        match self.0.parse_marker() {
361            ParsedMarker::Small(len) => usize::from(len),
362            ParsedMarker::Large => {
363                // SAFETY: variant indicated by marker
364                let large = unsafe { &self.0.large };
365                large.as_allocated().0.len
366            }
367        }
368    }
369
370    /// Returns whether the vector is empty.
371    pub fn is_empty(&self) -> bool { self.len() == 0 }
372
373    /// Returns the capacity of this vector.
374    ///
375    /// Capacity is always `N` when the inlined layout is used.
376    /// When the heap layout is used, `capacity` returns the maximum number of items
377    /// that can be stored in this vector without reallocating.
378    ///
379    /// Capacity only grows when length exceeds the current capacity,
380    /// so `capacity()` is never less than `N`.
381    /// Nevertheless, the length may shrink without reducing capacity,
382    /// so `len() <= N` does **not** imply `capacity() == N`.
383    pub fn capacity(&self) -> usize {
384        match self.0.parse_marker() {
385            ParsedMarker::Small(_) => N,
386            ParsedMarker::Large => {
387                // SAFETY: variant indicated by marker
388                let large = unsafe { &self.0.large };
389                large.as_allocated().0.cap
390            }
391        }
392    }
393
394    /// Pushes an item to the end of this vector.
395    pub fn push(&mut self, value: T) {
396        match self.0.parse_marker() {
397            ParsedMarker::Small(len) if usize::from(len) < N => {
398                let mut values = ManuallyDrop::new([value]);
399                // SAFETY: marker is Small
400                unsafe { self.extend_small(&mut *values) }
401            }
402            ParsedMarker::Small(_) => {
403                unsafe {
404                    self.move_small_to_large(N + 1);
405                }
406                let mut values = ManuallyDrop::new([value]);
407                // SAFETY: we have moved to large right above.
408                unsafe { self.extend_large_slice(&mut *values) }
409            }
410            ParsedMarker::Large => {
411                let mut values = ManuallyDrop::new([value]);
412                // SAFETY: marker is Large
413                unsafe { self.extend_large_slice(&mut *values) }
414            }
415        }
416    }
417
418    /// Inserts an item at the specified index.
419    ///
420    /// # Panics
421    /// Panics if `index > len`.
422    pub fn insert(&mut self, index: usize, value: T) {
423        self.reserve(1);
424        let (capacity_slice, len) = self.as_uninit_slice_with_length();
425        assert!(index <= len, "insertion index (is {index}) should be <= len (is {len})");
426
427        #[expect(clippy::range_plus_one, reason = "len+1 is more explicit")]
428        let mutated_slice = &mut capacity_slice[index..len + 1];
429
430        // mutated_slice[..mutated_slice.len() - 1] is initialized and
431        // needs to be right-shifted to `mutated_slice[1..]`
432        let mutated_len = mutated_slice.len();
433        if !mutated_slice.is_empty() {
434            shift_right_once(&mut mutated_slice[..mutated_len]);
435        }
436
437        mutated_slice[0] = MaybeUninit::new(value);
438
439        // SAFETY: mutated_slice is now fully initialized.
440        unsafe {
441            self.set_len(len + 1);
442        }
443    }
444
445    /// # Safety
446    /// - The current marker must be `small`
447    /// - `self.len() + values.len()` must be less than or equal to `N`
448    ///   (which will not overflow `u8`).
449    /// - `values` has the same invariants as [`ptr::drop_in_place`].
450    unsafe fn extend_small(&mut self, values: *mut [T]) {
451        debug_assert!(self.len() + values.len() <= N); // safety invariant check
452
453        // SAFETY: function safety invariant
454        let small = unsafe { &mut self.0.small };
455
456        let current_len = usize::from(small.marker >> 1);
457        let slice = &mut small.data.as_mut_slice()[current_len..current_len + values.len()];
458        // SAFETY: `values` cannot overlap with `self` which is referenced mutably.
459        unsafe {
460            ptr::copy_nonoverlapping(
461                values.cast::<T>(),
462                slice.as_mut_ptr().cast::<T>(),
463                values.len(),
464            );
465        }
466
467        let new_len =
468            (small.marker >> 1) + u8::try_from(values.len()).expect("values.len() <= N <= 127");
469        small.marker = (new_len << 1) | 1;
470    }
471
472    /// # Safety
473    /// The current marker must be `small` (which will not overflow `u8`).
474    ///
475    /// # Panics
476    /// Panics if `values` yields more than `N - self.len()` items.
477    unsafe fn extend_small_iter(&mut self, values: impl Iterator<Item = T>) {
478        // SAFETY: function safety invariant
479        let small = unsafe { &mut self.0.small };
480
481        let current_len = usize::from(small.marker >> 1);
482
483        for (i, value) in values.enumerate() {
484            let dest = small.data.get_mut(current_len + i).expect("values has too many items");
485            dest.write(value);
486            small.marker += 2; // this will not overflow since length <= N <= 127
487        }
488    }
489
490    /// # Safety
491    /// - The current marker must be `large`.
492    /// - `values` has the same invariants as [`ptr::drop_in_place`].
493    unsafe fn extend_large_slice(&mut self, values: *mut [T]) {
494        // SAFETY: function safety invariant
495        let large = unsafe { &mut self.0.large };
496        let (&Allocated { len, cap, .. }, _) = large.as_allocated();
497        let new_len = len.checked_add(values.len()).expect("new length is out of bounds");
498        if new_len > cap {
499            large.grow(new_len);
500        }
501
502        unsafe {
503            Allocated::extend(large.0, values);
504        }
505    }
506
507    /// # Safety
508    /// The current marker must be `large`.
509    unsafe fn extend_large_iter(&mut self, values: impl Iterator<Item = T>) {
510        // SAFETY: function safety invariant
511        let large = unsafe { &mut self.0.large };
512        let (&Allocated { len, mut cap, .. }, _) = large.as_allocated();
513
514        let (hint_min, _) = values.size_hint();
515        let hint_len = len.checked_add(hint_min).expect("new length out of bounds");
516
517        if hint_len > cap {
518            cap = large.grow(hint_len);
519        }
520
521        let mut new_len = len;
522        let mut values = values.fuse();
523
524        while new_len < cap {
525            // This simple loop allows better optimizations subject to the implementation of
526            // `values`.
527            if let Some(item) = values.next() {
528                new_len += 1; // new_len < cap <= usize::MAX, so this will not overflow
529                unsafe {
530                    let dest = Allocated::<T>::data_start(large.0).add(new_len - 1);
531                    dest.write(item);
532                }
533            } else {
534                // capacity is not full but input is exhausted
535                break;
536            }
537        }
538
539        for item in values {
540            new_len = new_len.checked_add(1).expect("new length is out of bounds");
541            if new_len > cap {
542                cap = large.grow(new_len);
543            }
544
545            unsafe {
546                let dest = Allocated::<T>::data_start(large.0).add(new_len - 1);
547                dest.write(item);
548            }
549        }
550
551        // SAFETY:
552        // - large will remain large
553        // - large.0 might have been reallocated, but accessing it through `self` is still correct.
554        // - only one item pushed at a time
555        unsafe {
556            let mut allocated_ptr = self.0.large.0;
557            allocated_ptr.as_mut().len = new_len;
558        }
559    }
560
561    /// # Safety
562    /// - The current marker must be `small`
563    /// - `new_cap` must be greater than or equal to `self.len()`.
564    unsafe fn move_small_to_large(&mut self, new_cap: usize) {
565        // SAFETY: function safety invariant
566        let small = unsafe { &mut self.0.small };
567        let data = small.data.as_mut_ptr().cast::<T>();
568        let small_len = small.marker >> 1;
569        let data_slice = ptr::slice_from_raw_parts_mut(data, small_len.into());
570
571        let large = unsafe { Large::new(new_cap, data_slice) };
572
573        self.0.large = ManuallyDrop::new(large);
574    }
575
576    /// Reserves capacity for at least `additional` more elements to be inserted
577    /// in the given `WordVec<T, N>`. The collection may reserve more space to
578    /// speculatively avoid frequent reallocations. After calling `reserve`,
579    /// capacity will be greater than or equal to `self.len() + additional`.
580    /// Does nothing if capacity is already sufficient.
581    ///
582    /// # Panics
583    ///
584    /// Panics if the new capacity results in integer overflow.
585    pub fn reserve(&mut self, additional: usize) {
586        self.reserve_with(|args| {
587            let req = args.len.checked_add(additional).expect("capacity overflow");
588            if req <= args.cap {
589                args.cap
590            } else if req <= args.cap * 2 {
591                args.cap * 2
592            } else {
593                req
594            }
595        });
596    }
597
598    /// Reserves the minimum capacity for at least `additional` more elements to
599    /// be inserted in the given `WordVec<T, N>`. Unlike [`reserve`], this will not
600    /// deliberately over-allocate to speculatively avoid frequent allocations.
601    /// After calling `reserve_exact`, capacity will be greater than or equal to
602    /// `self.len() + additional`. Does nothing if the capacity is already
603    /// sufficient.
604    ///
605    /// Note that the allocator may give the collection more space than it
606    /// requests. Therefore, capacity can not be relied upon to be precisely
607    /// minimal. Prefer [`reserve`] if future insertions are expected.
608    ///
609    /// # Panics
610    ///
611    /// Panics if the new capacity results in integer overflow.
612    pub fn reserve_exact(&mut self, additional: usize) {
613        self.reserve_with(|args| {
614            let req = args.len.checked_add(additional).expect("capacity overflow");
615            req.max(args.cap)
616        });
617    }
618
619    fn reserve_with(&mut self, get_new_cap: impl FnOnce(ReserveArgs) -> usize) {
620        match self.0.parse_marker() {
621            ParsedMarker::Small(len) => {
622                let len = usize::from(len);
623                let new_cap = get_new_cap(ReserveArgs { len, cap: N });
624                if new_cap > N {
625                    // SAFETY: parsed marker as small,
626                    // and new_cap > N >= len
627                    unsafe {
628                        self.move_small_to_large(new_cap);
629                    }
630                }
631            }
632            ParsedMarker::Large => {
633                // SAFETY: parsed marker as large
634                let large = unsafe { &mut self.0.large };
635                let (&Allocated { len, cap, .. }, _) = large.as_allocated();
636                let new_cap = get_new_cap(ReserveArgs { len, cap });
637                if new_cap > cap {
638                    large.grow_exact(new_cap);
639                }
640            }
641        }
642    }
643
644    /// Shrinks the capacity of the vector as much as possible.
645    ///
646    /// If the new capacity fits into the inlined layout,
647    /// the data is moved to the inlined layout.
648    /// Otherwise, the allocation is reallocated to the smaller size.
649    pub fn shrink_to_fit(&mut self) { self.shrink_to_with(|args| args.len.max(N)); }
650
651    /// Shrinks the capacity of the vector with a lower bound.
652    ///
653    /// The capacity will remain at least as large as both the length
654    /// and the supplied value.
655    ///
656    /// If the current capacity is less than the lower limit, this is a no-op.
657    ///
658    /// If the new capacity fits into the inlined layout,
659    /// the data is moved to the inlined layout.
660    /// Otherwise, the allocation is reallocated to the smaller size.
661    pub fn shrink_to(&mut self, min_cap: usize) {
662        // new capacity must be:
663        // - at least self.len(), so that data do not get truncated
664        // - at least min_cap, as requested
665        // - at least N, because capacity can never be less than N
666        self.shrink_to_with(|args| args.len.max(min_cap).max(N));
667    }
668
669    fn shrink_to_with(&mut self, get_new_cap: impl FnOnce(ShrinkToArgs) -> usize) {
670        if let ParsedMarker::Small(_) = self.0.parse_marker() {
671            return; // small cannot be further shrunk
672        }
673
674        // SAFETY: marker is Large
675        let large = unsafe { &mut *self.0.large };
676        let alloc_ptr = large.0;
677        // SAFETY: alloc_ptr is still valid.
678        let &Allocated { len, .. } = unsafe { alloc_ptr.as_ref() };
679        let large_layout = large.current_layout();
680
681        let new_cap = get_new_cap(ShrinkToArgs { len });
682        if new_cap == N {
683            // SAFETY: alloc_ptr is still valid.
684            let data_start = unsafe { Allocated::data_start(alloc_ptr) };
685
686            self.0.small = ManuallyDrop::new(Small {
687                marker: u8::try_from(len << 1)
688                    .expect("len <= new_cap == N <= 127, so len * 2 <= 254")
689                    | 1,
690                data:   [const { MaybeUninit::<T>::uninit() }; N],
691            });
692            // SAFETY:
693            // - data_start is derived from alloc_ptr, which must not point back to itself
694            // - self.0 is now initialized as Small.
695            // - data_start is still valid until alloc_ptr is deallocated below.
696            unsafe {
697                ptr::copy_nonoverlapping(data_start, (*self.0.small).data.as_mut_ptr().cast(), len);
698            }
699
700            // This is the last statement of this branch,
701            // and alloc_ptr is no longer referenced since
702            // its only reference was overwritten by writing to self.0.small above.
703            unsafe {
704                dealloc(alloc_ptr.as_ptr().cast(), large_layout);
705            }
706        } else {
707            // SAFETY: alloc_ptr is still valid at this point, and new_cap > N > 0.
708            let new_layout = Large::<T>::new_layout(new_cap);
709            let new_alloc_ptr =
710                unsafe { realloc(alloc_ptr.as_ptr().cast(), large_layout, new_layout.size()) };
711            match NonNull::new(new_alloc_ptr) {
712                None => {
713                    handle_alloc_error(new_layout);
714                }
715                Some(new_alloc_ptr) => {
716                    large.0 = new_alloc_ptr.cast();
717                    // SAFETY: large.0 has just been updated to a new valid allocation.
718                    unsafe {
719                        large.0.as_mut().cap = new_cap;
720                    }
721                }
722            }
723        }
724    }
725
726    /// Removes the item at index `index`,
727    /// shifting all subsequent items forward.
728    ///
729    /// This is an O(n) operation.
730    ///
731    /// # Panics
732    /// Panics if `index >= self.len()`.
733    #[inline]
734    pub fn remove(&mut self, index: usize) -> T {
735        match self.try_remove(index) {
736            Some(v) => v,
737            None => panic!("Cannot remove index {index} from length {}", self.len()),
738        }
739    }
740
741    /// Like [`remove`](Self::remove),
742    /// but returns `None` instead of panicking if `index` is out of bounds.
743    #[inline]
744    pub fn try_remove(&mut self, index: usize) -> Option<T> {
745        let slice = self.remove_last_uninit(index)?;
746
747        let mutated_slice = &mut slice[index..];
748        // SAFETY: index < `old_len`, so `mutated_slice` must not be empty.
749        let removed = unsafe { mutated_slice.first_mut().unwrap_unchecked().assume_init_read() };
750        shift_left_once(mutated_slice);
751        Some(removed)
752    }
753
754    /// Removes the item at index `index`,
755    /// moving the last item behind (if any) to its original position.
756    ///
757    /// This is an O(1) operation and changes the order.
758    ///
759    /// # Panics
760    /// Panics if `index >= self.len()`.
761    pub fn swap_remove(&mut self, index: usize) -> T {
762        match self.try_swap_remove(index) {
763            Some(v) => v,
764            None => panic!("Cannot remove index {index} from length {}", self.len()),
765        }
766    }
767
768    /// Like [`swap_remove`](Self::swap_remove),
769    /// but returns `None` instead of panicking if `index` is out of bounds.
770    pub fn try_swap_remove(&mut self, index: usize) -> Option<T> {
771        let slice = self.remove_last_uninit(index)?;
772
773        // SAFETY: slice[index] and slice.last() were previously initialized.
774        // Whichever item ends up at the latter position will no longer be reachable.
775        unsafe {
776            slice.swap(index, slice.len() - 1);
777            Some(slice.last_mut().unwrap_unchecked().assume_init_read())
778        }
779    }
780
781    /// Removes the last item.
782    /// Returns `None` if the vector is empty.
783    ///
784    /// The vector capacity is unchanged.
785    pub fn pop(&mut self) -> Option<T> {
786        let last_index = self.len().checked_sub(1)?;
787        self.try_swap_remove(last_index)
788    }
789
790    /// Reduces the length by one.
791    /// Returns `None` if the vector length is less than or equal to `len_gt`.
792    ///
793    /// `len_gt` is effectively the minimum new length after this function returns.
794    ///
795    /// This method cannot cause UB, but it will leak memory
796    /// if the last item in the returned slice is not dropped.
797    ///
798    /// Returns the *original* initialized slice before removing the last item.
799    fn remove_last_uninit(&mut self, len_gt: usize) -> Option<&mut [MaybeUninit<T>]> {
800        match self.0.parse_marker() {
801            ParsedMarker::Small(old_len) => {
802                // SAFETY: marker is Small
803                let small = unsafe { &mut self.0.small };
804
805                if usize::from(old_len) <= len_gt {
806                    return None;
807                }
808
809                // SAFETY: since new_len <= self.len <= 127, (new_len << 1) is still within bounds of u8.
810                small.marker = unsafe { small.marker.unchecked_sub(2) };
811
812                Some(&mut small.data[..usize::from(old_len)])
813            }
814            ParsedMarker::Large => {
815                // SAFETY: marker is Large
816                let large = unsafe { &mut self.0.large };
817                let (allocated, data_start) = large.as_allocated_mut();
818
819                let old_len = allocated.len;
820                if old_len <= len_gt {
821                    return None;
822                }
823
824                let new_len = old_len - 1; // this never overflows since `old_len > len_gt >= 0`
825                allocated.len = new_len;
826
827                // SAFETY: `allocated.data` is always a valid *uninit* slice pointer of length `allocated.cap`
828                let slice = unsafe {
829                    slice::from_raw_parts_mut(data_start.cast::<MaybeUninit<T>>(), old_len)
830                };
831                Some(slice)
832            }
833        }
834    }
835
836    /// Clears the vector, dropping all items.
837    ///
838    /// Does not change the capacity.
839    pub fn clear(&mut self) {
840        // SAFETY: 0 <= self.len() is always true.
841        let truncated = unsafe { self.decrease_len(0) };
842        // SAFETY: truncated is no longer used after decreasing length.
843        unsafe {
844            slice_assume_init_drop(truncated);
845        }
846    }
847
848    /// Decreases the length to `new_len` and returns the slice of truncated data.
849    ///
850    /// # Safety
851    /// `new_len` must be less than or equal to `self.len()`.
852    unsafe fn decrease_len(&mut self, new_len: usize) -> &mut [MaybeUninit<T>] {
853        let old_len = self.len();
854        debug_assert!(new_len <= old_len);
855
856        // SAFETY: new_len <= old_len <= self.cap().
857        unsafe {
858            self.set_len(new_len);
859        }
860
861        let (capacity_slice, _) = self.as_uninit_slice_with_length();
862        &mut capacity_slice[new_len..old_len]
863    }
864
865    /// Sets the length to `new_len`.
866    ///
867    /// # Safety
868    /// - `new_len` must be less than or equal to `self.cap()`.
869    /// - If `new_len >= self.len()`,
870    ///   the new items must be initialized before calling this function.
871    unsafe fn set_len(&mut self, new_len: usize) {
872        match self.0.parse_marker() {
873            ParsedMarker::Small(_) => {
874                // SAFETY: marker is Small
875                let small = unsafe { &mut self.0.small };
876                small.marker = (u8::try_from(new_len).expect("new_len <= N <= 127") << 1) | 1;
877            }
878            ParsedMarker::Large => {
879                // SAFETY: marker is Large
880                let large = unsafe { &mut self.0.large };
881                let (allocated, _) = large.as_allocated_mut();
882                allocated.len = new_len;
883            }
884        }
885    }
886}
887
888/// Shifts `slice[1..]` to `slice[..slice.len()-1]`.
889///
890/// # Panics
891/// Panics if `slice` is empty.
892fn shift_left_once<T>(slice: &mut [MaybeUninit<T>]) {
893    let moved_items = slice.len().checked_sub(1).expect("cannot shift empty slice");
894    let ptr = slice.as_mut_ptr();
895    unsafe {
896        ptr::copy(ptr.add(1), ptr, moved_items);
897    }
898}
899
900/// Shifts `slice[..slice.len()-1]` to `slice[1..]`.
901///
902/// # Panics
903/// Panics if `slice` is empty.
904fn shift_right_once<T>(slice: &mut [MaybeUninit<T>]) {
905    let moved_items = slice.len().checked_sub(1).expect("cannot shift empty slice");
906    let ptr = slice.as_mut_ptr();
907    unsafe {
908        ptr::copy(ptr, ptr.add(1), moved_items);
909    }
910}
911
912impl<T, const N: usize> Default for WordVec<T, N> {
913    fn default() -> Self {
914        Self(Inner {
915            small: ManuallyDrop::new(Small {
916                marker: 1,
917                data:   [const { MaybeUninit::uninit() }; N],
918            }),
919        })
920    }
921}
922
923impl<T, const LENGTH: usize, const N: usize> From<[T; LENGTH]> for WordVec<T, N> {
924    fn from(value: [T; LENGTH]) -> Self {
925        Inner::<T, N>::assert_generics();
926
927        if LENGTH <= N {
928            let mut data = [const { MaybeUninit::uninit() }; N];
929            for (dest, src) in iter::zip(&mut data[..LENGTH], value) {
930                dest.write(src);
931            }
932
933            Self(Inner {
934                small: ManuallyDrop::new(Small {
935                    marker: u8::try_from(LENGTH << 1).expect("LENGTH * 2 <= N * 2 <= 254") | 1,
936                    data,
937                }),
938            })
939        } else {
940            let mut value = ManuallyDrop::new(value);
941            let large = unsafe { Large::new(LENGTH, &mut *value) };
942            Self(Inner { large: ManuallyDrop::new(large) })
943        }
944    }
945}
946
947impl<T, const N: usize> Drop for WordVec<T, N> {
948    fn drop(&mut self) {
949        match self.0.parse_marker() {
950            ParsedMarker::Small(len) => {
951                // SAFETY: variant indicated by marker
952                let small = unsafe { &mut self.0.small };
953                // SAFETY: len must be less than or equal to N
954                let uninit_slice = unsafe { small.data.get_unchecked_mut(..usize::from(len)) };
955                // SAFETY: marker indicates that all first `len` elements are initialized.
956                unsafe { slice_assume_init_drop::<T>(uninit_slice) };
957            }
958            ParsedMarker::Large => {
959                // SAFETY: variant indicated by marker
960                let large = unsafe { &mut self.0.large };
961                // SAFETY: Large.0 is always a valid reference.
962                let (allocated, data_start) = large.as_allocated_mut();
963                // SAFETY: `allocated.data` is always a valid slice pointer of length `allocated.len`,
964                // and the destructor is only called once from its owner.
965                unsafe {
966                    let slice_ptr = ptr::slice_from_raw_parts_mut(data_start, allocated.len);
967                    slice_ptr.drop_in_place();
968                };
969
970                // SAFETY: everything is now cleaned up, the allocation will no longer be used.
971                unsafe {
972                    dealloc(large.0.as_ptr().cast(), large.current_layout());
973                }
974            }
975        }
976    }
977}
978
979impl<T, const N: usize> Extend<T> for WordVec<T, N> {
980    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
981        let mut iter = iter.into_iter();
982        let hint_min = iter.size_hint().0;
983
984        match self.0.parse_marker() {
985            ParsedMarker::Small(len) if usize::from(len) + hint_min <= N => {
986                // SAFETY: marker is Small
987                unsafe {
988                    self.extend_small_iter(iter.by_ref().take(N - usize::from(len)));
989                }
990
991                let mut peekable = iter.peekable();
992                if peekable.peek().is_some() {
993                    // The iterator has more items than `hint_min`.
994                    // We don't know how many more we will get, so our best bet is to double it.
995                    unsafe {
996                        self.move_small_to_large(N * 2);
997                    }
998                    // SAFETY: we have moved to large right above.
999                    unsafe { self.extend_large_iter(peekable) }
1000                }
1001            }
1002            ParsedMarker::Small(len) => {
1003                unsafe {
1004                    self.move_small_to_large(usize::from(len) + hint_min);
1005                }
1006                // SAFETY: we have moved to large right above.
1007                unsafe { self.extend_large_iter(iter) }
1008            }
1009            ParsedMarker::Large => {
1010                // SAFETY: marker is Large
1011                unsafe { self.extend_large_iter(iter) }
1012            }
1013        }
1014    }
1015}
1016
1017impl<T, const N: usize> FromIterator<T> for WordVec<T, N> {
1018    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1019        let mut v = Self::default();
1020        v.extend(iter);
1021        v
1022    }
1023}
1024
1025impl<T: fmt::Debug, const N: usize> fmt::Debug for WordVec<T, N> {
1026    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self.as_slice(), f) }
1027}
1028
1029impl<T, const N: usize> Deref for WordVec<T, N> {
1030    type Target = [T];
1031
1032    fn deref(&self) -> &[T] { self.as_slice() }
1033}
1034
1035impl<T, const N: usize> DerefMut for WordVec<T, N> {
1036    fn deref_mut(&mut self) -> &mut [T] { self.as_mut_slice() }
1037}
1038
1039impl<T, const N: usize, Idx> ops::Index<Idx> for WordVec<T, N>
1040where
1041    [T]: ops::Index<Idx>,
1042{
1043    type Output = <[T] as ops::Index<Idx>>::Output;
1044
1045    fn index(&self, index: Idx) -> &Self::Output { self.as_slice().index(index) }
1046}
1047
1048impl<T, const N: usize, Idx> ops::IndexMut<Idx> for WordVec<T, N>
1049where
1050    [T]: ops::IndexMut<Idx>,
1051{
1052    fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
1053        self.as_mut_slice().index_mut(index)
1054    }
1055}
1056
1057impl<T: PartialEq, const N: usize> PartialEq for WordVec<T, N> {
1058    fn eq(&self, other: &Self) -> bool { self.as_slice() == other.as_slice() }
1059}
1060
1061impl<T: Eq, const N: usize> Eq for WordVec<T, N> {}
1062
1063impl<T: PartialOrd, const N: usize> PartialOrd for WordVec<T, N> {
1064    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
1065        self.as_slice().partial_cmp(other.as_slice())
1066    }
1067}
1068
1069impl<T: Ord, const N: usize> Ord for WordVec<T, N> {
1070    fn cmp(&self, other: &Self) -> cmp::Ordering { self.as_slice().cmp(other.as_slice()) }
1071}
1072
1073impl<T: Hash, const N: usize> Hash for WordVec<T, N> {
1074    fn hash<H: hash::Hasher>(&self, state: &mut H) { self.as_slice().hash(state); }
1075}
1076
1077impl<'a, T, const N: usize> IntoIterator for &'a WordVec<T, N> {
1078    type Item = &'a T;
1079    type IntoIter = slice::Iter<'a, T>;
1080
1081    fn into_iter(self) -> Self::IntoIter { self.as_slice().iter() }
1082}
1083
1084impl<'a, T, const N: usize> IntoIterator for &'a mut WordVec<T, N> {
1085    type Item = &'a mut T;
1086    type IntoIter = slice::IterMut<'a, T>;
1087
1088    fn into_iter(self) -> Self::IntoIter { self.as_mut_slice().iter_mut() }
1089}
1090
1091impl<T, const N: usize> IntoIterator for WordVec<T, N> {
1092    type Item = T;
1093    type IntoIter = IntoIter<T, N>;
1094
1095    fn into_iter(self) -> Self::IntoIter {
1096        let mut this = ManuallyDrop::new(self); // the real destructor is called by `IntoIter`.
1097        match this.0.parse_marker() {
1098            ParsedMarker::Small(len) => {
1099                // SAFETY: indicated by marker
1100                let small = unsafe { ManuallyDrop::take(&mut this.0.small) };
1101                let data = small.data;
1102                let valid = data.into_iter().take(len.into());
1103                IntoIter(IntoIterInner::Small(valid.into_iter()))
1104            }
1105            ParsedMarker::Large => {
1106                // SAFETY: indicated by marker
1107                let alloc = unsafe { this.0.large.0 };
1108                IntoIter(IntoIterInner::Large { alloc, start: 0 })
1109            }
1110        }
1111    }
1112}
1113
1114/// Implements [`IntoIterator`] for [`WordVec`].
1115pub struct IntoIter<T, const N: usize>(IntoIterInner<T, N>);
1116
1117enum IntoIterInner<T, const N: usize> {
1118    Small(iter::Take<array::IntoIter<MaybeUninit<T>, N>>),
1119    Large { alloc: NonNull<Allocated<T>>, start: usize },
1120}
1121
1122impl<T, const N: usize> Iterator for IntoIter<T, N> {
1123    type Item = T;
1124
1125    fn next(&mut self) -> Option<Self::Item> {
1126        match &mut self.0 {
1127            IntoIterInner::Small(iter) => {
1128                // SAFETY: only initialized values are taken
1129                iter.next().map(|uninit| unsafe { uninit.assume_init() })
1130            }
1131            IntoIterInner::Large { alloc, start } => {
1132                // SAFETY: the header is always valid before drop.
1133                let len = unsafe { alloc.as_mut() }.len;
1134
1135                let index = *start;
1136                if index >= len {
1137                    return None;
1138                }
1139                *start = index + 1;
1140
1141                let value = unsafe { Allocated::data_start(*alloc) };
1142                // SAFETY: index was not consumed before this function was called.
1143                let value = unsafe { ptr::read(value.add(index)) };
1144                Some(value)
1145            }
1146        }
1147    }
1148}
1149
1150// Small: array::IntoIter implements FusedIterator.
1151// Large: we check `index >= len` before incrementing (not doing so may lead to UB caused by
1152// overflow).
1153impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
1154
1155impl<T, const N: usize> Drop for IntoIter<T, N> {
1156    fn drop(&mut self) {
1157        match &mut self.0 {
1158            IntoIterInner::Small(iter) => {
1159                // SAFETY: only initialized values are taken
1160                iter.by_ref().for_each(|uninit| drop(unsafe { uninit.assume_init() }));
1161            }
1162            IntoIterInner::Large { alloc, start } => {
1163                // SAFETY: the header is always valid before drop.
1164                let &mut Allocated { len, cap, .. } = unsafe { alloc.as_mut() };
1165
1166                if needs_drop::<T>() {
1167                    let value = unsafe { Allocated::data_start(*alloc) };
1168                    // SAFETY: `start` <= `len`.
1169                    let start_ptr = unsafe { value.add(*start) };
1170                    // SAFETY: All items in the range start..len are still initialized and need
1171                    // dropping.
1172                    unsafe {
1173                        let to_drop = ptr::slice_from_raw_parts_mut(start_ptr, len - *start);
1174                        ptr::drop_in_place(to_drop);
1175                    }
1176                }
1177
1178                let layout = Large::<T>::new_layout(cap);
1179                // SAFETY: alloc is valid before dropped; layout is provided by the header itself.
1180                unsafe {
1181                    dealloc(alloc.as_ptr().cast(), layout);
1182                }
1183            }
1184        }
1185    }
1186}
1187
1188// SAFETY: These are equivalent to the safety of `Vec<T>`.
1189unsafe impl<T: Send, const N: usize> Send for WordVec<T, N> {}
1190unsafe impl<T: Sync, const N: usize> Sync for WordVec<T, N> {}