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