1#![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
54pub 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 self.small.marker
81 };
82 if marker % 2 == 0 {
83 ParsedMarker::Large
84 } else {
85 let len = marker >> 1;
86
87 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 unsafe { Layout::from_size_align_unchecked(size, align) }
124 }
125
126 fn as_allocated(&self) -> (&Allocated<T>, *const T) {
127 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 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 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 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 unsafe {
167 (*self.0.as_ptr()).cap = new_cap;
168 }
169 }
170
171 unsafe fn new(cap: usize, src: *mut [T]) -> Self {
178 let this = Self::new_empty(cap);
179
180 unsafe {
182 Allocated::extend(this.0, src);
183 }
184
185 this
186 }
187
188 fn new_empty(cap: usize) -> Self {
190 let layout = Self::new_layout(cap);
191
192 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 unsafe {
199 ptr.write(Allocated::<T> { cap, len: 0, data_start: [] });
200 }
201
202 Self(ptr)
203 }
204}
205
206#[repr(C)]
211struct Allocated<T> {
212 len: usize,
213 cap: usize,
214 data_start: [T; 0], }
216
217impl<T> Allocated<T> {
218 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 unsafe fn extend_data(this: NonNull<Self>, src: *mut [T], old_len: usize) {
240 let dest_start = unsafe { Self::data_start(this).add(old_len) };
242
243 unsafe {
245 let src_start = src.cast::<T>();
246 ptr::copy_nonoverlapping(src_start, dest_start, src.len());
247 }
248 }
249
250 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 #[must_use]
271 pub fn new() -> Self { Self::default() }
272
273 #[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 pub fn as_slice(&self) -> &[T] {
290 match self.0.parse_marker() {
291 ParsedMarker::Small(len) => {
292 let small = unsafe { &self.0.small };
294 let uninit_slice = unsafe { small.data.get_unchecked(..usize::from(len)) };
296 unsafe { slice_assume_init_ref::<T>(uninit_slice) }
298 }
299 ParsedMarker::Large => {
300 let large = unsafe { &self.0.large };
302 let (allocated, data_start) = large.as_allocated();
304 unsafe { slice::from_raw_parts(data_start, allocated.len) }
306 }
307 }
308 }
309
310 pub fn as_mut_slice(&mut self) -> &mut [T] {
312 match self.0.parse_marker() {
313 ParsedMarker::Small(len) => {
314 let small = unsafe { &mut self.0.small };
316 let uninit_slice = unsafe { small.data.get_unchecked_mut(..usize::from(len)) };
318 unsafe { slice_assume_init_mut::<T>(uninit_slice) }
320 }
321 ParsedMarker::Large => {
322 let large = unsafe { &mut self.0.large };
324 let (allocated, data_start) = large.as_allocated_mut();
326 unsafe { slice::from_raw_parts_mut(data_start, allocated.len) }
328 }
329 }
330 }
331
332 pub fn as_uninit_slice_with_length(&mut self) -> (&mut [MaybeUninit<T>], usize) {
338 match self.0.parse_marker() {
339 ParsedMarker::Small(len) => {
340 let small = unsafe { &mut self.0.small };
342 (&mut small.data[..], usize::from(len))
343 }
344 ParsedMarker::Large => {
345 let large = unsafe { &mut self.0.large };
347 let (allocated, data_start) = large.as_allocated_mut();
349 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 pub fn len(&self) -> usize {
360 match self.0.parse_marker() {
361 ParsedMarker::Small(len) => usize::from(len),
362 ParsedMarker::Large => {
363 let large = unsafe { &self.0.large };
365 large.as_allocated().0.len
366 }
367 }
368 }
369
370 pub fn is_empty(&self) -> bool { self.len() == 0 }
372
373 pub fn capacity(&self) -> usize {
384 match self.0.parse_marker() {
385 ParsedMarker::Small(_) => N,
386 ParsedMarker::Large => {
387 let large = unsafe { &self.0.large };
389 large.as_allocated().0.cap
390 }
391 }
392 }
393
394 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 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 unsafe { self.extend_large_slice(&mut *values) }
409 }
410 ParsedMarker::Large => {
411 let mut values = ManuallyDrop::new([value]);
412 unsafe { self.extend_large_slice(&mut *values) }
414 }
415 }
416 }
417
418 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 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 unsafe {
441 self.set_len(len + 1);
442 }
443 }
444
445 unsafe fn extend_small(&mut self, values: *mut [T]) {
451 debug_assert!(self.len() + values.len() <= N); 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 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 unsafe fn extend_small_iter(&mut self, values: impl Iterator<Item = T>) {
478 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; }
488 }
489
490 unsafe fn extend_large_slice(&mut self, values: *mut [T]) {
494 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 unsafe fn extend_large_iter(&mut self, values: impl Iterator<Item = T>) {
510 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 if let Some(item) = values.next() {
528 new_len += 1; unsafe {
530 let dest = Allocated::<T>::data_start(large.0).add(new_len - 1);
531 dest.write(item);
532 }
533 } else {
534 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 unsafe {
556 let mut allocated_ptr = self.0.large.0;
557 allocated_ptr.as_mut().len = new_len;
558 }
559 }
560
561 unsafe fn move_small_to_large(&mut self, new_cap: usize) {
565 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 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 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 unsafe {
628 self.move_small_to_large(new_cap);
629 }
630 }
631 }
632 ParsedMarker::Large => {
633 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 pub fn shrink_to_fit(&mut self) { self.shrink_to_with(|args| args.len.max(N)); }
650
651 pub fn shrink_to(&mut self, min_cap: usize) {
662 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; }
673
674 let large = unsafe { &mut *self.0.large };
676 let alloc_ptr = large.0;
677 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 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 unsafe {
697 ptr::copy_nonoverlapping(data_start, (*self.0.small).data.as_mut_ptr().cast(), len);
698 }
699
700 unsafe {
704 dealloc(alloc_ptr.as_ptr().cast(), large_layout);
705 }
706 } else {
707 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 unsafe {
719 large.0.as_mut().cap = new_cap;
720 }
721 }
722 }
723 }
724 }
725
726 #[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 #[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 let removed = unsafe { mutated_slice.first_mut().unwrap_unchecked().assume_init_read() };
750 shift_left_once(mutated_slice);
751 Some(removed)
752 }
753
754 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 pub fn try_swap_remove(&mut self, index: usize) -> Option<T> {
771 let slice = self.remove_last_uninit(index)?;
772
773 unsafe {
776 slice.swap(index, slice.len() - 1);
777 Some(slice.last_mut().unwrap_unchecked().assume_init_read())
778 }
779 }
780
781 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 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 let small = unsafe { &mut self.0.small };
804
805 if usize::from(old_len) <= len_gt {
806 return None;
807 }
808
809 small.marker = unsafe { small.marker.unchecked_sub(2) };
811
812 Some(&mut small.data[..usize::from(old_len)])
813 }
814 ParsedMarker::Large => {
815 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; allocated.len = new_len;
826
827 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 pub fn clear(&mut self) {
840 let truncated = unsafe { self.decrease_len(0) };
842 unsafe {
844 slice_assume_init_drop(truncated);
845 }
846 }
847
848 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 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 unsafe fn set_len(&mut self, new_len: usize) {
872 match self.0.parse_marker() {
873 ParsedMarker::Small(_) => {
874 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 let large = unsafe { &mut self.0.large };
881 let (allocated, _) = large.as_allocated_mut();
882 allocated.len = new_len;
883 }
884 }
885 }
886}
887
888fn 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
900fn 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 let small = unsafe { &mut self.0.small };
953 let uninit_slice = unsafe { small.data.get_unchecked_mut(..usize::from(len)) };
955 unsafe { slice_assume_init_drop::<T>(uninit_slice) };
957 }
958 ParsedMarker::Large => {
959 let large = unsafe { &mut self.0.large };
961 let (allocated, data_start) = large.as_allocated_mut();
963 unsafe {
966 let slice_ptr = ptr::slice_from_raw_parts_mut(data_start, allocated.len);
967 slice_ptr.drop_in_place();
968 };
969
970 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 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 unsafe {
996 self.move_small_to_large(N * 2);
997 }
998 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 unsafe { self.extend_large_iter(iter) }
1008 }
1009 ParsedMarker::Large => {
1010 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); match this.0.parse_marker() {
1098 ParsedMarker::Small(len) => {
1099 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 let alloc = unsafe { this.0.large.0 };
1108 IntoIter(IntoIterInner::Large { alloc, start: 0 })
1109 }
1110 }
1111 }
1112}
1113
1114pub 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 iter.next().map(|uninit| unsafe { uninit.assume_init() })
1130 }
1131 IntoIterInner::Large { alloc, start } => {
1132 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 let value = unsafe { ptr::read(value.add(index)) };
1144 Some(value)
1145 }
1146 }
1147 }
1148}
1149
1150impl<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 iter.by_ref().for_each(|uninit| drop(unsafe { uninit.assume_init() }));
1161 }
1162 IntoIterInner::Large { alloc, start } => {
1163 let &mut Allocated { len, cap, .. } = unsafe { alloc.as_mut() };
1165
1166 if needs_drop::<T>() {
1167 let value = unsafe { Allocated::data_start(*alloc) };
1168 let start_ptr = unsafe { value.add(*start) };
1170 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 unsafe {
1181 dealloc(alloc.as_ptr().cast(), layout);
1182 }
1183 }
1184 }
1185 }
1186}
1187
1188unsafe impl<T: Send, const N: usize> Send for WordVec<T, N> {}
1190unsafe impl<T: Sync, const N: usize> Sync for WordVec<T, N> {}