fixed_slice_vec/
vec.rs

1//! FixedSliceVec is a structure for defining variably populated vectors backed
2//! by a slice of storage capacity.
3use core::borrow::{Borrow, BorrowMut};
4use core::convert::From;
5use core::hash::{Hash, Hasher};
6use core::iter::Extend;
7use core::mem::MaybeUninit;
8use core::ops::{Deref, DerefMut};
9
10/// Vec-like structure backed by a storage slice of possibly uninitialized data.
11///
12/// The maximum length (the capacity) is fixed at runtime to the length of the
13/// provided storage slice.
14pub struct FixedSliceVec<'a, T: Sized> {
15    /// Backing storage, provides capacity
16    storage: &'a mut [MaybeUninit<T>],
17    /// The number of items that have been
18    /// initialized
19    len: usize,
20}
21
22impl<'a, T: Sized> Drop for FixedSliceVec<'a, T> {
23    fn drop(&mut self) {
24        self.clear();
25    }
26}
27
28impl<'a, T: Sized> FixedSliceVec<'a, T> {
29    /// Create a FixedSliceVec backed by a slice of possibly-uninitialized data.
30    /// The backing storage slice is used as capacity for Vec-like operations,
31    ///
32    /// The initial length of the FixedSliceVec is 0.
33    #[inline]
34    pub fn new(storage: &'a mut [MaybeUninit<T>]) -> Self {
35        FixedSliceVec { storage, len: 0 }
36    }
37
38    /// Create a well-aligned FixedSliceVec backed by a slice of the provided bytes.
39    /// The slice is as large as possible given the item type and alignment of
40    /// the provided bytes.
41    ///
42    /// If you are interested in recapturing the prefix and suffix bytes on
43    /// either side of the carved-out FixedSliceVec buffer, consider using `align_from_bytes` instead:
44    ///
45    /// ```
46    /// # let mut bytes = [3u8, 1, 4, 1, 5, 9];
47    /// let vec = unsafe { fixed_slice_vec::FixedSliceVec::from_bytes(&mut bytes[..]) };
48    /// # let vec: fixed_slice_vec::FixedSliceVec<u16> = vec;
49    /// ```
50    ///
51    /// The bytes are treated as if they might be uninitialized, so even if `T` is `u8`,
52    /// the length of the returned `FixedSliceVec` will be zero.
53    ///
54    /// # Safety
55    ///
56    /// If the item type `T` of the FixedSliceVec contains any padding bytes
57    /// then those padding bytes may be observable in the provided slice
58    /// after the `FixedSliceVec` is dropped. Observing padding bytes is
59    /// undefined behavior.
60    #[inline]
61    pub unsafe fn from_bytes(bytes: &'a mut [u8]) -> FixedSliceVec<'a, T> {
62        FixedSliceVec::align_from_bytes(bytes).1
63    }
64
65    /// Create a well-aligned FixedSliceVec backed by a slice of the provided
66    /// uninitialized bytes. The typed slice is as large as possible given its
67    /// item type and the alignment of the provided bytes.
68    ///
69    /// If you are interested in recapturing the prefix and suffix bytes on
70    /// either side of the carved-out FixedSliceVec buffer, consider using `align_from_uninit_bytes`:
71    ///
72    #[inline]
73    pub fn from_uninit_bytes(bytes: &'a mut [MaybeUninit<u8>]) -> FixedSliceVec<'a, T> {
74        FixedSliceVec::align_from_uninit_bytes(bytes).1
75    }
76
77    /// Create a well-aligned FixedSliceVec backed by a slice of the provided bytes.
78    /// The slice is as large as possible given the item type and alignment of
79    /// the provided bytes. Returns the unused prefix and suffix bytes on
80    /// either side of the carved-out FixedSliceVec.
81    ///
82    /// ```
83    /// let mut bytes = [3u8, 1, 4, 1, 5, 9];
84    /// let (prefix, vec, suffix) = unsafe { fixed_slice_vec::FixedSliceVec::align_from_bytes(&mut bytes[..]) };
85    /// let vec: fixed_slice_vec::FixedSliceVec<u16> = vec;
86    /// ```
87    ///
88    /// The bytes are treated as if they might be uninitialized, so even if `T` is `u8`,
89    /// the length of the returned `FixedSliceVec` will be zero.
90    ///
91    /// # Safety
92    ///
93    /// If the item type `T` of the FixedSliceVec contains any padding bytes
94    /// then those padding bytes may be observable in the provided slice
95    /// after the `FixedSliceVec` is dropped. Observing padding bytes is
96    /// undefined behavior.
97    #[inline]
98    pub unsafe fn align_from_bytes(
99        bytes: &'a mut [u8],
100    ) -> (&'a mut [u8], FixedSliceVec<'a, T>, &'a mut [u8]) {
101        let (prefix, storage, suffix) = bytes.align_to_mut();
102        (prefix, FixedSliceVec { storage, len: 0 }, suffix)
103    }
104
105    /// Create a well-aligned FixedSliceVec backed by a slice of the provided bytes.
106    /// The slice is as large as possible given the item type and alignment of
107    /// the provided bytes. Returns the unused prefix and suffix bytes on
108    /// either side of the carved-out FixedSliceVec.
109    ///
110    /// ```
111    /// # use core::mem::MaybeUninit;
112    /// let mut bytes: [MaybeUninit<u8>; 15] = unsafe { MaybeUninit::uninit().assume_init() };
113    /// let (prefix, vec, suffix) = fixed_slice_vec::FixedSliceVec::align_from_uninit_bytes(&mut
114    /// bytes[..]);
115    /// let vec: fixed_slice_vec::FixedSliceVec<u16> = vec;
116    /// ```
117    ///
118    /// The length of the returned `FixedSliceVec` will be zero.
119    #[inline]
120    pub fn align_from_uninit_bytes(
121        bytes: &'a mut [MaybeUninit<u8>],
122    ) -> (
123        &'a mut [MaybeUninit<u8>],
124        FixedSliceVec<'a, T>,
125        &'a mut [MaybeUninit<u8>],
126    ) {
127        let (prefix, storage, suffix) = unsafe { bytes.align_to_mut() };
128        (prefix, FixedSliceVec { storage, len: 0 }, suffix)
129    }
130
131    /// Returns an unsafe mutable pointer to the FixedSliceVec's buffer.
132    ///
133    /// The caller must ensure that the FixedSliceVec and the backing
134    /// storage data for the FixedSliceVec (provided at construction)
135    /// outlives the pointer this function returns.
136    ///
137    /// Furthermore, the contents of the buffer are not guaranteed
138    /// to have been initialized at indices >= len.
139    ///
140    /// # Examples
141    ///
142    /// ```
143    /// use core::mem::MaybeUninit;
144    /// let mut storage: [MaybeUninit<u8>; 16] = unsafe { MaybeUninit::uninit().assume_init() };
145    /// let mut x: fixed_slice_vec::FixedSliceVec<u16> = fixed_slice_vec::FixedSliceVec::from_uninit_bytes(&mut storage[..]);
146    /// assert!(x.try_extend([1u16, 2, 4, 8].iter().copied()).is_ok());
147    /// let size = x.len();
148    /// let x_ptr = x.as_mut_ptr();
149    ///
150    /// // Set elements via raw pointer writes.
151    /// unsafe {
152    ///     for i in 0..size {
153    ///         *x_ptr.add(i) = MaybeUninit::new(i as u16);
154    ///     }
155    /// }
156    /// assert_eq!(&*x, &[0,1,2,3]);
157    /// ```
158    #[inline]
159    pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit<T> {
160        self.storage.as_mut_ptr()
161    }
162    /// Returns a raw pointer to the FixedSliceVec's buffer.
163    ///
164    /// The caller must ensure that the FixedSliceVec and the backing
165    /// storage data for the FixedSliceVec (provided at construction)
166    /// outlives the pointer this function returns.
167    ///
168    /// Furthermore, the contents of the buffer are not guaranteed
169    /// to have been initialized at indices >= len.
170    ///
171    /// The caller must also ensure that the memory the pointer (non-transitively) points to
172    /// is never written to using this pointer or any pointer derived from it.
173    ///
174    /// If you need to mutate the contents of the slice with pointers, use [`as_mut_ptr`].
175    ///
176    /// # Examples
177    ///
178    /// ```
179    /// use core::mem::MaybeUninit;
180    /// let mut storage: [MaybeUninit<u8>; 16] = unsafe { MaybeUninit::uninit().assume_init() };
181    /// let mut x: fixed_slice_vec::FixedSliceVec<u16> = fixed_slice_vec::FixedSliceVec::from_uninit_bytes(&mut storage[..]);
182    /// x.extend([1u16, 2, 4].iter().copied());
183    /// let x_ptr = x.as_ptr();
184    ///
185    /// unsafe {
186    ///     for i in 0..x.len() {
187    ///         assert_eq!((*x_ptr.add(i)).assume_init(), 1 << i);
188    ///     }
189    /// }
190    /// ```
191    ///
192    /// [`as_mut_ptr`]: #method.as_mut_ptr
193    #[inline]
194    pub fn as_ptr(&self) -> *const MaybeUninit<T> {
195        self.storage.as_ptr()
196    }
197
198    /// The length of the FixedSliceVec. The number of initialized
199    /// values that have been added to it.
200    #[inline]
201    pub fn len(&self) -> usize {
202        self.len
203    }
204
205    /// The maximum amount of items that can live in this FixedSliceVec
206    #[inline]
207    pub fn capacity(&self) -> usize {
208        self.storage.len()
209    }
210
211    /// Returns true if there are no items present.
212    #[inline]
213    pub fn is_empty(&self) -> bool {
214        self.len == 0
215    }
216
217    /// Returns true if the FixedSliceVec is full to capacity.
218    #[inline]
219    pub fn is_full(&self) -> bool {
220        self.len == self.capacity()
221    }
222
223    /// Attempt to add a value to the FixedSliceVec.
224    ///
225    /// Returns an error if there is not enough capacity to hold another item.
226    #[inline]
227    pub fn try_push(&mut self, value: T) -> Result<(), StorageError<T>> {
228        if self.is_full() {
229            return Err(StorageError(value));
230        }
231        self.storage[self.len] = MaybeUninit::new(value);
232        self.len += 1;
233        Ok(())
234    }
235
236    /// Attempt to add a value to the FixedSliceVec.
237    ///
238    /// # Panics
239    ///
240    /// Panics if there is not sufficient capacity to hold another item.
241    #[inline]
242    pub fn push(&mut self, value: T) {
243        self.try_push(value).unwrap();
244    }
245
246    /// Attempt to insert a value to the FixedSliceVec.
247    ///
248    /// Returns an error if there is not enough capacity to hold another item.
249    #[inline]
250    pub fn try_insert(&mut self, index: usize, value: T) -> Result<(), StorageError<T>> {
251        if index > self.len() {
252            return Err(StorageError(value));
253        }
254        self.try_push(value)?;
255        self.as_mut_slice()[index..].rotate_right(1);
256        Ok(())
257    }
258
259    /// Inserts a value to the FixedSliceVec.
260    ///
261    /// # Panics
262    ///
263    /// Panics if there is not sufficient capacity to hold another item.
264    #[inline]
265    pub fn insert(&mut self, index: usize, value: T) {
266        self.try_insert(index, value).unwrap()
267    }
268
269    /// Attempt to add as many values as will fit from an iterable.
270    ///
271    /// Returns Ok(()) if all of the items in the iterator can fit into `self`.
272    /// Returns an Err containing the iterator if `self` fills up and there
273    /// are items remaining in the iterator.
274    #[inline]
275    pub fn try_extend(
276        &mut self,
277        iterable: impl IntoIterator<Item = T>,
278    ) -> Result<(), impl Iterator<Item = T>> {
279        let mut iter = iterable.into_iter().peekable();
280        loop {
281            if iter.peek().is_some() {
282                if self.is_full() {
283                    return Err(iter);
284                } else if let Some(item) = iter.next() {
285                    self.storage[self.len] = MaybeUninit::new(item);
286                    self.len += 1;
287                } else {
288                    unreachable!("`FixedSliceVec::try_extend` peeked above to ensure that `next` would return Some")
289                }
290            } else {
291                return Ok(());
292            }
293        }
294    }
295
296    /// Remove the last item from the FixedSliceVec.
297    #[inline]
298    pub fn pop(&mut self) -> Option<T> {
299        if self.len == 0 {
300            return None;
301        }
302        self.len -= 1;
303        Some(unsafe { self.storage[self.len].as_ptr().read() })
304    }
305
306    /// Removes the FixedSliceVec's tracking of all items in it while retaining the
307    /// same capacity.
308    #[inline]
309    pub fn clear(&mut self) {
310        let original_len = self.len;
311        self.len = 0;
312        unsafe {
313            // Note we cannot use the usual DerefMut helper to produce a slice because it relies
314            // on the `len` field, which we have updated above already.
315            // The early setting of `len` is designed to avoid double-free errors if there
316            // is a panic in the middle of the following drop.
317            (core::slice::from_raw_parts_mut(self.storage.as_mut_ptr() as *mut T, original_len)
318                as *mut [T])
319                .drop_in_place();
320        }
321    }
322
323    /// Shortens the FixedSliceVec, keeping the first `len` elements and dropping the rest.
324    ///
325    /// If len is greater than the current length, this has no effect.
326    /// Note that this method has no effect on the capacity of the FixedSliceVec.
327    #[inline]
328    pub fn truncate(&mut self, len: usize) {
329        let original_len = self.len;
330        if len > original_len {
331            return;
332        }
333        self.len = len;
334        unsafe {
335            // Note we cannot use the usual DerefMut helper to produce a slice because it relies
336            // on the `len` field, which we have updated above already.
337            // The early setting of `len` is designed to avoid double-free errors if there
338            // is a panic in the middle of the following drop.
339            (&mut core::slice::from_raw_parts_mut(self.storage.as_mut_ptr() as *mut T, original_len)[len..] as *mut [T]).drop_in_place();
340        }
341    }
342    /// Removes and returns the element at position `index` within the FixedSliceVec,
343    /// shifting all elements after it to the left.
344    ///
345    /// # Panics
346    ///
347    /// Panics if `index` is out of bounds.
348    pub fn remove(&mut self, index: usize) -> T {
349        // Error message and overall impl strategy following along with std vec,
350        if index >= self.len {
351            panic!(
352                "removal index (is {}) should be < len (is {})",
353                index, self.len
354            );
355        }
356        unsafe { self.unchecked_remove(index) }
357    }
358
359    /// Removes and returns the element at position `index` within the FixedSliceVec,
360    /// shifting all elements after it to the left.
361    pub fn try_remove(&mut self, index: usize) -> Result<T, IndexError> {
362        if index >= self.len {
363            return Err(IndexError);
364        }
365        Ok(unsafe { self.unchecked_remove(index) })
366    }
367
368    /// Remove and return an element without checking if it's actually there.
369    #[inline]
370    unsafe fn unchecked_remove(&mut self, index: usize) -> T {
371        let ptr = (self.as_mut_ptr() as *mut T).add(index);
372        let out = core::ptr::read(ptr);
373        core::ptr::copy(ptr.offset(1), ptr, self.len - index - 1);
374        self.len -= 1;
375        out
376    }
377    /// Removes an element from the vector and returns it.
378    ///
379    /// The removed element is replaced by the last element of the vector.
380    ///
381    /// This does not preserve ordering, but is O(1).
382    ///
383    /// # Panics
384    ///
385    /// Panics if `index` is out of bounds.
386    pub fn swap_remove(&mut self, index: usize) -> T {
387        if index >= self.len {
388            panic!(
389                "swap_remove index (is {}) should be < len (is {})",
390                index, self.len
391            );
392        }
393        unsafe { self.unchecked_swap_remove(index) }
394    }
395    /// Removes an element from the vector and returns it.
396    ///
397    /// The removed element is replaced by the last element of the vector.
398    ///
399    /// This does not preserve ordering, but is O(1).
400    pub fn try_swap_remove(&mut self, index: usize) -> Result<T, IndexError> {
401        if index >= self.len {
402            return Err(IndexError);
403        }
404        Ok(unsafe { self.unchecked_swap_remove(index) })
405    }
406
407    /// swap_remove, without the length-checking
408    #[inline]
409    unsafe fn unchecked_swap_remove(&mut self, index: usize) -> T {
410        let target_ptr = (self.as_mut_ptr() as *mut T).add(index);
411        let end_ptr = (self.as_ptr() as *const T).add(self.len - 1);
412        let end_value = core::ptr::read(end_ptr);
413        self.len -= 1;
414        core::ptr::replace(target_ptr, end_value)
415    }
416
417    /// Obtain an immutable slice view on the initialized portion of the
418    /// FixedSliceVec.
419    #[inline]
420    pub fn as_slice(&self) -> &[T] {
421        Deref::deref(self)
422    }
423
424    /// Obtain a mutable slice view on the initialized portion of the
425    /// FixedSliceVec.
426    #[inline]
427    pub fn as_mut_slice(&mut self) -> &mut [T] {
428        DerefMut::deref_mut(self)
429    }
430}
431
432/// Error that occurs when a call that attempts to increase
433/// the number of items in the FixedSliceVec fails
434/// due to insufficient storage capacity.
435#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
436pub struct StorageError<T>(pub T);
437
438impl<T> core::fmt::Debug for StorageError<T> {
439    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
440        f.write_str("Push failed because FixedSliceVec was full")
441    }
442}
443
444/// Error that occurs when a call that attempts to access
445/// the FixedSliceVec in a manner that does not respect
446/// the current length of the vector, i.e. its current
447/// number of initialized items.
448#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
449pub struct IndexError;
450
451impl core::fmt::Debug for IndexError {
452    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
453        f.write_str(
454            "Access to the FixedSliceVec failed because an invalid index or length was provided",
455        )
456    }
457}
458
459impl<'a, T: Sized> From<&'a mut [MaybeUninit<T>]> for FixedSliceVec<'a, T> {
460    #[inline]
461    fn from(v: &'a mut [MaybeUninit<T>]) -> Self {
462        FixedSliceVec { storage: v, len: 0 }
463    }
464}
465
466impl<'a, T: Sized> Hash for FixedSliceVec<'a, T>
467where
468    T: Hash,
469{
470    #[inline]
471    fn hash<H: Hasher>(&self, state: &mut H) {
472        Hash::hash(&**self, state)
473    }
474}
475
476impl<'a, T: Sized> PartialEq for FixedSliceVec<'a, T>
477where
478    T: PartialEq,
479{
480    #[inline]
481    fn eq(&self, other: &Self) -> bool {
482        **self == **other
483    }
484}
485
486impl<'a, T: Sized> PartialEq<[T]> for FixedSliceVec<'a, T>
487where
488    T: PartialEq,
489{
490    #[inline]
491    fn eq(&self, other: &[T]) -> bool {
492        **self == *other
493    }
494}
495
496impl<'a, T: Sized> Eq for FixedSliceVec<'a, T> where T: Eq {}
497
498impl<'a, T: Sized> Borrow<[T]> for FixedSliceVec<'a, T> {
499    #[inline]
500    fn borrow(&self) -> &[T] {
501        self
502    }
503}
504
505impl<'a, T: Sized> BorrowMut<[T]> for FixedSliceVec<'a, T> {
506    #[inline]
507    fn borrow_mut(&mut self) -> &mut [T] {
508        self
509    }
510}
511
512impl<'a, T: Sized> AsRef<[T]> for FixedSliceVec<'a, T> {
513    #[inline]
514    fn as_ref(&self) -> &[T] {
515        self
516    }
517}
518
519impl<'a, T: Sized> AsMut<[T]> for FixedSliceVec<'a, T> {
520    #[inline]
521    fn as_mut(&mut self) -> &mut [T] {
522        self
523    }
524}
525
526impl<'a, T: Sized> core::fmt::Debug for FixedSliceVec<'a, T>
527where
528    T: core::fmt::Debug,
529{
530    #[inline]
531    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
532        (**self).fmt(f)
533    }
534}
535
536impl<'a, T: Sized> PartialOrd for FixedSliceVec<'a, T>
537where
538    T: PartialOrd,
539{
540    #[inline]
541    fn partial_cmp(&self, other: &FixedSliceVec<'a, T>) -> Option<core::cmp::Ordering> {
542        (**self).partial_cmp(other)
543    }
544
545    #[inline]
546    fn lt(&self, other: &Self) -> bool {
547        (**self).lt(other)
548    }
549
550    #[inline]
551    fn le(&self, other: &Self) -> bool {
552        (**self).le(other)
553    }
554
555    #[inline]
556    fn gt(&self, other: &Self) -> bool {
557        (**self).gt(other)
558    }
559
560    #[inline]
561    fn ge(&self, other: &Self) -> bool {
562        (**self).ge(other)
563    }
564}
565
566impl<'a, T: Sized> Deref for FixedSliceVec<'a, T> {
567    type Target = [T];
568    #[inline]
569    fn deref(&self) -> &Self::Target {
570        unsafe { core::slice::from_raw_parts(self.storage.as_ptr() as *const T, self.len) }
571    }
572}
573
574impl<'a, T: Sized> DerefMut for FixedSliceVec<'a, T> {
575    #[inline]
576    fn deref_mut(&mut self) -> &mut [T] {
577        unsafe { core::slice::from_raw_parts_mut(self.storage.as_mut_ptr() as *mut T, self.len) }
578    }
579}
580
581/// Adds as many items from the provided iterable as can fit.
582///
583/// Gives no indication of how many were extracted or if some
584/// could not fit.
585///
586/// Use `FixedSliceVec::try_extend` if you require more fine-
587/// grained signal about the outcome of attempted extension.
588impl<'a, T: Sized> Extend<T> for FixedSliceVec<'a, T> {
589    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
590        let _ = self.try_extend(iter);
591    }
592}
593
594#[cfg(test)]
595mod tests {
596    use super::*;
597
598    #[test]
599    fn from_uninit() {
600        let mut data: [MaybeUninit<u8>; 32] = unsafe { MaybeUninit::uninit().assume_init() };
601        let mut sv: FixedSliceVec<u8> = (&mut data[..]).into();
602        assert_eq!(0, sv.len());
603        assert_eq!(32, sv.capacity());
604        assert!(sv.is_empty());
605        let sv_as_slice: &[u8] = &sv;
606        let empty_slice: &[u8] = &[];
607        assert_eq!(empty_slice, sv_as_slice);
608        assert_eq!(Ok(()), sv.try_push(3));
609        assert_eq!(Ok(()), sv.try_push(1));
610        assert_eq!(Ok(()), sv.try_push(4));
611        let non_empty_slice: &[u8] = &[3u8, 1, 4];
612        assert_eq!(non_empty_slice, &sv as &[u8]);
613        let sv_as_mut_slice: &mut [u8] = &mut sv;
614        sv_as_mut_slice[1] = 2;
615        let non_empty_slice: &[u8] = &[3u8, 2, 4];
616        assert_eq!(non_empty_slice, &sv as &[u8]);
617
618        sv.clear();
619        assert_eq!(0, sv.len());
620        assert!(sv.is_empty());
621    }
622
623    #[test]
624    fn happy_path_from_bytes() {
625        let mut data = [0u8; 31];
626        let mut sv: FixedSliceVec<usize> = unsafe { FixedSliceVec::from_bytes(&mut data[..]) };
627        assert!(sv.is_empty());
628        // capacity might be 0 if miri messes with the align-ability of pointers
629        if sv.capacity() > 0 {
630            for i in 0..sv.capacity() {
631                assert_eq!(Ok(()), sv.try_push(i));
632            }
633        }
634        assert!(sv.is_full());
635    }
636
637    #[test]
638    fn align_captures_suffix_and_prefix() {
639        let mut data = [
640            3u8, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3,
641        ];
642        let original_len = data.len();
643        for i in 0..original_len {
644            for len in 0..original_len - i {
645                let storage = &mut data[i..i + len];
646                let storage_len = storage.len();
647                let (prefix, fixed_slice_vec, suffix): (_, FixedSliceVec<u16>, _) =
648                    unsafe { FixedSliceVec::align_from_bytes(storage) };
649                assert_eq!(
650                    storage_len,
651                    prefix.len() + 2 * fixed_slice_vec.capacity() + suffix.len()
652                );
653            }
654        }
655    }
656    fn uninit_storage() -> [MaybeUninit<u8>; 4] {
657        unsafe { MaybeUninit::uninit().assume_init() }
658    }
659
660    #[test]
661    fn as_ptr_reveals_expected_internal_content() {
662        let expected = [0u8, 1, 2, 3];
663        let mut storage = uninit_storage();
664        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
665        assert!(fsv.try_extend(expected.iter().copied()).is_ok());
666
667        let ptr = fsv.as_ptr();
668        for i in 0..fsv.len() {
669            assert_eq!(expected[i], unsafe { (*ptr.add(i)).assume_init() });
670        }
671
672        let mut fsv = fsv;
673        fsv[3] = 99;
674        assert_eq!(99, unsafe { (*fsv.as_ptr().add(3)).assume_init() })
675    }
676
677    #[test]
678    fn as_mut_ptr_allows_changes_to_internal_content() {
679        let expected = [0u8, 2, 4, 8];
680        let mut storage = uninit_storage();
681        let mut fsv: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
682        assert!(fsv.try_extend(expected.iter().copied()).is_ok());
683
684        assert_eq!(8, unsafe { fsv.as_mut_ptr().add(3).read().assume_init() });
685        unsafe {
686            fsv.as_mut_ptr().add(3).write(MaybeUninit::new(99));
687        }
688        assert_eq!(99, fsv[3]);
689
690        fsv[1] = 200;
691        assert_eq!(200, unsafe { fsv.as_mut_ptr().add(1).read().assume_init() });
692    }
693
694    #[test]
695    fn manual_truncate() {
696        let expected = [0u8, 2, 4, 8];
697        let mut storage = uninit_storage();
698        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
699        assert!(fsv.try_extend(expected.iter().copied()).is_ok());
700
701        fsv.truncate(100);
702        assert_eq!(&[0u8, 2, 4, 8], fsv.as_slice());
703        fsv.truncate(2);
704        assert_eq!(&[0u8, 2], fsv.as_slice());
705        fsv.truncate(2);
706        assert_eq!(&[0u8, 2], fsv.as_slice());
707        fsv.truncate(0);
708        assert!(fsv.is_empty());
709    }
710
711    #[test]
712    fn manual_try_remove() {
713        let expected = [0u8, 2, 4, 8];
714        let mut storage = uninit_storage();
715        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
716        assert!(fsv.try_extend(expected.iter().copied()).is_ok());
717
718        assert_eq!(Err(IndexError), fsv.try_remove(100));
719        assert_eq!(Err(IndexError), fsv.try_remove(4));
720        assert_eq!(&[0u8, 2, 4, 8], fsv.as_slice());
721        assert_eq!(Ok(2), fsv.try_remove(1));
722        assert_eq!(&[0u8, 4, 8], fsv.as_slice());
723    }
724
725    #[test]
726    #[should_panic]
727    fn manual_swap_remove_outside_range() {
728        let mut storage = uninit_storage();
729        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
730        assert!(fsv.try_extend([0u8, 2, 4, 8].iter().copied()).is_ok());
731        fsv.swap_remove(100);
732    }
733
734    #[test]
735    #[should_panic]
736    fn manual_swap_remove_empty() {
737        let mut storage = uninit_storage();
738        let mut fsv: FixedSliceVec<u16> = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
739        assert!(fsv.capacity() > 0);
740        assert_eq!(0, fsv.len());
741        fsv.swap_remove(0);
742    }
743
744    #[test]
745    fn manual_swap_remove_inside_range() {
746        let mut storage = uninit_storage();
747        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
748        assert!(fsv.try_extend([0u8, 2, 4, 8].iter().copied()).is_ok());
749        assert_eq!(&[0u8, 2, 4, 8], fsv.as_slice());
750        assert_eq!(2, fsv.swap_remove(1));
751        assert_eq!(&[0u8, 8, 4], fsv.as_slice());
752        assert_eq!(0, fsv.swap_remove(0));
753        assert_eq!(&[4u8, 8], fsv.as_slice());
754        assert_eq!(4, fsv.swap_remove(0));
755        assert_eq!(&[8u8], fsv.as_slice());
756        assert_eq!(8, fsv.swap_remove(0));
757        assert!(fsv.as_slice().is_empty());
758    }
759
760    #[test]
761    fn manual_try_swap_remove() {
762        let expected = [0u8, 2, 4, 8];
763        let mut storage = uninit_storage();
764        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
765        assert!(fsv.try_extend(expected.iter().copied()).is_ok());
766
767        assert_eq!(Err(IndexError), fsv.try_swap_remove(100));
768        assert_eq!(Err(IndexError), fsv.try_swap_remove(4));
769        assert_eq!(&[0u8, 2, 4, 8], fsv.as_slice());
770        assert_eq!(Ok(2), fsv.try_swap_remove(1));
771        assert_eq!(&[0u8, 8, 4], fsv.as_slice());
772        assert_eq!(Ok(0), fsv.try_swap_remove(0));
773        assert_eq!(&[4u8, 8], fsv.as_slice());
774        assert_eq!(Ok(4), fsv.try_swap_remove(0));
775        assert_eq!(&[8u8], fsv.as_slice());
776        assert_eq!(Ok(8), fsv.try_swap_remove(0));
777        assert!(fsv.as_slice().is_empty());
778        assert_eq!(Err(IndexError), fsv.try_swap_remove(0));
779    }
780
781    #[test]
782    fn try_extend_with_exactly_enough_room() {
783        let expected = [0u8, 2, 4, 8];
784        let mut storage = uninit_storage();
785        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
786        assert!(fsv.try_extend(expected.iter().copied()).is_ok());
787        assert_eq!(&expected[..], &fsv[..]);
788    }
789
790    #[test]
791    fn try_extend_with_more_than_enough_room() {
792        let expected = [0u8, 2, 4, 8];
793        let mut storage: [MaybeUninit<u8>; 100] = unsafe { MaybeUninit::uninit().assume_init() };
794        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
795        assert!(fsv.try_extend(expected.iter().copied()).is_ok());
796        assert_eq!(&expected[..], &fsv[..]);
797    }
798
799    #[test]
800    fn try_extend_with_not_enough_room() {
801        let expected = [0u8, 2, 4, 8];
802        let mut storage: [MaybeUninit<u8>; 2] = unsafe { MaybeUninit::uninit().assume_init() };
803        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
804        let mut out_iter = fsv.try_extend(expected.iter().copied()).unwrap_err();
805        assert_eq!(Some(4), out_iter.next());
806        assert_eq!(Some(8), out_iter.next());
807        assert_eq!(None, out_iter.next());
808        assert_eq!(&expected[0..2], &fsv[..]);
809    }
810    #[test]
811    fn extend_with_exactly_enough_room() {
812        let expected = [0u8, 2, 4, 8];
813        let mut storage = uninit_storage();
814        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
815        fsv.extend(expected.iter().copied());
816        assert_eq!(&expected[..], &fsv[..]);
817    }
818
819    #[test]
820    fn extend_with_more_than_enough_room() {
821        let expected = [0u8, 2, 4, 8];
822        let mut storage: [MaybeUninit<u8>; 100] = unsafe { MaybeUninit::uninit().assume_init() };
823        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
824        fsv.extend(expected.iter().copied());
825        assert_eq!(&expected[..], &fsv[..]);
826    }
827
828    #[test]
829    fn extend_with_not_enough_room() {
830        let expected = [0u8, 2, 4, 8];
831        let mut storage: [MaybeUninit<u8>; 2] = unsafe { MaybeUninit::uninit().assume_init() };
832        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
833        fsv.extend(expected.iter().copied());
834        assert_eq!(&expected[0..2], &fsv[..]);
835    }
836
837    #[test]
838    fn from_uninit_bytes_empty_slice() {
839        let storage: &mut [MaybeUninit<u8>] = &mut [];
840        let mut fsv: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(storage);
841        assert_eq!(0, fsv.capacity());
842        assert_eq!(0, fsv.len());
843        assert!(fsv.try_push(31).is_err());
844    }
845    #[test]
846    fn from_uninit_bytes_smaller_than_item_slice() {
847        let mut storage: [MaybeUninit<u8>; 1] = unsafe { MaybeUninit::uninit().assume_init() };
848        let mut fsv: FixedSliceVec<u16> = FixedSliceVec::from_uninit_bytes(&mut storage);
849        assert_eq!(0, fsv.capacity());
850        assert_eq!(0, fsv.len());
851        assert!(fsv.try_push(31).is_err());
852    }
853    #[test]
854    fn from_uninit_bytes_larger_than_item_slice() {
855        let mut storage: [MaybeUninit<u8>; 9] = unsafe { MaybeUninit::uninit().assume_init() };
856        let mut fsv: FixedSliceVec<u16> = FixedSliceVec::from_uninit_bytes(&mut storage);
857        assert!(fsv.capacity() > 0);
858        assert_eq!(0, fsv.len());
859        assert!(fsv.try_push(31).is_ok());
860        assert_eq!(&[31], &fsv[..]);
861    }
862
863    #[test]
864    fn equality_sanity_checks() {
865        let mut storage_a: [MaybeUninit<u8>; 2] = unsafe { MaybeUninit::uninit().assume_init() };
866        let mut a: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(&mut storage_a);
867        let mut storage_b: [MaybeUninit<u8>; 2] = unsafe { MaybeUninit::uninit().assume_init() };
868        let mut b: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(&mut storage_b);
869
870        assert_eq!(a, b);
871        assert_eq!(&a, &b[..]);
872        assert_eq!(&b, &a[..]);
873        a.push(1u8);
874        assert_ne!(a, b);
875        assert_ne!(&a, &b[..]);
876        assert_ne!(&b, &a[..]);
877        b.push(1u8);
878        assert_eq!(a, b);
879        assert_eq!(&a, &b[..]);
880        assert_eq!(&b, &a[..]);
881    }
882
883    #[test]
884    fn borrow_ish_sanity_checks() {
885        let mut expected = [0u8, 2, 4, 8];
886        let mut storage: [MaybeUninit<u8>; 12] = unsafe { MaybeUninit::uninit().assume_init() };
887        let mut fsv = FixedSliceVec::from_uninit_bytes(&mut storage[..]);
888        fsv.extend(expected.iter().copied());
889
890        assert_eq!(&expected[..], Borrow::<[u8]>::borrow(&fsv));
891        assert_eq!(&mut expected[..], BorrowMut::<[u8]>::borrow_mut(&mut fsv));
892        assert_eq!(&expected[..], fsv.as_ref());
893        assert_eq!(&mut expected[..], fsv.as_mut());
894    }
895
896    #[test]
897    fn comparison_sanity_checks() {
898        let mut storage_a: [MaybeUninit<u8>; 2] = unsafe { MaybeUninit::uninit().assume_init() };
899        let mut a: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(&mut storage_a);
900        let mut storage_b: [MaybeUninit<u8>; 2] = unsafe { MaybeUninit::uninit().assume_init() };
901        let mut b: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(&mut storage_b);
902        use core::cmp::Ordering;
903        assert_eq!(Some(Ordering::Equal), a.partial_cmp(&b));
904        b.push(1);
905        assert!(a.lt(&b));
906        assert!(b.gt(&a));
907        a.push(1);
908        assert!(a.ge(&b));
909        assert!(a.le(&b));
910        a[0] = 2;
911        assert!(a.gt(&b));
912        assert!(b.lt(&a));
913    }
914
915    #[test]
916    fn insertion_sanity_checks() {
917        // Opposite order element addition check
918        let mut storage_a: [MaybeUninit<u8>; 4] = unsafe { MaybeUninit::uninit().assume_init() };
919        let mut a: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(&mut storage_a);
920        let mut storage_b: [MaybeUninit<u8>; 4] = unsafe { MaybeUninit::uninit().assume_init() };
921        let mut b: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(&mut storage_b);
922        assert_eq!(a.as_slice(), b.as_slice(), "Equal sets of 0 elements");
923        a.insert(0usize, 1);
924        a.insert(0usize, 2);
925        a.insert(0usize, 3);
926        a.insert(0usize, 4);
927        b.push(4);
928        b.push(3);
929        b.push(2);
930        b.push(1);
931        assert_eq!(
932            a.as_slice(),
933            b.as_slice(),
934            "Equal sets of 4 elements, added in opposite order"
935        );
936        assert_eq!(a.try_insert(0, 0), b.try_push(0));
937        assert_eq!(
938            a.as_slice(),
939            &[4u8, 3u8, 2u8, 1u8],
940            "Insert should not modify until required capacity is verified."
941        );
942        assert_eq!(
943            b.as_slice(),
944            &[4u8, 3u8, 2u8, 1u8],
945            "Push should not modify until required capacity is verified."
946        );
947
948        // Mixed insertion order check
949        a.clear();
950        assert!(
951            a.try_insert(1usize, 55).is_err(),
952            "Given `n` elements and index `0` to `n-1` the maximum insert index is `n` (push)"
953        );
954        a.insert(0usize, 4);
955        a.insert(1usize, 2);
956        a.insert(1usize, 3);
957        a.insert(3usize, 1);
958        assert_eq!(
959            a.as_slice(),
960            &[4u8, 3u8, 2u8, 1u8],
961            "Alternate insert order should yeild same result."
962        );
963
964        // Zero sized buffer check
965        let mut storage_c: [MaybeUninit<u8>; 0] = unsafe { MaybeUninit::uninit().assume_init() };
966        let mut c: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(&mut storage_c);
967        assert!(
968            c.try_insert(0usize, 1).is_err(),
969            "Zero sized buffer should fail on insert"
970        );
971
972        // Zero remaining capacity check
973        let mut storage_d: [MaybeUninit<u8>; 1] = unsafe { MaybeUninit::uninit().assume_init() };
974        let mut d: FixedSliceVec<u8> = FixedSliceVec::from_uninit_bytes(&mut storage_d);
975        d.push(1);
976        assert!(
977            d.try_insert(0usize, 2).is_err(),
978            "Zero remaining capacity should fail an insert"
979        );
980    }
981}