Coverage Report

Created: 2025-02-21 07:11

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