• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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")]
6 mod databake;
7 
8 #[cfg(feature = "serde")]
9 mod serde;
10 
11 mod slice;
12 
13 pub use slice::ZeroSlice;
14 pub use slice::ZeroSliceIter;
15 
16 use crate::ule::*;
17 #[cfg(feature = "alloc")]
18 use alloc::borrow::Cow;
19 #[cfg(feature = "alloc")]
20 use alloc::vec::Vec;
21 use core::cmp::{Ord, Ordering, PartialOrd};
22 use core::fmt;
23 #[cfg(feature = "alloc")]
24 use core::iter::FromIterator;
25 use core::marker::PhantomData;
26 use core::num::NonZeroUsize;
27 use core::ops::Deref;
28 use 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.
92 pub struct ZeroVec<'a, T>
93 where
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.
107 unsafe 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
109 unsafe impl<'a, T: AsULE> Sync for ZeroVec<'a, T> where T::ULE: Sync {}
110 
111 impl<'a, T: AsULE> Deref for ZeroVec<'a, T> {
112     type Target = ZeroSlice<T>;
113     #[inline]
deref(&self) -> &Self::Target114     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]
128 struct 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 
138 impl<U> EyepatchHackVector<U> {
139     // Return a slice to the inner data for an arbitrary caller-specified lifetime
140     #[inline]
as_arbitrary_slice<'a>(&self) -> &'a [U]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]
as_slice<'a>(&'a self) -> &'a [U]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")]
get_vec(&self) -> Vec<U>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")]
171 impl<U> Drop for EyepatchHackVector<U> {
172     #[inline]
drop(&mut self)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 
183 impl<'a, T: AsULE> Clone for ZeroVec<'a, T> {
clone(&self) -> Self184     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 
201 impl<'a, T: AsULE> AsRef<ZeroSlice<T>> for ZeroVec<'a, T> {
as_ref(&self) -> &ZeroSlice<T>202     fn as_ref(&self) -> &ZeroSlice<T> {
203         self.as_slice()
204     }
205 }
206 
207 impl<T> fmt::Debug for ZeroVec<'_, T>
208 where
209     T: AsULE + fmt::Debug,
210 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result211     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 
225 impl<T> Eq for ZeroVec<'_, T> where T: AsULE + Eq {}
226 
227 impl<'a, 'b, T> PartialEq<ZeroVec<'b, T>> for ZeroVec<'a, T>
228 where
229     T: AsULE + PartialEq,
230 {
231     #[inline]
eq(&self, other: &ZeroVec<'b, T>) -> bool232     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 
238 impl<T> PartialEq<&[T]> for ZeroVec<'_, T>
239 where
240     T: AsULE + PartialEq,
241 {
242     #[inline]
eq(&self, other: &&[T]) -> bool243     fn eq(&self, other: &&[T]) -> bool {
244         self.iter().eq(other.iter().copied())
245     }
246 }
247 
248 impl<T, const N: usize> PartialEq<[T; N]> for ZeroVec<'_, T>
249 where
250     T: AsULE + PartialEq,
251 {
252     #[inline]
eq(&self, other: &[T; N]) -> bool253     fn eq(&self, other: &[T; N]) -> bool {
254         self.iter().eq(other.iter().copied())
255     }
256 }
257 
258 impl<'a, T: AsULE> Default for ZeroVec<'a, T> {
259     #[inline]
default() -> Self260     fn default() -> Self {
261         Self::new()
262     }
263 }
264 
265 impl<'a, T: AsULE + PartialOrd> PartialOrd for ZeroVec<'a, T> {
partial_cmp(&self, other: &Self) -> Option<Ordering>266     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
267         self.iter().partial_cmp(other.iter())
268     }
269 }
270 
271 impl<'a, T: AsULE + Ord> Ord for ZeroVec<'a, T> {
cmp(&self, other: &Self) -> Ordering272     fn cmp(&self, other: &Self) -> Ordering {
273         self.iter().cmp(other.iter())
274     }
275 }
276 
277 impl<'a, T: AsULE> AsRef<[T::ULE]> for ZeroVec<'a, T> {
as_ref(&self) -> &[T::ULE]278     fn as_ref(&self) -> &[T::ULE] {
279         self.as_ule_slice()
280     }
281 }
282 
283 impl<'a, T: AsULE> From<&'a [T::ULE]> for ZeroVec<'a, T> {
from(other: &'a [T::ULE]) -> Self284     fn from(other: &'a [T::ULE]) -> Self {
285         ZeroVec::new_borrowed(other)
286     }
287 }
288 
289 #[cfg(feature = "alloc")]
290 impl<'a, T: AsULE> From<Vec<T::ULE>> for ZeroVec<'a, T> {
from(other: Vec<T::ULE>) -> Self291     fn from(other: Vec<T::ULE>) -> Self {
292         ZeroVec::new_owned(other)
293     }
294 }
295 
296 impl<'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]
new() -> Self308     pub const fn new() -> Self {
309         Self::new_borrowed(&[])
310     }
311 
312     /// Same as `ZeroSlice::len`, which is available through `Deref` and not `const`.
const_len(&self) -> usize313     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")]
new_owned(vec: Vec<T::ULE>) -> Self324     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]
new_borrowed(slice: &'a [T::ULE]) -> Self346     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")]
with_capacity(capacity: usize) -> Self363     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     /// ```
parse_bytes(bytes: &'a [u8]) -> Result<Self, UleError>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()`].
from_bytes_unchecked(bytes: &'a [u8]) -> Self401     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")]
into_bytes(self) -> ZeroVec<'a, u8>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]
as_slice(&self) -> &ZeroSlice<T>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")]
cast<P>(self) -> ZeroVec<'a, P> where P: AsULE<ULE = T::ULE>,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")]
try_into_converted<P: AsULE>(self) -> Result<ZeroVec<'a, P>, UleError>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]
is_owned(&self) -> bool602     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]
as_maybe_borrowed(&self) -> Option<&'a ZeroSlice<T>>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]
owned_capacity(&self) -> Option<NonZeroUsize>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 
658 impl<'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")]
try_into_parsed<T: AsULE>(self) -> Result<ZeroVec<'a, T>, UleError>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 
705 impl<'a, T> ZeroVec<'a, T>
706 where
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")]
alloc_from_slice(other: &[T]) -> Self729     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")]
to_vec(&self) -> Vec<T>747     pub fn to_vec(&self) -> Vec<T> {
748         self.iter().collect()
749     }
750 }
751 
752 impl<'a, T> ZeroVec<'a, T>
753 where
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]
try_from_slice(slice: &'a [T]) -> Option<Self>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")]
from_slice_or_alloc(slice: &'a [T]) -> Self801     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 
806 impl<'a, T> ZeroVec<'a, T>
807 where
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")]
for_each_mut(&mut self, mut f: impl FnMut(&mut T))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")]
try_for_each_mut<E>( &mut self, mut f: impl FnMut(&mut T) -> Result<(), E>, ) -> Result<(), E>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")]
into_owned(self) -> ZeroVec<'static, T>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")]
with_mut<R>(&mut self, f: impl FnOnce(&mut alloc::vec::Vec<T::ULE>) -> R) -> R917     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")]
to_mut_slice(&mut self) -> &mut [T::ULE]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.
clear(&mut self)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")]
take_first(&mut self) -> Option<T>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")]
take_last(&mut self) -> Option<T>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")]
into_cow(self) -> Cow<'a, [T::ULE]>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")]
1074 impl<T: AsULE> FromIterator<T> for ZeroVec<'_, T> {
1075     /// Creates an owned [`ZeroVec`] from an iterator of values.
from_iter<I>(iter: I) -> Self where I: IntoIterator<Item = T>,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]
1122 macro_rules! zeroslice {
1123     () => (
1124         $crate::ZeroSlice::new_empty()
1125     );
1126     ($aligned:ty; $convert:expr; [$($x:expr),+ $(,)?]) => (
1127         $crate::ZeroSlice::<$aligned>::from_ule_slice(
1128             {const X: &[<$aligned as $crate::ule::AsULE>::ULE] = &[
1129                 $($convert($x)),*
1130             ]; X}
1131         )
1132     );
1133 }
1134 
1135 /// Creates a borrowed `ZeroVec`. Convenience wrapper for `zeroslice!(...).as_zerovec()`. The value
1136 /// will be created at compile-time, meaning that all arguments must also be constant.
1137 ///
1138 /// See [`zeroslice!`](crate::zeroslice) for more information.
1139 ///
1140 /// # Examples
1141 ///
1142 /// ```
1143 /// use zerovec::{ZeroVec, zerovec, ule::AsULE};
1144 ///
1145 /// const SIGNATURE: ZeroVec<char> = zerovec!(char; <char as AsULE>::ULE::from_aligned; ['a', 'y', 'e', '✌']);
1146 /// assert!(!SIGNATURE.is_owned());
1147 ///
1148 /// const EMPTY: ZeroVec<u32> = zerovec![];
1149 /// assert!(!EMPTY.is_owned());
1150 /// ```
1151 #[macro_export]
1152 macro_rules! zerovec {
1153     () => (
1154         $crate::ZeroVec::new()
1155     );
1156     ($aligned:ty; $convert:expr; [$($x:expr),+ $(,)?]) => (
1157         $crate::zeroslice![$aligned; $convert; [$($x),+]].as_zerovec()
1158     );
1159 }
1160 
1161 #[cfg(test)]
1162 mod tests {
1163     use super::*;
1164     use crate::samples::*;
1165 
1166     #[test]
test_get()1167     fn test_get() {
1168         {
1169             let zerovec = ZeroVec::from_slice_or_alloc(TEST_SLICE);
1170             assert_eq!(zerovec.get(0), Some(TEST_SLICE[0]));
1171             assert_eq!(zerovec.get(1), Some(TEST_SLICE[1]));
1172             assert_eq!(zerovec.get(2), Some(TEST_SLICE[2]));
1173         }
1174         {
1175             let zerovec = ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap();
1176             assert_eq!(zerovec.get(0), Some(TEST_SLICE[0]));
1177             assert_eq!(zerovec.get(1), Some(TEST_SLICE[1]));
1178             assert_eq!(zerovec.get(2), Some(TEST_SLICE[2]));
1179         }
1180     }
1181 
1182     #[test]
test_binary_search()1183     fn test_binary_search() {
1184         {
1185             let zerovec = ZeroVec::from_slice_or_alloc(TEST_SLICE);
1186             assert_eq!(Ok(3), zerovec.binary_search(&0x0e0d0c));
1187             assert_eq!(Err(3), zerovec.binary_search(&0x0c0d0c));
1188         }
1189         {
1190             let zerovec = ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap();
1191             assert_eq!(Ok(3), zerovec.binary_search(&0x0e0d0c));
1192             assert_eq!(Err(3), zerovec.binary_search(&0x0c0d0c));
1193         }
1194     }
1195 
1196     #[test]
test_odd_alignment()1197     fn test_odd_alignment() {
1198         assert_eq!(
1199             Some(0x020100),
1200             ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap().get(0)
1201         );
1202         assert_eq!(
1203             Some(0x04000201),
1204             ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[1..77])
1205                 .unwrap()
1206                 .get(0)
1207         );
1208         assert_eq!(
1209             Some(0x05040002),
1210             ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[2..78])
1211                 .unwrap()
1212                 .get(0)
1213         );
1214         assert_eq!(
1215             Some(0x06050400),
1216             ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[3..79])
1217                 .unwrap()
1218                 .get(0)
1219         );
1220         assert_eq!(
1221             Some(0x060504),
1222             ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[4..])
1223                 .unwrap()
1224                 .get(0)
1225         );
1226         assert_eq!(
1227             Some(0x4e4d4c00),
1228             ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[75..79])
1229                 .unwrap()
1230                 .get(0)
1231         );
1232         assert_eq!(
1233             Some(0x4e4d4c00),
1234             ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[3..79])
1235                 .unwrap()
1236                 .get(18)
1237         );
1238         assert_eq!(
1239             Some(0x4e4d4c),
1240             ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[76..])
1241                 .unwrap()
1242                 .get(0)
1243         );
1244         assert_eq!(
1245             Some(0x4e4d4c),
1246             ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap().get(19)
1247         );
1248         // TODO(#1144): Check for correct slice length in RawBytesULE
1249         // assert_eq!(
1250         //     None,
1251         //     ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[77..])
1252         //         .unwrap()
1253         //         .get(0)
1254         // );
1255         assert_eq!(
1256             None,
1257             ZeroVec::<u32>::parse_bytes(TEST_BUFFER_LE).unwrap().get(20)
1258         );
1259         assert_eq!(
1260             None,
1261             ZeroVec::<u32>::parse_bytes(&TEST_BUFFER_LE[3..79])
1262                 .unwrap()
1263                 .get(19)
1264         );
1265     }
1266 }
1267