bones_schema/alloc/
vec.rs

1use std::{
2    any::{type_name, TypeId},
3    ffi::c_void,
4    fmt::Debug,
5    iter::Iterator,
6    marker::PhantomData,
7    mem::MaybeUninit,
8    sync::OnceLock,
9};
10
11use bones_utils::{default, fxhash::FxHasher, parking_lot::RwLock, HashMap};
12
13use crate::{prelude::*, raw_fns::*};
14
15use super::ResizableAlloc;
16
17/// A type-erased [`Vec`]-like collection that for items with the same [`Schema`].
18pub struct SchemaVec {
19    /// The allocation for stored items.
20    buffer: ResizableAlloc,
21    /// The number of items actually stored in the vec.
22    len: usize,
23    /// The schema of the items stored in the vec.
24    schema: &'static Schema,
25}
26
27impl std::fmt::Debug for SchemaVec {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        f.debug_struct("SchemaVec")
30            .field("buffer", &"ResizableAlloc")
31            .field("len", &self.len)
32            .field("schema", &self.schema)
33            .finish()
34    }
35}
36
37// SOUND: the SchemaVec may only contain `HasSchema` types which are required to be `Sync + Send`.
38unsafe impl Sync for SchemaVec {}
39unsafe impl Send for SchemaVec {}
40
41impl SchemaVec {
42    /// Initialize an empty [`SchemaVec`] for items with the given schema.
43    pub fn new(schema: &'static Schema) -> Self {
44        Self {
45            buffer: ResizableAlloc::new(schema.layout()),
46            len: 0,
47            schema,
48        }
49    }
50
51    /// Grow the backing buffer to fit more elements.
52    fn grow(&mut self) {
53        let cap = self.buffer.capacity();
54        if cap == 0 {
55            self.buffer.resize(1).unwrap();
56        } else {
57            self.buffer.resize(cap * 2).unwrap();
58        }
59    }
60
61    /// Push an item unsafely to the vector.
62    /// # Safety
63    /// - The item must be a pointer to data with the same schema.
64    /// - You must ensure the `item` pointer is not used after pusing.
65    unsafe fn push_raw(&mut self, item: *mut c_void) {
66        // Make room for more elements if necessary
67        if self.len == self.buffer.capacity() {
68            self.grow();
69        }
70
71        // Copy the item into the vec
72        unsafe {
73            self.buffer
74                .unchecked_idx(self.len)
75                .copy_from_nonoverlapping(item, self.buffer.layout().size());
76        }
77
78        // Extend the length. This cannot overflow because we will run out of memory before we
79        // exhaust `usize`.
80        self.len += 1;
81    }
82
83    /// Push an item to the vec.
84    /// # Errors
85    /// Errors if the schema of `T` doesn't match the vec.
86    pub fn try_push<T: HasSchema>(&mut self, mut item: T) -> Result<(), SchemaMismatchError> {
87        // Ensure matching schema
88        if self.schema != T::schema() {
89            return Err(SchemaMismatchError);
90        }
91
92        unsafe {
93            self.push_raw(&mut item as *mut T as *mut c_void);
94            std::mem::forget(item);
95        }
96
97        Ok(())
98    }
99
100    /// Push an item to the vec.
101    /// # Panics
102    /// Panics if the schema of `T` doesn't match the vec.
103    #[inline]
104    #[track_caller]
105    pub fn push<T: HasSchema>(&mut self, item: T) {
106        self.try_push(item).unwrap()
107    }
108
109    /// Push the item into the end of the vector.
110    pub fn try_push_box(&mut self, mut item: SchemaBox) -> Result<(), SchemaMismatchError> {
111        // Ensure matching schema
112        if self.schema != item.schema() {
113            return Err(SchemaMismatchError);
114        }
115
116        // We validated matching schemas.
117        unsafe {
118            self.push_raw(item.as_mut().as_ptr());
119        }
120
121        // Don't run the item's destructor, it's the responsibility of the vec
122        item.forget();
123
124        Ok(())
125    }
126
127    /// Push the item into the end of the vector.
128    #[track_caller]
129    #[inline]
130    pub fn push_box(&mut self, item: SchemaBox) {
131        self.try_push_box(item).unwrap()
132    }
133
134    /// Pop the last item off of the end of the vector.
135    pub fn pop_box(&mut self) -> Option<SchemaBox> {
136        if self.len == 0 {
137            None
138        } else {
139            unsafe { self.raw_pop() }.map(|ptr| unsafe {
140                let mut b = SchemaBox::uninitialized(self.schema);
141                b.as_mut()
142                    .as_ptr()
143                    .copy_from_nonoverlapping(ptr, self.buffer.layout().size());
144                b
145            })
146        }
147    }
148
149    /// Pop an item off the vec.
150    /// # Errors
151    /// Errors if the schema of `T` doesn't match.
152    pub fn try_pop<T: HasSchema>(&mut self) -> Result<Option<T>, SchemaMismatchError> {
153        if self.schema != T::schema() {
154            Err(SchemaMismatchError)
155        } else {
156            let ret = unsafe { self.raw_pop() }.map(|ptr| {
157                let mut data = MaybeUninit::<T>::uninit();
158                unsafe {
159                    (data.as_mut_ptr() as *mut c_void)
160                        .copy_from_nonoverlapping(ptr, self.buffer.layout().size());
161                    data.assume_init()
162                }
163            });
164            Ok(ret)
165        }
166    }
167
168    /// # Safety
169    /// The pointer may only be used immediately after calling raw_pop to read the data out of the
170    /// popped item. Any further mutations to the vector may make the pointer invalid.
171    unsafe fn raw_pop(&mut self) -> Option<*mut c_void> {
172        if self.len == 0 {
173            None
174        } else {
175            // Decrement our length
176            self.len -= 1;
177
178            // Return the pointer to the item that is being popped off.
179            Some(unsafe { self.buffer.unchecked_idx(self.len) })
180        }
181    }
182
183    /// Pop an item off the vec.
184    /// # Panics
185    /// Panics if the schema of `T` doesn't match.
186    #[inline]
187    #[track_caller]
188    pub fn pop<T: HasSchema>(&mut self) -> Option<T> {
189        self.try_pop().unwrap()
190    }
191
192    /// Get an item in the vec.
193    /// # Errors
194    /// Errors if the schema doesn't match.
195    pub fn try_get<T: HasSchema>(&self, idx: usize) -> Result<Option<&T>, SchemaMismatchError> {
196        self.get_ref(idx).map(|x| x.try_cast()).transpose()
197    }
198
199    /// Get an item in the vec.
200    /// # Panics
201    /// Panics if the schema doesn't match.
202    #[inline]
203    #[track_caller]
204    pub fn get<T: HasSchema>(&self, idx: usize) -> Option<&T> {
205        self.try_get(idx).unwrap()
206    }
207
208    /// Get the item with the given index.
209    pub fn get_ref(&self, idx: usize) -> Option<SchemaRef<'_>> {
210        if idx >= self.len {
211            None
212        } else {
213            let ptr = unsafe { self.buffer.unchecked_idx(idx) };
214            unsafe { Some(SchemaRef::from_ptr_schema(ptr, self.schema)) }
215        }
216    }
217
218    /// Get an item in the vec.
219    /// # Errors
220    /// Errors if the schema doesn't match.
221    pub fn try_get_mut<T: HasSchema>(
222        &mut self,
223        idx: usize,
224    ) -> Result<Option<&mut T>, SchemaMismatchError> {
225        self.get_ref_mut(idx)
226            // SOUND: We are extending the lifetime of the cast to the lifetime of our borrow of
227            // `&mut self`, which is valid.
228            .map(|mut x| unsafe { x.try_cast_mut().map(|x| transmute_lifetime(x)) })
229            .transpose()
230    }
231
232    /// Get an item in the vec.
233    /// # Panics
234    /// Panics if the schema doesn't match.
235    #[inline]
236    #[track_caller]
237    pub fn get_mut<T: HasSchema>(&mut self, idx: usize) -> Option<&mut T> {
238        self.try_get_mut(idx).unwrap()
239    }
240
241    /// Get an item with the given index.
242    pub fn get_ref_mut(&mut self, idx: usize) -> Option<SchemaRefMut<'_>> {
243        if idx >= self.len {
244            None
245        } else {
246            let ptr = unsafe { self.buffer.unchecked_idx(idx) };
247            unsafe { Some(SchemaRefMut::from_ptr_schema(ptr, self.schema)) }
248        }
249    }
250
251    /// Get the number of items in the vector.
252    #[inline]
253    pub fn len(&self) -> usize {
254        self.len
255    }
256
257    /// Returns `true` if the vector has zero items in it.
258    #[inline]
259    pub fn is_empty(&self) -> bool {
260        self.len() == 0
261    }
262
263    /// Get the capacity of the backing buffer.
264    #[inline]
265    pub fn capacity(&self) -> usize {
266        self.buffer.capacity()
267    }
268
269    /// Get the schema of items in this [`SchemaVec`].
270    #[inline]
271    pub fn schema(&self) -> &'static Schema {
272        self.schema
273    }
274
275    /// Iterate over values in the vec
276    pub fn iter(&self) -> SchemaVecIter {
277        SchemaVecIter { vec: self, idx: 0 }
278    }
279
280    /// Iterate mutably over values in the vec
281    pub fn iter_mut(&mut self) -> SchemaVecIterMut {
282        SchemaVecIterMut { vec: self, idx: 0 }
283    }
284
285    /// Convert into a typed [`SVec`].
286    /// # Panics
287    /// Panics if the schema of `T` doesn't match this [`SchemaVec`]'s schema.
288    #[track_caller]
289    pub fn into_svec<T: HasSchema>(self) -> SVec<T> {
290        self.try_into_svec().unwrap()
291    }
292
293    /// Try to convert into a typed [`SVec`].
294    /// # Errors
295    /// Errors if the schema of `T` doesn't match this [`SchemaVec`]'s schema.
296    pub fn try_into_svec<T: HasSchema>(self) -> Result<SVec<T>, SchemaMismatchError> {
297        if T::schema() == self.schema {
298            Ok(SVec {
299                vec: self,
300                _phantom: PhantomData,
301            })
302        } else {
303            Err(SchemaMismatchError)
304        }
305    }
306
307    /// Get the hash of this [`SchemaVec`].
308    /// # Panics
309    /// Panics if the inner type doesn't implement hash.
310    #[track_caller]
311    pub fn hash(&self) -> u64 {
312        use std::hash::{Hash, Hasher};
313        let Some(hash_fn) = &self.schema.hash_fn else {
314            panic!("Schema doesn't specify a hash_fn");
315        };
316        let mut hasher = FxHasher::default();
317        for item_ptr in self.buffer.iter() {
318            let item_hash = unsafe { (hash_fn.get())(item_ptr) };
319            item_hash.hash(&mut hasher);
320        }
321        hasher.finish()
322    }
323
324    /// Raw version of the [`hash()`][Self::hash] function. Not meant for normal use.
325    /// # Safety
326    /// Pointer must be a valid pointer to a [`SchemaVec`].
327    pub unsafe fn raw_hash(ptr: *const c_void) -> u64 {
328        let this = unsafe { &*(ptr as *const Self) };
329        this.hash()
330    }
331
332    /// Raw version of the [`eq()`][PartialEq::eq] function. Not meant for normal use.
333    /// # Safety
334    /// Pointers must be valid pointers to [`SchemaVec`]s.
335    pub unsafe fn raw_eq(a: *const c_void, b: *const c_void) -> bool {
336        let a = &*(a as *const Self);
337        let b = &*(b as *const Self);
338        a.eq(b)
339    }
340
341    /// Remove and return the element at position `index` within the vector,
342    /// shifting all elements after it to the left.
343    /// # Panics
344    /// Panics if `index` is out of bounds.
345    pub fn remove(&mut self, index: usize) -> SchemaBox {
346        if index >= self.len {
347            panic!("index out of bounds");
348        }
349        let item = unsafe {
350            let ptr = self.buffer.unchecked_idx(index);
351            let mut boxed = SchemaBox::uninitialized(self.schema);
352            boxed
353                .as_mut()
354                .as_ptr()
355                .copy_from_nonoverlapping(ptr, self.schema.layout().size());
356
357            // Shift elements
358            let to_move = self.len - index - 1;
359            if to_move > 0 {
360                std::ptr::copy(
361                    self.buffer.unchecked_idx(index + 1),
362                    self.buffer.unchecked_idx(index),
363                    to_move * self.schema.layout().size(),
364                );
365            }
366
367            self.len -= 1;
368            boxed
369        };
370        item
371    }
372
373    /// Clears the vector, removing all values.
374    pub fn clear(&mut self) {
375        while self.pop_box().is_some() {}
376    }
377
378    /// Shortens the vector, keeping the first `len` elements and dropping the rest.
379    ///
380    /// If `len` is greater than the vector's current length, this has no effect.
381    pub fn truncate(&mut self, len: usize) {
382        while self.len > len {
383            self.pop_box();
384        }
385    }
386}
387
388impl<T: HasSchema> FromIterator<T> for SVec<T> {
389    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
390        let mut this = Self::default();
391        for item in iter {
392            this.push(item);
393        }
394        this
395    }
396}
397
398impl<'a> IntoIterator for &'a SchemaVec {
399    type Item = SchemaRef<'a>;
400    type IntoIter = SchemaVecIter<'a>;
401    fn into_iter(self) -> Self::IntoIter {
402        self.iter()
403    }
404}
405impl<'a> IntoIterator for &'a mut SchemaVec {
406    type Item = SchemaRefMut<'a>;
407    type IntoIter = SchemaVecIterMut<'a>;
408    fn into_iter(self) -> Self::IntoIter {
409        self.iter_mut()
410    }
411}
412
413/// Iterator over [`SchemaVec`].
414pub struct SchemaVecIter<'a> {
415    vec: &'a SchemaVec,
416    idx: usize,
417}
418
419impl<'a> Iterator for SchemaVecIter<'a> {
420    type Item = SchemaRef<'a>;
421    fn next(&mut self) -> Option<Self::Item> {
422        let item = self.vec.get_ref(self.idx);
423        if item.is_some() {
424            self.idx += 1;
425        }
426        item
427    }
428}
429
430/// Mutable iterator over [`SchemaVec`].
431pub struct SchemaVecIterMut<'a> {
432    vec: &'a mut SchemaVec,
433    idx: usize,
434}
435impl<'a> Iterator for SchemaVecIterMut<'a> {
436    type Item = SchemaRefMut<'a>;
437
438    fn next(&mut self) -> Option<Self::Item> {
439        let item = self
440            .vec
441            .get_ref_mut(self.idx)
442            // SOUND: We are returning data with the lifetime of the SchemaVec, which is accurate
443            // and sound as long as we don't return two mutable references to the same item.
444            .map(|x| unsafe { SchemaRefMut::from_ptr_schema(x.as_ptr(), x.schema()) });
445        if item.is_some() {
446            self.idx += 1;
447        }
448        item
449    }
450}
451
452impl Eq for SchemaVec {}
453impl PartialEq for SchemaVec {
454    #[track_caller]
455    fn eq(&self, other: &Self) -> bool {
456        if self.schema != other.schema {
457            panic!("Cannot compare two `SchemaVec`s with different schemas.");
458        }
459        let Some(eq_fn) = &self.schema.eq_fn else {
460            panic!("Schema doesn't have an eq_fn");
461        };
462
463        for i in 0..self.len {
464            unsafe {
465                let a = self.buffer.unchecked_idx(i);
466                let b = self.buffer.unchecked_idx(i);
467                if !(eq_fn.get())(a, b) {
468                    return false;
469                }
470            }
471        }
472        true
473    }
474}
475
476impl Clone for SchemaVec {
477    fn clone(&self) -> Self {
478        let Some(clone_fn) = &self.schema.clone_fn else {
479            panic!("This type cannot be cloned");
480        };
481        let mut buffer_clone = ResizableAlloc::new(self.schema.layout());
482        buffer_clone.resize(self.len).unwrap();
483
484        // Clone each item in the vec
485        for i in 0..self.len {
486            // SOUND: we've check that the index is within bounds, and the schema asserts the
487            // validity of the clone function.
488            unsafe {
489                let item = self.buffer.unchecked_idx(i);
490                (clone_fn.get())(item, buffer_clone.unchecked_idx(i));
491            }
492        }
493
494        SchemaVec {
495            buffer: buffer_clone,
496            len: self.len,
497            schema: self.schema,
498        }
499    }
500}
501
502impl Drop for SchemaVec {
503    fn drop(&mut self) {
504        for _ in 0..self.len {
505            drop(self.pop_box().unwrap());
506        }
507    }
508}
509
510/// A typed version of a [`SchemaVec`].
511///
512/// This type exists as an alternative to [`Vec`] that properly implements [`HasSchema`].
513///
514/// Additionally, accessing an [`SVec`] is more efficient than using a [`SchemaVec`] because it
515/// avoids runtime schema checks after construction.
516#[repr(transparent)]
517#[derive(Eq, PartialEq)]
518pub struct SVec<T: HasSchema> {
519    vec: SchemaVec,
520    _phantom: PhantomData<T>,
521}
522
523impl<T: HasSchema> SVec<T> {
524    /// Create a new, empty [`SVec`].
525    pub fn new() -> Self {
526        Self {
527            vec: SchemaVec::new(T::schema()),
528            _phantom: PhantomData,
529        }
530    }
531
532    /// Push an item onto the vector.
533    pub fn push(&mut self, mut item: T) {
534        // SOUND: We know that the schema matches, and we forget the item after pushing.
535        unsafe {
536            self.vec.push_raw(&mut item as *mut T as *mut c_void);
537        }
538        std::mem::forget(item);
539    }
540
541    /// Pop an item off of the vector.
542    pub fn pop(&mut self) -> Option<T> {
543        unsafe {
544            self.vec.raw_pop().map(|ptr| {
545                let mut ret = MaybeUninit::<T>::uninit();
546                ret.as_mut_ptr().copy_from_nonoverlapping(ptr as *mut T, 1);
547                ret.assume_init()
548            })
549        }
550    }
551
552    /// Get an item from the vec.
553    pub fn get(&self, idx: usize) -> Option<&T> {
554        // SOUND: We know that the pointer is to a type T
555        self.vec
556            .get_ref(idx)
557            .map(|x| unsafe { x.cast_into_unchecked() })
558    }
559
560    /// Get an item from the vec.
561    pub fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
562        // SOUND: We know that the pointer is to a type T
563        self.vec
564            .get_ref_mut(idx)
565            .map(|x| unsafe { x.cast_into_mut_unchecked() })
566    }
567
568    /// Iterate over references to the items in the vec.
569    pub fn iter(&self) -> SVecIter<T> {
570        SVecIter {
571            vec: self,
572            idx: 0,
573            end: self.len() as isize - 1,
574        }
575    }
576
577    /// Iterate over mutable references to the items in the vec.
578    pub fn iter_mut(&mut self) -> SVecIterMut<T> {
579        SVecIterMut {
580            idx: 0,
581            end: self.len() as isize - 1,
582            vec: self,
583        }
584    }
585
586    /// Get the length of the vector.
587    #[inline]
588    pub fn len(&self) -> usize {
589        self.vec.len()
590    }
591
592    /// Returns `true` if there are no items in the vector.
593    #[inline]
594    pub fn is_empty(&self) -> bool {
595        self.vec.is_empty()
596    }
597
598    /// Get the capacity of the vec.
599    #[inline]
600    pub fn capacity(&self) -> usize {
601        self.vec.capacity()
602    }
603
604    /// Convert to an untyped [`SchemaVec`].
605    #[inline]
606    pub fn into_schema_vec(self) -> SchemaVec {
607        self.vec
608    }
609
610    /// Get the hash of the [`SVec`].
611    pub fn hash(&self) -> u64 {
612        self.vec.hash()
613    }
614
615    /// Remove and return the element at position `index` within the vector,
616    /// shifting all elements after it to the left.
617    /// # Panics
618    /// Panics if `index` is out of bounds.
619    pub fn remove(&mut self, index: usize) -> T {
620        let boxed = self.vec.remove(index);
621        // SAFETY: We know that the SchemaBox contains a value of type T
622        unsafe { boxed.cast_into_unchecked() }
623    }
624
625    /// Clears the vector, removing all values.
626    pub fn clear(&mut self) {
627        self.vec.clear();
628    }
629
630    /// Shortens the vector, keeping the first `len` elements and dropping the rest.
631    ///
632    /// If `len` is greater than the vector's current length, this has no effect.
633    pub fn truncate(&mut self, len: usize) {
634        self.vec.truncate(len);
635    }
636
637    /// Extends the vector with the contents of an iterator.
638    pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
639        for item in iter {
640            self.push(item);
641        }
642    }
643
644    /// Retains only the elements specified by the predicate.
645    pub fn retain<F>(&mut self, mut f: F)
646    where
647        F: FnMut(&T) -> bool,
648    {
649        let mut i = 0;
650        while i < self.len() {
651            if !f(&self[i]) {
652                self.remove(i);
653            } else {
654                i += 1;
655            }
656        }
657    }
658
659    /// Retains only the elements specified by the predicate, passing a mutable reference to it.
660    pub fn retain_mut<F>(&mut self, mut f: F)
661    where
662        F: FnMut(&mut T) -> bool,
663    {
664        let mut i = 0;
665        while i < self.len() {
666            if !f(self.get_mut(i).unwrap()) {
667                self.remove(i);
668            } else {
669                i += 1;
670            }
671        }
672    }
673
674    /// Removes and returns the last element of the vector if the predicate returns true.
675    pub fn pop_if<F>(&mut self, f: F) -> Option<T>
676    where
677        F: FnOnce(&T) -> bool,
678    {
679        if let Some(last) = self.last() {
680            if f(last) {
681                self.pop()
682            } else {
683                None
684            }
685        } else {
686            None
687        }
688    }
689
690    /// Returns a reference to the first element of the vector, or None if it is empty.
691    pub fn first(&self) -> Option<&T> {
692        self.get(0)
693    }
694
695    /// Returns a mutable reference to the first element of the vector, or None if it is empty.
696    pub fn first_mut(&mut self) -> Option<&mut T> {
697        self.get_mut(0)
698    }
699
700    /// Returns a reference to the last element of the vector, or None if it is empty.
701    pub fn last(&self) -> Option<&T> {
702        self.get(self.len().wrapping_sub(1))
703    }
704
705    /// Returns a mutable reference to the last element of the vector, or None if it is empty.
706    pub fn last_mut(&mut self) -> Option<&mut T> {
707        let len = self.len();
708        self.get_mut(len.wrapping_sub(1))
709    }
710
711    /// Reverses the order of elements in the vector, in place.
712    pub fn reverse(&mut self) {
713        let mut i = 0;
714        let mut j = self.len().saturating_sub(1);
715        while i < j {
716            // SAFETY: We know that i and j are within bounds and not equal.
717            unsafe {
718                let ptr_i = self.get_mut(i).unwrap() as *mut T;
719                let ptr_j = self.get_mut(j).unwrap() as *mut T;
720                std::ptr::swap(ptr_i, ptr_j);
721            }
722            i += 1;
723            j -= 1;
724        }
725    }
726}
727
728/// Iterator over [`SVec`].
729pub struct SVecIntoIter<T: HasSchema> {
730    svec: SVec<T>,
731    index: usize,
732}
733
734impl<T: HasSchema + Debug> std::fmt::Debug for SVec<T> {
735    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
736        let mut l = f.debug_list();
737        for item in self.iter() {
738            l.entry(item);
739        }
740        l.finish()
741    }
742}
743
744impl<T: HasSchema> From<SVec<T>> for Vec<T> {
745    fn from(svec: SVec<T>) -> Self {
746        let mut vec = Vec::with_capacity(svec.len());
747        for item in svec {
748            vec.push(item);
749        }
750        vec
751    }
752}
753
754impl<T: HasSchema> From<Vec<T>> for SVec<T> {
755    fn from(vec: Vec<T>) -> Self {
756        let mut svec = SVec::new();
757        for item in vec {
758            svec.push(item);
759        }
760        svec
761    }
762}
763
764// Implement IntoIterator for SVec<T>
765impl<T: HasSchema> IntoIterator for SVec<T> {
766    type Item = T;
767    type IntoIter = SVecIntoIter<T>;
768
769    fn into_iter(self) -> Self::IntoIter {
770        SVecIntoIter {
771            svec: self,
772            index: 0,
773        }
774    }
775}
776
777impl<T: HasSchema> Iterator for SVecIntoIter<T> {
778    type Item = T;
779
780    fn next(&mut self) -> Option<Self::Item> {
781        if self.index < self.svec.len() {
782            let item = self.svec.remove(self.index);
783            Some(item)
784        } else {
785            None
786        }
787    }
788
789    fn size_hint(&self) -> (usize, Option<usize>) {
790        let remaining = self.svec.len() - self.index;
791        (remaining, Some(remaining))
792    }
793}
794
795impl<T: HasSchema> Drop for SVecIntoIter<T> {
796    fn drop(&mut self) {
797        // Ensure all remaining elements are properly dropped
798        for _ in self.by_ref() {}
799    }
800}
801
802impl<T: HasSchema, const N: usize> From<[T; N]> for SVec<T> {
803    fn from(arr: [T; N]) -> Self {
804        arr.into_iter().collect()
805    }
806}
807
808impl<T: HasSchema> std::ops::Index<usize> for SVec<T> {
809    type Output = T;
810
811    #[track_caller]
812    fn index(&self, idx: usize) -> &Self::Output {
813        self.get(idx).unwrap()
814    }
815}
816
817impl<T: HasSchema> std::ops::IndexMut<usize> for SVec<T> {
818    #[track_caller]
819    fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
820        self.get_mut(idx).unwrap()
821    }
822}
823
824impl<T: HasSchema> std::ops::Deref for SVec<T> {
825    type Target = [T];
826
827    fn deref(&self) -> &Self::Target {
828        // SOUND: we know that the schema matches T, and the internal buffer of a SchemaVec stores
829        // the types contiguously in memory.
830        unsafe { std::slice::from_raw_parts(self.vec.buffer.as_ptr() as *const T, self.len()) }
831    }
832}
833impl<T: HasSchema> std::ops::DerefMut for SVec<T> {
834    fn deref_mut(&mut self) -> &mut Self::Target {
835        // SOUND: we know that the schema matches T, and the internal buffer of a SchemaVec stores
836        // the types contiguously in memory.
837        unsafe { std::slice::from_raw_parts_mut(self.vec.buffer.as_ptr() as *mut T, self.len()) }
838    }
839}
840
841unsafe impl<T: HasSchema> HasSchema for SVec<T> {
842    fn schema() -> &'static Schema {
843        static S: OnceLock<RwLock<HashMap<TypeId, &'static Schema>>> = OnceLock::new();
844        let schema = {
845            S.get_or_init(default)
846                .read()
847                .get(&TypeId::of::<Self>())
848                .copied()
849        };
850        schema.unwrap_or_else(|| {
851            let schema = SCHEMA_REGISTRY.register(SchemaData {
852                name: type_name::<Self>().into(),
853                full_name: format!("{}::{}", module_path!(), type_name::<Self>()).into(),
854                kind: SchemaKind::Vec(T::schema()),
855                type_id: Some(TypeId::of::<Self>()),
856                clone_fn: Some(<Self as RawClone>::raw_clone_cb()),
857                drop_fn: Some(<Self as RawDrop>::raw_drop_cb()),
858                default_fn: Some(<Self as RawDefault>::raw_default_cb()),
859                hash_fn: Some(unsafe {
860                    Unsafe::new(Box::leak(Box::new(|a| SchemaVec::raw_hash(a))))
861                }),
862                eq_fn: Some(unsafe {
863                    Unsafe::new(Box::leak(Box::new(|a, b| SchemaVec::raw_eq(a, b))))
864                }),
865                type_data: Default::default(),
866            });
867
868            S.get_or_init(default)
869                .write()
870                .insert(TypeId::of::<Self>(), schema);
871
872            schema
873        })
874    }
875}
876
877impl<T: HasSchema> Default for SVec<T> {
878    fn default() -> Self {
879        Self {
880            vec: SchemaVec::new(T::schema()),
881            _phantom: Default::default(),
882        }
883    }
884}
885impl<T: HasSchema> Clone for SVec<T> {
886    fn clone(&self) -> Self {
887        Self {
888            vec: self.vec.clone(),
889            _phantom: self._phantom,
890        }
891    }
892}
893
894impl<'a, T: HasSchema> IntoIterator for &'a SVec<T> {
895    type Item = &'a T;
896    type IntoIter = SVecIter<'a, T>;
897    fn into_iter(self) -> Self::IntoIter {
898        self.iter()
899    }
900}
901impl<'a, T: HasSchema> IntoIterator for &'a mut SVec<T> {
902    type Item = &'a mut T;
903    type IntoIter = SVecIterMut<'a, T>;
904    fn into_iter(self) -> Self::IntoIter {
905        self.iter_mut()
906    }
907}
908
909/// Iterator over items in an [`SVec`].
910pub struct SVecIter<'a, T: HasSchema> {
911    vec: &'a SVec<T>,
912    idx: usize,
913    end: isize,
914}
915impl<'a, T: HasSchema> Iterator for SVecIter<'a, T> {
916    type Item = &'a T;
917
918    fn next(&mut self) -> Option<Self::Item> {
919        if self.end < 0 {
920            return None;
921        }
922        let item = (self.idx <= self.end as usize).then(|| self.vec.get(self.idx).unwrap());
923        if item.is_some() {
924            self.idx += 1;
925        }
926        item
927    }
928}
929impl<'a, T: HasSchema> DoubleEndedIterator for SVecIter<'a, T> {
930    fn next_back(&mut self) -> Option<Self::Item> {
931        if self.end < 0 {
932            return None;
933        }
934        let item =
935            (self.end as usize >= self.idx).then(|| self.vec.get(self.end as usize).unwrap());
936        if item.is_some() {
937            self.end -= 1;
938        }
939        item
940    }
941}
942
943/// Iterator over items in an [`SVec`].
944pub struct SVecIterMut<'a, T: HasSchema> {
945    vec: &'a mut SVec<T>,
946    idx: usize,
947    end: isize,
948}
949impl<'a, T: HasSchema> Iterator for SVecIterMut<'a, T> {
950    type Item = &'a mut T;
951
952    fn next(&mut self) -> Option<Self::Item> {
953        if self.end < 0 {
954            return None;
955        }
956        let item = (self.idx <= self.end as usize).then(|| self.vec.get_mut(self.idx).unwrap());
957        if item.is_some() {
958            self.idx += 1;
959        }
960        // SOUND: we are returning data with the lifetime of the vec which is valid and sound,
961        // assuming we don't return two mutable references to the same item.
962        item.map(|x| unsafe { transmute_lifetime(x) })
963    }
964}
965impl<'a, T: HasSchema> DoubleEndedIterator for SVecIterMut<'a, T> {
966    fn next_back(&mut self) -> Option<Self::Item> {
967        if self.end < 0 {
968            return None;
969        }
970        let item =
971            (self.end as usize >= self.idx).then(|| self.vec.get_mut(self.end as usize).unwrap());
972        if item.is_some() {
973            self.end -= 1;
974        }
975        // SOUND: we are returning data with the lifetime of the vec which is valid and sound,
976        // assuming we don't return two mutable references to the same item.
977        item.map(|x| unsafe { transmute_lifetime(x) })
978    }
979}
980
981/// Helper to transmute a lifetime unsafely.
982///
983/// This is safer than just calling [`transmute`][std::mem::transmute] because it can only transmut
984/// the lifetime, not the type of the reference.
985unsafe fn transmute_lifetime<'b, T>(v: &mut T) -> &'b mut T {
986    std::mem::transmute(v)
987}
988
989#[cfg(test)]
990mod test {
991    use super::*;
992
993    #[test]
994    fn double_ended() {
995        let mut v = [1, 2, 3, 4, 5, 6].into_iter().collect::<SVec<_>>();
996
997        let mut iter = v.iter();
998        assert_eq!(iter.next_back(), Some(&6));
999        assert_eq!(iter.next_back(), Some(&5));
1000        assert_eq!(iter.next(), Some(&1));
1001        assert_eq!(iter.next(), Some(&2));
1002        assert_eq!(iter.next_back(), Some(&4));
1003        assert_eq!(iter.next(), Some(&3));
1004        assert_eq!(iter.next_back(), None);
1005        assert_eq!(iter.next(), None);
1006
1007        let mut iter = v.iter_mut();
1008        assert_eq!(iter.next_back(), Some(&mut 6));
1009        assert_eq!(iter.next_back(), Some(&mut 5));
1010        assert_eq!(iter.next(), Some(&mut 1));
1011        assert_eq!(iter.next(), Some(&mut 2));
1012        assert_eq!(iter.next_back(), Some(&mut 4));
1013        assert_eq!(iter.next(), Some(&mut 3));
1014        assert_eq!(iter.next_back(), None);
1015        assert_eq!(iter.next(), None);
1016
1017        let v = [].into_iter().collect::<SVec<u8>>();
1018        let mut iter = v.iter();
1019        assert_eq!(iter.next(), None);
1020        assert_eq!(iter.next(), None);
1021        assert_eq!(iter.next_back(), None);
1022        let mut iter = v.iter();
1023        assert_eq!(iter.next_back(), None);
1024        assert_eq!(iter.next(), None);
1025    }
1026
1027    #[test]
1028    fn test_vec_and_svec_conversions() {
1029        // Test Vec to SVec conversion
1030        let vec = vec![1, 2, 3, 4, 5];
1031        let svec: SVec<i32> = vec.clone().into();
1032        assert_eq!(svec.len(), 5);
1033        // Test SVec to Vec conversion
1034        let vec_from_svec: Vec<i32> = svec.into();
1035        assert_eq!(vec, vec_from_svec);
1036        // Test direct array conversion to SVec
1037        let svec_direct: SVec<i32> = [11, 12, 13].into();
1038        assert_eq!(svec_direct.len(), 3);
1039        // Test SVec to Vec conversion for array-created SVec
1040        let vec_from_array_svec: Vec<i32> = svec_direct.into();
1041        assert_eq!(vec_from_array_svec, vec![11, 12, 13]);
1042    }
1043
1044    #[test]
1045    fn test_remove() {
1046        let mut svec: SVec<i32> = vec![10, 20, 30, 40, 50].into();
1047
1048        // Remove from the middle
1049        let removed = svec.remove(2);
1050        assert_eq!(removed, 30);
1051        assert_eq!(svec.len(), 4);
1052        assert_eq!(svec[0], 10);
1053
1054        // Remove from the beginning
1055        let removed = svec.remove(0);
1056        assert_eq!(removed, 10);
1057        assert_eq!(svec.len(), 3);
1058        assert_eq!(svec[0], 20);
1059
1060        // Remove from the end
1061        let removed = svec.remove(2);
1062        assert_eq!(removed, 50);
1063        assert_eq!(svec.len(), 2);
1064        assert_eq!(svec[1], 40);
1065
1066        // Test removing the last element
1067        let removed = svec.remove(1);
1068        assert_eq!(removed, 40);
1069        assert_eq!(svec.len(), 1);
1070        assert_eq!(svec[0], 20);
1071
1072        // Test removing the very last element
1073        let removed = svec.remove(0);
1074        assert_eq!(removed, 20);
1075        assert_eq!(svec.len(), 0);
1076    }
1077
1078    #[test]
1079    fn test_svec_operations() {
1080        let mut vec: SVec<i32> = SVec::new();
1081
1082        // Test push and len
1083        vec.push(1);
1084        vec.push(2);
1085        vec.push(3);
1086        assert_eq!(vec.len(), 3);
1087
1088        // Test get
1089        assert_eq!(vec.get(1), Some(&2));
1090        assert_eq!(vec.get(3), None);
1091
1092        // Test remove
1093        let removed = vec.remove(2);
1094        assert_eq!(removed, 3);
1095        assert_eq!(vec.len(), 2);
1096
1097        // Test iteration
1098        let sum: i32 = vec.iter().copied().sum();
1099        assert_eq!(sum, 3); // 1 + 2
1100
1101        // Test extend
1102        vec.extend(vec![5, 6]);
1103        assert_eq!(vec.len(), 4);
1104        assert_eq!(vec.get(2), Some(&5));
1105        assert_eq!(vec.get(3), Some(&6));
1106
1107        // Test retain
1108        vec.retain(|&x| x % 2 == 0);
1109        assert_eq!(vec.len(), 2);
1110        assert_eq!(vec[0], 2);
1111        assert_eq!(vec[1], 6);
1112
1113        // Test retain_mut
1114        vec.retain_mut(|x| {
1115            *x *= 2;
1116            true
1117        });
1118        assert_eq!(vec.len(), 2);
1119        assert_eq!(vec[0], 4);
1120        assert_eq!(vec[1], 12);
1121
1122        // Test truncate
1123        vec.truncate(1);
1124        assert_eq!(vec.len(), 1);
1125        assert_eq!(vec[0], 4);
1126        assert_eq!(vec.get(1), None);
1127
1128        // Prepare for further tests
1129        vec.extend(vec![7, 9, 11]);
1130
1131        // Test first() and first_mut()
1132        assert_eq!(vec.first(), Some(&4));
1133        if let Some(first) = vec.first_mut() {
1134            *first = 1;
1135        }
1136        assert_eq!(vec[0], 1);
1137
1138        // Test last() and last_mut()
1139        assert_eq!(vec.last(), Some(&11));
1140        if let Some(last) = vec.last_mut() {
1141            *last = 15;
1142        }
1143        assert_eq!(vec[3], 15);
1144
1145        // Test pop_if()
1146        assert_eq!(vec.pop_if(|&x| x > 10), Some(15));
1147        assert_eq!(vec.len(), 3);
1148        assert_eq!(vec.pop_if(|&x| x < 0), None);
1149        assert_eq!(vec.len(), 3);
1150
1151        // Test clear
1152        vec.clear();
1153        assert_eq!(vec.len(), 0);
1154        assert!(vec.is_empty());
1155
1156        // Test pop on empty vector
1157        assert_eq!(vec.pop(), None);
1158
1159        // Test Vec and SVec conversions
1160        let original_vec = vec![1, 2, 3, 4, 5];
1161        let svec: SVec<i32> = original_vec.clone().into();
1162        let vec_from_svec: Vec<i32> = svec.into();
1163        assert_eq!(original_vec, vec_from_svec);
1164
1165        // Test reverse
1166        let mut reversed_vec = original_vec.clone();
1167        reversed_vec.reverse();
1168        assert_eq!(reversed_vec, vec![5, 4, 3, 2, 1]);
1169    }
1170
1171    #[test]
1172    fn miri_error_001() {
1173        let mut vec: SVec<i32> = SVec::new();
1174        vec.push(10);
1175        vec.pop();
1176    }
1177}