zerovec/zerovec/
mod.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5#[cfg(feature = "databake")]
6mod databake;
7
8#[cfg(feature = "serde")]
9mod serde;
10
11mod slice;
12
13pub use slice::ZeroSlice;
14pub use slice::ZeroSliceIter;
15
16use crate::ule::*;
17#[cfg(feature = "alloc")]
18use alloc::borrow::Cow;
19#[cfg(feature = "alloc")]
20use alloc::vec::Vec;
21use core::cmp::{Ord, Ordering, PartialOrd};
22use core::fmt;
23#[cfg(feature = "alloc")]
24use core::iter::FromIterator;
25use core::marker::PhantomData;
26use core::num::NonZeroUsize;
27use core::ops::Deref;
28use core::ptr::NonNull;
29
30/// A zero-copy, byte-aligned vector for fixed-width types.
31///
32/// `ZeroVec<T>` is designed as a drop-in replacement for `Vec<T>` in situations where it is
33/// desirable to borrow data from an unaligned byte slice, such as zero-copy deserialization.
34///
35/// `T` must implement [`AsULE`], which is auto-implemented for a number of built-in types,
36/// including all fixed-width multibyte integers. For variable-width types like [`str`],
37/// see [`VarZeroVec`](crate::VarZeroVec). [`zerovec::make_ule`](crate::make_ule) may
38/// be used to automatically implement [`AsULE`] for a type and generate the underlying [`ULE`] type.
39///
40/// Typically, the zero-copy equivalent of a `Vec<T>` will simply be `ZeroVec<'a, T>`.
41///
42/// Most of the methods on `ZeroVec<'a, T>` come from its [`Deref`] implementation to [`ZeroSlice<T>`](ZeroSlice).
43///
44/// For creating zero-copy vectors of fixed-size types, see [`VarZeroVec`](crate::VarZeroVec).
45///
46/// `ZeroVec<T>` behaves much like [`Cow`](alloc::borrow::Cow), where it can be constructed from
47/// owned data (and then mutated!) but can also borrow from some buffer.
48///
49/// # Example
50///
51/// ```
52/// use zerovec::ZeroVec;
53///
54/// // The little-endian bytes correspond to the numbers on the following line.
55/// let nums: &[u16] = &[211, 281, 421, 461];
56///
57/// #[derive(serde::Serialize, serde::Deserialize)]
58/// struct Data<'a> {
59///     #[serde(borrow)]
60///     nums: ZeroVec<'a, u16>,
61/// }
62///
63/// // The owned version will allocate
64/// let data = Data {
65///     nums: ZeroVec::alloc_from_slice(nums),
66/// };
67/// let bincode_bytes =
68///     bincode::serialize(&data).expect("Serialization should be successful");
69///
70/// // Will deserialize without allocations
71/// let deserialized: Data = bincode::deserialize(&bincode_bytes)
72///     .expect("Deserialization should be successful");
73///
74/// // This deserializes without allocation!
75/// assert!(!deserialized.nums.is_owned());
76/// assert_eq!(deserialized.nums.get(2), Some(421));
77/// assert_eq!(deserialized.nums, nums);
78/// ```
79///
80/// [`ule`]: crate::ule
81///
82/// # How it Works
83///
84/// `ZeroVec<T>` represents a slice of `T` as a slice of `T::ULE`. The difference between `T` and
85/// `T::ULE` is that `T::ULE` must be encoded in little-endian with 1-byte alignment. When accessing
86/// items from `ZeroVec<T>`, we fetch the `T::ULE`, convert it on the fly to `T`, and return `T` by
87/// value.
88///
89/// Benchmarks can be found in the project repository, with some results found in the [crate-level documentation](crate).
90///
91/// See [the design doc](https://github.com/unicode-org/icu4x/blob/main/utils/zerovec/design_doc.md) for more details.
92pub struct ZeroVec<'a, T>
93where
94    T: AsULE,
95{
96    vector: EyepatchHackVector<T::ULE>,
97
98    /// Marker type, signalling variance and dropck behavior
99    /// by containing all potential types this type represents
100    marker1: PhantomData<T::ULE>,
101    marker2: PhantomData<&'a T::ULE>,
102}
103
104// Send inherits as long as all fields are Send, but also references are Send only
105// when their contents are Sync (this is the core purpose of Sync), so
106// we need a Send+Sync bound since this struct can logically be a vector or a slice.
107unsafe impl<'a, T: AsULE> Send for ZeroVec<'a, T> where T::ULE: Send + Sync {}
108// Sync typically inherits as long as all fields are Sync
109unsafe impl<'a, T: AsULE> Sync for ZeroVec<'a, T> where T::ULE: Sync {}
110
111impl<'a, T: AsULE> Deref for ZeroVec<'a, T> {
112    type Target = ZeroSlice<T>;
113    #[inline]
114    fn deref(&self) -> &Self::Target {
115        self.as_slice()
116    }
117}
118
119// Represents an unsafe potentially-owned vector/slice type, without a lifetime
120// working around dropck limitations.
121//
122// Must either be constructed by deconstructing a Vec<U>, or from &[U] with capacity set to
123// zero. Should not outlive its source &[U] in the borrowed case; this type does not in
124// and of itself uphold this guarantee, but the .as_slice() method assumes it.
125//
126// After https://github.com/rust-lang/rust/issues/34761 stabilizes,
127// we should remove this type and use #[may_dangle]
128struct EyepatchHackVector<U> {
129    /// Pointer to data
130    /// This pointer is *always* valid, the reason it is represented as a raw pointer
131    /// is that it may logically represent an `&[T::ULE]` or the ptr,len of a `Vec<T::ULE>`
132    buf: NonNull<[U]>,
133    #[cfg(feature = "alloc")]
134    /// Borrowed if zero. Capacity of buffer above if not
135    capacity: usize,
136}
137
138impl<U> EyepatchHackVector<U> {
139    // Return a slice to the inner data for an arbitrary caller-specified lifetime
140    #[inline]
141    unsafe fn as_arbitrary_slice<'a>(&self) -> &'a [U] {
142        self.buf.as_ref()
143    }
144    // Return a slice to the inner data
145    #[inline]
146    const fn as_slice<'a>(&'a self) -> &'a [U] {
147        // Note: self.buf.as_ref() is not const until 1.73
148        unsafe { &*(self.buf.as_ptr() as *const [U]) }
149    }
150
151    /// Return this type as a vector
152    ///
153    /// Data MUST be known to be owned beforehand
154    ///
155    /// Because this borrows self, this is effectively creating two owners to the same
156    /// data, make sure that `self` is cleaned up after this
157    ///
158    /// (this does not simply take `self` since then it wouldn't be usable from the Drop impl)
159    #[cfg(feature = "alloc")]
160    unsafe fn get_vec(&self) -> Vec<U> {
161        debug_assert!(self.capacity != 0);
162        let slice: &[U] = self.as_slice();
163        let len = slice.len();
164        // Safety: we are assuming owned, and in owned cases
165        // this always represents a valid vector
166        Vec::from_raw_parts(self.buf.as_ptr() as *mut U, len, self.capacity)
167    }
168}
169
170#[cfg(feature = "alloc")]
171impl<U> Drop for EyepatchHackVector<U> {
172    #[inline]
173    fn drop(&mut self) {
174        if self.capacity != 0 {
175            unsafe {
176                // we don't need to clean up self here since we're already in a Drop impl
177                let _ = self.get_vec();
178            }
179        }
180    }
181}
182
183impl<'a, T: AsULE> Clone for ZeroVec<'a, T> {
184    fn clone(&self) -> Self {
185        #[cfg(feature = "alloc")]
186        if self.is_owned() {
187            return ZeroVec::new_owned(self.as_ule_slice().into());
188        }
189        Self {
190            vector: EyepatchHackVector {
191                buf: self.vector.buf,
192                #[cfg(feature = "alloc")]
193                capacity: 0,
194            },
195            marker1: PhantomData,
196            marker2: PhantomData,
197        }
198    }
199}
200
201impl<'a, T: AsULE> AsRef<ZeroSlice<T>> for ZeroVec<'a, T> {
202    fn as_ref(&self) -> &ZeroSlice<T> {
203        self.as_slice()
204    }
205}
206
207impl<T> fmt::Debug for ZeroVec<'_, T>
208where
209    T: AsULE + fmt::Debug,
210{
211    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
212        write!(f, "ZeroVec([")?;
213        let mut first = true;
214        for el in self.iter() {
215            if !first {
216                write!(f, ", ")?;
217            }
218            write!(f, "{el:?}")?;
219            first = false;
220        }
221        write!(f, "])")
222    }
223}
224
225impl<T> Eq for ZeroVec<'_, T> where T: AsULE + Eq {}
226
227impl<'a, 'b, T> PartialEq<ZeroVec<'b, T>> for ZeroVec<'a, T>
228where
229    T: AsULE + PartialEq,
230{
231    #[inline]
232    fn eq(&self, other: &ZeroVec<'b, T>) -> bool {
233        // Note: T implements PartialEq but not T::ULE
234        self.iter().eq(other.iter())
235    }
236}
237
238impl<T> PartialEq<&[T]> for ZeroVec<'_, T>
239where
240    T: AsULE + PartialEq,
241{
242    #[inline]
243    fn eq(&self, other: &&[T]) -> bool {
244        self.iter().eq(other.iter().copied())
245    }
246}
247
248impl<T, const N: usize> PartialEq<[T; N]> for ZeroVec<'_, T>
249where
250    T: AsULE + PartialEq,
251{
252    #[inline]
253    fn eq(&self, other: &[T; N]) -> bool {
254        self.iter().eq(other.iter().copied())
255    }
256}
257
258impl<'a, T: AsULE> Default for ZeroVec<'a, T> {
259    #[inline]
260    fn default() -> Self {
261        Self::new()
262    }
263}
264
265impl<'a, T: AsULE + PartialOrd> PartialOrd for ZeroVec<'a, T> {
266    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
267        self.iter().partial_cmp(other.iter())
268    }
269}
270
271impl<'a, T: AsULE + Ord> Ord for ZeroVec<'a, T> {
272    fn cmp(&self, other: &Self) -> Ordering {
273        self.iter().cmp(other.iter())
274    }
275}
276
277impl<'a, T: AsULE> AsRef<[T::ULE]> for ZeroVec<'a, T> {
278    fn as_ref(&self) -> &[T::ULE] {
279        self.as_ule_slice()
280    }
281}
282
283impl<'a, T: AsULE> From<&'a [T::ULE]> for ZeroVec<'a, T> {
284    fn from(other: &'a [T::ULE]) -> Self {
285        ZeroVec::new_borrowed(other)
286    }
287}
288
289#[cfg(feature = "alloc")]
290impl<'a, T: AsULE> From<Vec<T::ULE>> for ZeroVec<'a, T> {
291    fn from(other: Vec<T::ULE>) -> Self {
292        ZeroVec::new_owned(other)
293    }
294}
295
296impl<'a, T: AsULE> ZeroVec<'a, T> {
297    /// Creates a new, borrowed, empty `ZeroVec<T>`.
298    ///
299    /// # Examples
300    ///
301    /// ```
302    /// use zerovec::ZeroVec;
303    ///
304    /// let zv: ZeroVec<u16> = ZeroVec::new();
305    /// assert!(zv.is_empty());
306    /// ```
307    #[inline]
308    pub const fn new() -> Self {
309        Self::new_borrowed(&[])
310    }
311
312    /// Same as `ZeroSlice::len`, which is available through `Deref` and not `const`.
313    pub const fn const_len(&self) -> usize {
314        self.vector.as_slice().len()
315    }
316
317    /// Creates a new owned `ZeroVec` using an existing
318    /// allocated backing buffer
319    ///
320    /// If you have a slice of `&[T]`s, prefer using
321    /// [`Self::alloc_from_slice()`].
322    #[inline]
323    #[cfg(feature = "alloc")]
324    pub fn new_owned(vec: Vec<T::ULE>) -> Self {
325        // Deconstruct the vector into parts
326        // This is the only part of the code that goes from Vec
327        // to ZeroVec, all other such operations should use this function
328        let capacity = vec.capacity();
329        let len = vec.len();
330        let ptr = core::mem::ManuallyDrop::new(vec).as_mut_ptr();
331        // Safety: `ptr` comes from Vec::as_mut_ptr, which says:
332        // "Returns an unsafe mutable pointer to the vector’s buffer,
333        // or a dangling raw pointer valid for zero sized reads"
334        let ptr = unsafe { NonNull::new_unchecked(ptr) };
335        let buf = NonNull::slice_from_raw_parts(ptr, len);
336        Self {
337            vector: EyepatchHackVector { buf, capacity },
338            marker1: PhantomData,
339            marker2: PhantomData,
340        }
341    }
342
343    /// Creates a new borrowed `ZeroVec` using an existing
344    /// backing buffer
345    #[inline]
346    pub const fn new_borrowed(slice: &'a [T::ULE]) -> Self {
347        // Safety: references in Rust cannot be null.
348        // The safe function `impl From<&T> for NonNull<T>` is not const.
349        let slice = unsafe { NonNull::new_unchecked(slice as *const [_] as *mut [_]) };
350        Self {
351            vector: EyepatchHackVector {
352                buf: slice,
353                #[cfg(feature = "alloc")]
354                capacity: 0,
355            },
356            marker1: PhantomData,
357            marker2: PhantomData,
358        }
359    }
360
361    /// Creates a new, owned, empty `ZeroVec<T>`, with a certain capacity pre-allocated.
362    #[cfg(feature = "alloc")]
363    pub fn with_capacity(capacity: usize) -> Self {
364        Self::new_owned(Vec::with_capacity(capacity))
365    }
366
367    /// Parses a `&[u8]` buffer into a `ZeroVec<T>`.
368    ///
369    /// This function is infallible for built-in integer types, but fallible for other types,
370    /// such as `char`. For more information, see [`ULE::parse_bytes_to_slice`].
371    ///
372    /// The bytes within the byte buffer must remain constant for the life of the ZeroVec.
373    ///
374    /// # Endianness
375    ///
376    /// The byte buffer must be encoded in little-endian, even if running in a big-endian
377    /// environment. This ensures a consistent representation of data across platforms.
378    ///
379    /// # Example
380    ///
381    /// ```
382    /// use zerovec::ZeroVec;
383    ///
384    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
385    /// let zerovec: ZeroVec<u16> =
386    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
387    ///
388    /// assert!(!zerovec.is_owned());
389    /// assert_eq!(zerovec.get(2), Some(421));
390    /// ```
391    pub fn parse_bytes(bytes: &'a [u8]) -> Result<Self, UleError> {
392        let slice: &'a [T::ULE] = T::ULE::parse_bytes_to_slice(bytes)?;
393        Ok(Self::new_borrowed(slice))
394    }
395
396    /// Uses a `&[u8]` buffer as a `ZeroVec<T>` without any verification.
397    ///
398    /// # Safety
399    ///
400    /// `bytes` need to be an output from [`ZeroSlice::as_bytes()`].
401    pub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
402        // &[u8] and &[T::ULE] are the same slice with different length metadata.
403        Self::new_borrowed(core::slice::from_raw_parts(
404            bytes.as_ptr() as *const T::ULE,
405            bytes.len() / core::mem::size_of::<T::ULE>(),
406        ))
407    }
408
409    /// Converts a `ZeroVec<T>` into a `ZeroVec<u8>`, retaining the current ownership model.
410    ///
411    /// Note that the length of the ZeroVec may change.
412    ///
413    /// # Examples
414    ///
415    /// Convert a borrowed `ZeroVec`:
416    ///
417    /// ```
418    /// use zerovec::ZeroVec;
419    ///
420    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
421    /// let zerovec: ZeroVec<u16> =
422    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
423    /// let zv_bytes = zerovec.into_bytes();
424    ///
425    /// assert!(!zv_bytes.is_owned());
426    /// assert_eq!(zv_bytes.get(0), Some(0xD3));
427    /// ```
428    ///
429    /// Convert an owned `ZeroVec`:
430    ///
431    /// ```
432    /// use zerovec::ZeroVec;
433    ///
434    /// let nums: &[u16] = &[211, 281, 421, 461];
435    /// let zerovec = ZeroVec::alloc_from_slice(nums);
436    /// let zv_bytes = zerovec.into_bytes();
437    ///
438    /// assert!(zv_bytes.is_owned());
439    /// assert_eq!(zv_bytes.get(0), Some(0xD3));
440    /// ```
441    #[cfg(feature = "alloc")]
442    pub fn into_bytes(self) -> ZeroVec<'a, u8> {
443        use alloc::borrow::Cow;
444        match self.into_cow() {
445            Cow::Borrowed(slice) => {
446                let bytes: &'a [u8] = T::ULE::slice_as_bytes(slice);
447                ZeroVec::new_borrowed(bytes)
448            }
449            Cow::Owned(vec) => {
450                let bytes = Vec::from(T::ULE::slice_as_bytes(&vec));
451                ZeroVec::new_owned(bytes)
452            }
453        }
454    }
455
456    /// Returns this [`ZeroVec`] as a [`ZeroSlice`].
457    ///
458    /// To get a reference with a longer lifetime from a borrowed [`ZeroVec`],
459    /// use [`ZeroVec::as_maybe_borrowed`].
460    #[inline]
461    pub const fn as_slice(&self) -> &ZeroSlice<T> {
462        let slice: &[T::ULE] = self.vector.as_slice();
463        ZeroSlice::from_ule_slice(slice)
464    }
465
466    /// Casts a `ZeroVec<T>` to a compatible `ZeroVec<P>`.
467    ///
468    /// `T` and `P` are compatible if they have the same `ULE` representation.
469    ///
470    /// If the `ULE`s of `T` and `P` are different types but have the same size,
471    /// use [`Self::try_into_converted()`].
472    ///
473    /// # Examples
474    ///
475    /// ```
476    /// use zerovec::ZeroVec;
477    ///
478    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
479    ///
480    /// let zerovec_u16: ZeroVec<u16> =
481    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
482    /// assert_eq!(zerovec_u16.get(3), Some(32973));
483    ///
484    /// let zerovec_i16: ZeroVec<i16> = zerovec_u16.cast();
485    /// assert_eq!(zerovec_i16.get(3), Some(-32563));
486    /// ```
487    #[cfg(feature = "alloc")]
488    pub fn cast<P>(self) -> ZeroVec<'a, P>
489    where
490        P: AsULE<ULE = T::ULE>,
491    {
492        match self.into_cow() {
493            Cow::Owned(v) => ZeroVec::new_owned(v),
494            Cow::Borrowed(v) => ZeroVec::new_borrowed(v),
495        }
496    }
497
498    /// Converts a `ZeroVec<T>` into a `ZeroVec<P>`, retaining the current ownership model.
499    ///
500    /// If `T` and `P` have the exact same `ULE`, use [`Self::cast()`].
501    ///
502    /// # Panics
503    ///
504    /// Panics if `T::ULE` and `P::ULE` are not the same size.
505    ///
506    /// # Examples
507    ///
508    /// Convert a borrowed `ZeroVec`:
509    ///
510    /// ```
511    /// use zerovec::ZeroVec;
512    ///
513    /// let bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x49, 0xF6, 0x01];
514    /// let zv_char: ZeroVec<char> =
515    ///     ZeroVec::parse_bytes(bytes).expect("valid code points");
516    /// let zv_u8_3: ZeroVec<[u8; 3]> =
517    ///     zv_char.try_into_converted().expect("infallible conversion");
518    ///
519    /// assert!(!zv_u8_3.is_owned());
520    /// assert_eq!(zv_u8_3.get(0), Some([0x7F, 0xF3, 0x01]));
521    /// ```
522    ///
523    /// Convert an owned `ZeroVec`:
524    ///
525    /// ```
526    /// use zerovec::ZeroVec;
527    ///
528    /// let chars: &[char] = &['🍿', '🙉'];
529    /// let zv_char = ZeroVec::alloc_from_slice(chars);
530    /// let zv_u8_3: ZeroVec<[u8; 3]> =
531    ///     zv_char.try_into_converted().expect("length is divisible");
532    ///
533    /// assert!(zv_u8_3.is_owned());
534    /// assert_eq!(zv_u8_3.get(0), Some([0x7F, 0xF3, 0x01]));
535    /// ```
536    ///
537    /// If the types are not the same size, we refuse to convert:
538    ///
539    /// ```should_panic
540    /// use zerovec::ZeroVec;
541    ///
542    /// let bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x49, 0xF6, 0x01];
543    /// let zv_char: ZeroVec<char> =
544    ///     ZeroVec::parse_bytes(bytes).expect("valid code points");
545    ///
546    /// // Panics! core::mem::size_of::<char::ULE> != core::mem::size_of::<u16::ULE>
547    /// zv_char.try_into_converted::<u16>();
548    /// ```
549    ///
550    /// Instead, convert to bytes and then parse:
551    ///
552    /// ```
553    /// use zerovec::ZeroVec;
554    ///
555    /// let bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x49, 0xF6, 0x01];
556    /// let zv_char: ZeroVec<char> =
557    ///     ZeroVec::parse_bytes(bytes).expect("valid code points");
558    /// let zv_u16: ZeroVec<u16> =
559    ///     zv_char.into_bytes().try_into_parsed().expect("infallible");
560    ///
561    /// assert!(!zv_u16.is_owned());
562    /// assert_eq!(zv_u16.get(0), Some(0xF37F));
563    /// ```
564    #[cfg(feature = "alloc")]
565    pub fn try_into_converted<P: AsULE>(self) -> Result<ZeroVec<'a, P>, UleError> {
566        assert_eq!(
567            core::mem::size_of::<<T as AsULE>::ULE>(),
568            core::mem::size_of::<<P as AsULE>::ULE>()
569        );
570        match self.into_cow() {
571            Cow::Borrowed(old_slice) => {
572                let bytes: &'a [u8] = T::ULE::slice_as_bytes(old_slice);
573                let new_slice = P::ULE::parse_bytes_to_slice(bytes)?;
574                Ok(ZeroVec::new_borrowed(new_slice))
575            }
576            Cow::Owned(old_vec) => {
577                let bytes: &[u8] = T::ULE::slice_as_bytes(&old_vec);
578                P::ULE::validate_bytes(bytes)?;
579                // Feature "vec_into_raw_parts" is not yet stable (#65816). Polyfill:
580                let (ptr, len, cap) = {
581                    // Take ownership of the pointer
582                    let mut v = core::mem::ManuallyDrop::new(old_vec);
583                    // Fetch the pointer, length, and capacity
584                    (v.as_mut_ptr(), v.len(), v.capacity())
585                };
586                // Safety checklist for Vec::from_raw_parts:
587                // 1. ptr came from a Vec<T>
588                // 2. P and T are asserted above to be the same size
589                // 3. length is what it was before
590                // 4. capacity is what it was before
591                let new_vec = unsafe {
592                    let ptr = ptr as *mut P::ULE;
593                    Vec::from_raw_parts(ptr, len, cap)
594                };
595                Ok(ZeroVec::new_owned(new_vec))
596            }
597        }
598    }
599
600    /// Check if this type is fully owned
601    #[inline]
602    pub fn is_owned(&self) -> bool {
603        #[cfg(feature = "alloc")]
604        return self.vector.capacity != 0;
605        #[cfg(not(feature = "alloc"))]
606        return false;
607    }
608
609    /// If this is a borrowed [`ZeroVec`], return it as a slice that covers
610    /// its lifetime parameter.
611    ///
612    /// To infallibly get a [`ZeroSlice`] with a shorter lifetime, use
613    /// [`ZeroVec::as_slice`].
614    #[inline]
615    pub fn as_maybe_borrowed(&self) -> Option<&'a ZeroSlice<T>> {
616        if self.is_owned() {
617            None
618        } else {
619            // We can extend the lifetime of the slice to 'a
620            // since we know it is borrowed
621            let ule_slice = unsafe { self.vector.as_arbitrary_slice() };
622            Some(ZeroSlice::from_ule_slice(ule_slice))
623        }
624    }
625
626    /// If the ZeroVec is owned, returns the capacity of the vector.
627    ///
628    /// Otherwise, if the ZeroVec is borrowed, returns `None`.
629    ///
630    /// # Examples
631    ///
632    /// ```
633    /// use zerovec::ZeroVec;
634    ///
635    /// let mut zv = ZeroVec::<u8>::new_borrowed(&[0, 1, 2, 3]);
636    /// assert!(!zv.is_owned());
637    /// assert_eq!(zv.owned_capacity(), None);
638    ///
639    /// // Convert to owned without appending anything
640    /// zv.with_mut(|v| ());
641    /// assert!(zv.is_owned());
642    /// assert_eq!(zv.owned_capacity(), Some(4.try_into().unwrap()));
643    ///
644    /// // Double the size by appending
645    /// zv.with_mut(|v| v.push(0));
646    /// assert!(zv.is_owned());
647    /// assert_eq!(zv.owned_capacity(), Some(8.try_into().unwrap()));
648    /// ```
649    #[inline]
650    pub fn owned_capacity(&self) -> Option<NonZeroUsize> {
651        #[cfg(feature = "alloc")]
652        return NonZeroUsize::try_from(self.vector.capacity).ok();
653        #[cfg(not(feature = "alloc"))]
654        return None;
655    }
656}
657
658impl<'a> ZeroVec<'a, u8> {
659    /// Converts a `ZeroVec<u8>` into a `ZeroVec<T>`, retaining the current ownership model.
660    ///
661    /// Note that the length of the ZeroVec may change.
662    ///
663    /// # Examples
664    ///
665    /// Convert a borrowed `ZeroVec`:
666    ///
667    /// ```
668    /// use zerovec::ZeroVec;
669    ///
670    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
671    /// let zv_bytes = ZeroVec::new_borrowed(bytes);
672    /// let zerovec: ZeroVec<u16> = zv_bytes.try_into_parsed().expect("infallible");
673    ///
674    /// assert!(!zerovec.is_owned());
675    /// assert_eq!(zerovec.get(0), Some(211));
676    /// ```
677    ///
678    /// Convert an owned `ZeroVec`:
679    ///
680    /// ```
681    /// use zerovec::ZeroVec;
682    ///
683    /// let bytes: Vec<u8> = vec![0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
684    /// let zv_bytes = ZeroVec::new_owned(bytes);
685    /// let zerovec: ZeroVec<u16> = zv_bytes.try_into_parsed().expect("infallible");
686    ///
687    /// assert!(zerovec.is_owned());
688    /// assert_eq!(zerovec.get(0), Some(211));
689    /// ```
690    #[cfg(feature = "alloc")]
691    pub fn try_into_parsed<T: AsULE>(self) -> Result<ZeroVec<'a, T>, UleError> {
692        match self.into_cow() {
693            Cow::Borrowed(bytes) => {
694                let slice: &'a [T::ULE] = T::ULE::parse_bytes_to_slice(bytes)?;
695                Ok(ZeroVec::new_borrowed(slice))
696            }
697            Cow::Owned(vec) => {
698                let slice = Vec::from(T::ULE::parse_bytes_to_slice(&vec)?);
699                Ok(ZeroVec::new_owned(slice))
700            }
701        }
702    }
703}
704
705impl<'a, T> ZeroVec<'a, T>
706where
707    T: AsULE,
708{
709    /// Creates a `ZeroVec<T>` from a `&[T]` by allocating memory.
710    ///
711    /// This function results in an `Owned` instance of `ZeroVec<T>`.
712    ///
713    /// # Example
714    ///
715    /// ```
716    /// use zerovec::ZeroVec;
717    ///
718    /// // The little-endian bytes correspond to the numbers on the following line.
719    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
720    /// let nums: &[u16] = &[211, 281, 421, 461];
721    ///
722    /// let zerovec = ZeroVec::alloc_from_slice(nums);
723    ///
724    /// assert!(zerovec.is_owned());
725    /// assert_eq!(bytes, zerovec.as_bytes());
726    /// ```
727    #[inline]
728    #[cfg(feature = "alloc")]
729    pub fn alloc_from_slice(other: &[T]) -> Self {
730        Self::new_owned(other.iter().copied().map(T::to_unaligned).collect())
731    }
732
733    /// Creates a `Vec<T>` from a `ZeroVec<T>`.
734    ///
735    /// # Example
736    ///
737    /// ```
738    /// use zerovec::ZeroVec;
739    ///
740    /// let nums: &[u16] = &[211, 281, 421, 461];
741    /// let vec: Vec<u16> = ZeroVec::alloc_from_slice(nums).to_vec();
742    ///
743    /// assert_eq!(nums, vec.as_slice());
744    /// ```
745    #[inline]
746    #[cfg(feature = "alloc")]
747    pub fn to_vec(&self) -> Vec<T> {
748        self.iter().collect()
749    }
750}
751
752impl<'a, T> ZeroVec<'a, T>
753where
754    T: EqULE,
755{
756    /// Attempts to create a `ZeroVec<'a, T>` from a `&'a [T]` by borrowing the argument.
757    ///
758    /// If this is not possible, such as on a big-endian platform, `None` is returned.
759    ///
760    /// # Example
761    ///
762    /// ```
763    /// use zerovec::ZeroVec;
764    ///
765    /// // The little-endian bytes correspond to the numbers on the following line.
766    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
767    /// let nums: &[u16] = &[211, 281, 421, 461];
768    ///
769    /// if let Some(zerovec) = ZeroVec::try_from_slice(nums) {
770    ///     assert!(!zerovec.is_owned());
771    ///     assert_eq!(bytes, zerovec.as_bytes());
772    /// }
773    /// ```
774    #[inline]
775    pub fn try_from_slice(slice: &'a [T]) -> Option<Self> {
776        T::slice_to_unaligned(slice).map(|ule_slice| Self::new_borrowed(ule_slice))
777    }
778
779    /// Creates a `ZeroVec<'a, T>` from a `&'a [T]`, either by borrowing the argument or by
780    /// allocating a new vector.
781    ///
782    /// This is a cheap operation on little-endian platforms, falling back to a more expensive
783    /// operation on big-endian platforms.
784    ///
785    /// # Example
786    ///
787    /// ```
788    /// use zerovec::ZeroVec;
789    ///
790    /// // The little-endian bytes correspond to the numbers on the following line.
791    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
792    /// let nums: &[u16] = &[211, 281, 421, 461];
793    ///
794    /// let zerovec = ZeroVec::from_slice_or_alloc(nums);
795    ///
796    /// // Note: zerovec could be either borrowed or owned.
797    /// assert_eq!(bytes, zerovec.as_bytes());
798    /// ```
799    #[inline]
800    #[cfg(feature = "alloc")]
801    pub fn from_slice_or_alloc(slice: &'a [T]) -> Self {
802        Self::try_from_slice(slice).unwrap_or_else(|| Self::alloc_from_slice(slice))
803    }
804}
805
806impl<'a, T> ZeroVec<'a, T>
807where
808    T: AsULE,
809{
810    /// Mutates each element according to a given function, meant to be
811    /// a more convenient version of calling `.iter_mut()` with
812    /// [`ZeroVec::with_mut()`] which serves fewer use cases.
813    ///
814    /// This will convert the ZeroVec into an owned ZeroVec if not already the case.
815    ///
816    /// # Example
817    ///
818    /// ```
819    /// use zerovec::ZeroVec;
820    ///
821    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
822    /// let mut zerovec: ZeroVec<u16> =
823    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
824    ///
825    /// zerovec.for_each_mut(|item| *item += 1);
826    ///
827    /// assert_eq!(zerovec.to_vec(), &[212, 282, 422, 462]);
828    /// assert!(zerovec.is_owned());
829    /// ```
830    #[inline]
831    #[cfg(feature = "alloc")]
832    pub fn for_each_mut(&mut self, mut f: impl FnMut(&mut T)) {
833        self.to_mut_slice().iter_mut().for_each(|item| {
834            let mut aligned = T::from_unaligned(*item);
835            f(&mut aligned);
836            *item = aligned.to_unaligned()
837        })
838    }
839
840    /// Same as [`ZeroVec::for_each_mut()`], but bubbles up errors.
841    ///
842    /// # Example
843    ///
844    /// ```
845    /// use zerovec::ZeroVec;
846    ///
847    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
848    /// let mut zerovec: ZeroVec<u16> =
849    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
850    ///
851    /// zerovec.try_for_each_mut(|item| {
852    ///     *item = item.checked_add(1).ok_or(())?;
853    ///     Ok(())
854    /// })?;
855    ///
856    /// assert_eq!(zerovec.to_vec(), &[212, 282, 422, 462]);
857    /// assert!(zerovec.is_owned());
858    /// # Ok::<(), ()>(())
859    /// ```
860    #[inline]
861    #[cfg(feature = "alloc")]
862    pub fn try_for_each_mut<E>(
863        &mut self,
864        mut f: impl FnMut(&mut T) -> Result<(), E>,
865    ) -> Result<(), E> {
866        self.to_mut_slice().iter_mut().try_for_each(|item| {
867            let mut aligned = T::from_unaligned(*item);
868            f(&mut aligned)?;
869            *item = aligned.to_unaligned();
870            Ok(())
871        })
872    }
873
874    /// Converts a borrowed ZeroVec to an owned ZeroVec. No-op if already owned.
875    ///
876    /// # Example
877    ///
878    /// ```
879    /// use zerovec::ZeroVec;
880    ///
881    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
882    /// let zerovec: ZeroVec<u16> =
883    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
884    /// assert!(!zerovec.is_owned());
885    ///
886    /// let owned = zerovec.into_owned();
887    /// assert!(owned.is_owned());
888    /// ```
889    #[cfg(feature = "alloc")]
890    pub fn into_owned(self) -> ZeroVec<'static, T> {
891        use alloc::borrow::Cow;
892        match self.into_cow() {
893            Cow::Owned(vec) => ZeroVec::new_owned(vec),
894            Cow::Borrowed(b) => ZeroVec::new_owned(b.into()),
895        }
896    }
897
898    /// Allows the ZeroVec to be mutated by converting it to an owned variant, and producing
899    /// a mutable vector of ULEs. If you only need a mutable slice, consider using [`Self::to_mut_slice()`]
900    /// instead.
901    ///
902    /// # Example
903    ///
904    /// ```rust
905    /// # use crate::zerovec::ule::AsULE;
906    /// use zerovec::ZeroVec;
907    ///
908    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
909    /// let mut zerovec: ZeroVec<u16> =
910    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
911    /// assert!(!zerovec.is_owned());
912    ///
913    /// zerovec.with_mut(|v| v.push(12_u16.to_unaligned()));
914    /// assert!(zerovec.is_owned());
915    /// ```
916    #[cfg(feature = "alloc")]
917    pub fn with_mut<R>(&mut self, f: impl FnOnce(&mut alloc::vec::Vec<T::ULE>) -> R) -> R {
918        use alloc::borrow::Cow;
919        // We're in danger if f() panics whilst we've moved a vector out of self;
920        // replace it with an empty dummy vector for now
921        let this = core::mem::take(self);
922        let mut vec = match this.into_cow() {
923            Cow::Owned(v) => v,
924            Cow::Borrowed(s) => s.into(),
925        };
926        let ret = f(&mut vec);
927        *self = Self::new_owned(vec);
928        ret
929    }
930
931    /// Allows the ZeroVec to be mutated by converting it to an owned variant (if necessary)
932    /// and returning a slice to its backing buffer. [`Self::with_mut()`] allows for mutation
933    /// of the vector itself.
934    ///
935    /// # Example
936    ///
937    /// ```rust
938    /// # use crate::zerovec::ule::AsULE;
939    /// use zerovec::ZeroVec;
940    ///
941    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
942    /// let mut zerovec: ZeroVec<u16> =
943    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
944    /// assert!(!zerovec.is_owned());
945    ///
946    /// zerovec.to_mut_slice()[1] = 5u16.to_unaligned();
947    /// assert!(zerovec.is_owned());
948    /// ```
949    #[cfg(feature = "alloc")]
950    pub fn to_mut_slice(&mut self) -> &mut [T::ULE] {
951        if !self.is_owned() {
952            // `buf` is either a valid vector or slice of `T::ULE`s, either
953            // way it's always valid
954            let slice = self.vector.as_slice();
955            *self = ZeroVec::new_owned(slice.into());
956        }
957        unsafe { self.vector.buf.as_mut() }
958    }
959    /// Remove all elements from this ZeroVec and reset it to an empty borrowed state.
960    pub fn clear(&mut self) {
961        *self = Self::new_borrowed(&[])
962    }
963
964    /// Removes the first element of the ZeroVec. The ZeroVec remains in the same
965    /// borrowed or owned state.
966    ///
967    /// # Examples
968    ///
969    /// ```
970    /// # use crate::zerovec::ule::AsULE;
971    /// use zerovec::ZeroVec;
972    ///
973    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
974    /// let mut zerovec: ZeroVec<u16> =
975    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
976    /// assert!(!zerovec.is_owned());
977    ///
978    /// let first = zerovec.take_first().unwrap();
979    /// assert_eq!(first, 0x00D3);
980    /// assert!(!zerovec.is_owned());
981    ///
982    /// let mut zerovec = zerovec.into_owned();
983    /// assert!(zerovec.is_owned());
984    /// let first = zerovec.take_first().unwrap();
985    /// assert_eq!(first, 0x0119);
986    /// assert!(zerovec.is_owned());
987    /// ```
988    #[cfg(feature = "alloc")]
989    pub fn take_first(&mut self) -> Option<T> {
990        match core::mem::take(self).into_cow() {
991            Cow::Owned(mut vec) => {
992                if vec.is_empty() {
993                    return None;
994                }
995                let ule = vec.remove(0);
996                let rv = T::from_unaligned(ule);
997                *self = ZeroVec::new_owned(vec);
998                Some(rv)
999            }
1000            Cow::Borrowed(b) => {
1001                let (ule, remainder) = b.split_first()?;
1002                let rv = T::from_unaligned(*ule);
1003                *self = ZeroVec::new_borrowed(remainder);
1004                Some(rv)
1005            }
1006        }
1007    }
1008
1009    /// Removes the last element of the ZeroVec. The ZeroVec remains in the same
1010    /// borrowed or owned state.
1011    ///
1012    /// # Examples
1013    ///
1014    /// ```
1015    /// # use crate::zerovec::ule::AsULE;
1016    /// use zerovec::ZeroVec;
1017    ///
1018    /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
1019    /// let mut zerovec: ZeroVec<u16> =
1020    ///     ZeroVec::parse_bytes(bytes).expect("infallible");
1021    /// assert!(!zerovec.is_owned());
1022    ///
1023    /// let last = zerovec.take_last().unwrap();
1024    /// assert_eq!(last, 0x01CD);
1025    /// assert!(!zerovec.is_owned());
1026    ///
1027    /// let mut zerovec = zerovec.into_owned();
1028    /// assert!(zerovec.is_owned());
1029    /// let last = zerovec.take_last().unwrap();
1030    /// assert_eq!(last, 0x01A5);
1031    /// assert!(zerovec.is_owned());
1032    /// ```
1033    #[cfg(feature = "alloc")]
1034    pub fn take_last(&mut self) -> Option<T> {
1035        match core::mem::take(self).into_cow() {
1036            Cow::Owned(mut vec) => {
1037                let ule = vec.pop()?;
1038                let rv = T::from_unaligned(ule);
1039                *self = ZeroVec::new_owned(vec);
1040                Some(rv)
1041            }
1042            Cow::Borrowed(b) => {
1043                let (ule, remainder) = b.split_last()?;
1044                let rv = T::from_unaligned(*ule);
1045                *self = ZeroVec::new_borrowed(remainder);
1046                Some(rv)
1047            }
1048        }
1049    }
1050
1051    /// Converts the type into a `Cow<'a, [T::ULE]>`, which is
1052    /// the logical equivalent of this type's internal representation
1053    #[inline]
1054    #[cfg(feature = "alloc")]
1055    pub fn into_cow(self) -> Cow<'a, [T::ULE]> {
1056        let this = core::mem::ManuallyDrop::new(self);
1057        if this.is_owned() {
1058            let vec = unsafe {
1059                // safe to call: we know it's owned,
1060                // and `self`/`this` are thenceforth no longer used or dropped
1061                { this }.vector.get_vec()
1062            };
1063            Cow::Owned(vec)
1064        } else {
1065            // We can extend the lifetime of the slice to 'a
1066            // since we know it is borrowed
1067            let slice = unsafe { { this }.vector.as_arbitrary_slice() };
1068            Cow::Borrowed(slice)
1069        }
1070    }
1071}
1072
1073#[cfg(feature = "alloc")]
1074impl<T: AsULE> FromIterator<T> for ZeroVec<'_, T> {
1075    /// Creates an owned [`ZeroVec`] from an iterator of values.
1076    fn from_iter<I>(iter: I) -> Self
1077    where
1078        I: IntoIterator<Item = T>,
1079    {
1080        ZeroVec::new_owned(iter.into_iter().map(|t| t.to_unaligned()).collect())
1081    }
1082}
1083
1084/// Convenience wrapper for [`ZeroSlice::from_ule_slice`]. The value will be created at compile-time,
1085/// meaning that all arguments must also be constant.
1086///
1087/// # Arguments
1088///
1089/// * `$aligned` - The type of an element in its canonical, aligned form, e.g., `char`.
1090/// * `$convert` - A const function that converts an `$aligned` into its unaligned equivalent, e.g.,
1091///   const fn from_aligned(a: CanonicalType) -> CanonicalType::ULE`.
1092/// * `$x` - The elements that the `ZeroSlice` will hold.
1093///
1094/// # Examples
1095///
1096/// Using array-conversion functions provided by this crate:
1097///
1098/// ```
1099/// use zerovec::{ZeroSlice, zeroslice, ule::AsULE};
1100///
1101/// const SIGNATURE: &ZeroSlice<char> = zeroslice!(char; <char as AsULE>::ULE::from_aligned; ['b', 'y', 'e', '✌']);
1102/// const EMPTY: &ZeroSlice<u32> = zeroslice![];
1103///
1104/// let empty: &ZeroSlice<u32> = zeroslice![];
1105/// let nums = zeroslice!(u32; <u32 as AsULE>::ULE::from_unsigned; [1, 2, 3, 4, 5]);
1106/// assert_eq!(nums.last().unwrap(), 5);
1107/// ```
1108///
1109/// Using a custom array-conversion function:
1110///
1111/// ```
1112/// use zerovec::{ule::AsULE, ule::RawBytesULE, zeroslice, ZeroSlice};
1113///
1114/// const fn be_convert(num: i16) -> <i16 as AsULE>::ULE {
1115///     RawBytesULE(num.to_be_bytes())
1116/// }
1117///
1118/// const NUMBERS_BE: &ZeroSlice<i16> =
1119///     zeroslice!(i16; be_convert; [1, -2, 3, -4, 5]);
1120/// ```
1121#[macro_export]
1122macro_rules! zeroslice {
1123    () => {
1124        $crate::ZeroSlice::new_empty()
1125    };
1126    ($aligned:ty; $convert:expr; [$($x:expr),+ $(,)?]) => {
1127        $crate::ZeroSlice::<$aligned>::from_ule_slice(const { &[$($convert($x)),*] })
1128    };
1129}
1130
1131/// Creates a borrowed `ZeroVec`. Convenience wrapper for `zeroslice!(...).as_zerovec()`. The value
1132/// will be created at compile-time, meaning that all arguments must also be constant.
1133///
1134/// See [`zeroslice!`](crate::zeroslice) for more information.
1135///
1136/// # Examples
1137///
1138/// ```
1139/// use zerovec::{ZeroVec, zerovec, ule::AsULE};
1140///
1141/// const SIGNATURE: ZeroVec<char> = zerovec!(char; <char as AsULE>::ULE::from_aligned; ['a', 'y', 'e', '✌']);
1142/// assert!(!SIGNATURE.is_owned());
1143///
1144/// const EMPTY: ZeroVec<u32> = zerovec![];
1145/// assert!(!EMPTY.is_owned());
1146/// ```
1147#[macro_export]
1148macro_rules! zerovec {
1149    () => (
1150        $crate::ZeroVec::new()
1151    );
1152    ($aligned:ty; $convert:expr; [$($x:expr),+ $(,)?]) => (
1153        $crate::zeroslice![$aligned; $convert; [$($x),+]].as_zerovec()
1154    );
1155}
1156
1157#[cfg(test)]
1158mod tests {
1159    use super::*;
1160    use crate::samples::*;
1161
1162    #[test]
1163    fn test_get() {
1164        {
1165            let zerovec = ZeroVec::from_slice_or_alloc(TEST_SLICE);
1166            assert_eq!(zerovec.get(0), Some(TEST_SLICE[0]));
1167            assert_eq!(zerovec.get(1), Some(TEST_SLICE[1]));
1168            assert_eq!(zerovec.get(2), Some(TEST_SLICE[2]));
1169        }
1170        {
1171            let zerovec = ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap();
1172            assert_eq!(zerovec.get(0), Some(TEST_SLICE[0]));
1173            assert_eq!(zerovec.get(1), Some(TEST_SLICE[1]));
1174            assert_eq!(zerovec.get(2), Some(TEST_SLICE[2]));
1175        }
1176    }
1177
1178    #[test]
1179    fn test_binary_search() {
1180        {
1181            let zerovec = ZeroVec::from_slice_or_alloc(TEST_SLICE);
1182            assert_eq!(Ok(3), zerovec.binary_search(&0x0e0d0c));
1183            assert_eq!(Err(3), zerovec.binary_search(&0x0c0d0c));
1184        }
1185        {
1186            let zerovec = ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap();
1187            assert_eq!(Ok(3), zerovec.binary_search(&0x0e0d0c));
1188            assert_eq!(Err(3), zerovec.binary_search(&0x0c0d0c));
1189        }
1190    }
1191
1192    #[test]
1193    fn test_odd_alignment() {
1194        assert_eq!(
1195            Some(0x020100),
1196            ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap().get(0)
1197        );
1198        assert_eq!(
1199            Some(0x04000201),
1200            ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[1..77])
1201                .unwrap()
1202                .get(0)
1203        );
1204        assert_eq!(
1205            Some(0x05040002),
1206            ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[2..78])
1207                .unwrap()
1208                .get(0)
1209        );
1210        assert_eq!(
1211            Some(0x06050400),
1212            ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[3..79])
1213                .unwrap()
1214                .get(0)
1215        );
1216        assert_eq!(
1217            Some(0x060504),
1218            ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[4..])
1219                .unwrap()
1220                .get(0)
1221        );
1222        assert_eq!(
1223            Some(0x4e4d4c00),
1224            ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[75..79])
1225                .unwrap()
1226                .get(0)
1227        );
1228        assert_eq!(
1229            Some(0x4e4d4c00),
1230            ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[3..79])
1231                .unwrap()
1232                .get(18)
1233        );
1234        assert_eq!(
1235            Some(0x4e4d4c),
1236            ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[76..])
1237                .unwrap()
1238                .get(0)
1239        );
1240        assert_eq!(
1241            Some(0x4e4d4c),
1242            ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap().get(19)
1243        );
1244        // TODO(#1144): Check for correct slice length in RawBytesULE
1245        // assert_eq!(
1246        //     None,
1247        //     ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[77..])
1248        //         .unwrap()
1249        //         .get(0)
1250        // );
1251        assert_eq!(
1252            None,
1253            ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap().get(20)
1254        );
1255        assert_eq!(
1256            None,
1257            ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[3..79])
1258                .unwrap()
1259                .get(19)
1260        );
1261    }
1262}