Coverage Report

Created: 2025-05-08 06:26

/rust/registry/src/index.crates.io-6f17d22bba15001f/zerovec-0.10.4/src/varzerovec/vec.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
use crate::ule::*;
6
7
use alloc::vec::Vec;
8
use core::cmp::{Ord, Ordering, PartialOrd};
9
use core::fmt;
10
use core::ops::Deref;
11
12
use super::*;
13
14
/// A zero-copy, byte-aligned vector for variable-width types.
15
///
16
/// `VarZeroVec<T>` is designed as a drop-in replacement for `Vec<T>` in situations where it is
17
/// desirable to borrow data from an unaligned byte slice, such as zero-copy deserialization, and
18
/// where `T`'s data is variable-length (e.g. `String`)
19
///
20
/// `T` must implement [`VarULE`], which is already implemented for [`str`] and `[u8]`. For storing more
21
/// complicated series of elements, it is implemented on `ZeroSlice<T>` as well as `VarZeroSlice<T>`
22
/// for nesting. [`zerovec::make_varule`](crate::make_varule) may be used to generate
23
/// a dynamically-sized [`VarULE`] type and conversions to and from a custom type.
24
///
25
/// For example, here are some owned types and their zero-copy equivalents:
26
///
27
/// - `Vec<String>`: `VarZeroVec<'a, str>`
28
/// - `Vec<Vec<u8>>>`: `VarZeroVec<'a, [u8]>`
29
/// - `Vec<Vec<u32>>`: `VarZeroVec<'a, ZeroSlice<u32>>`
30
/// - `Vec<Vec<String>>`: `VarZeroVec<'a, VarZeroSlice<str>>`
31
///
32
/// Most of the methods on `VarZeroVec<'a, T>` come from its [`Deref`] implementation to [`VarZeroSlice<T>`](VarZeroSlice).
33
///
34
/// For creating zero-copy vectors of fixed-size types, see [`ZeroVec`](crate::ZeroVec).
35
///
36
/// `VarZeroVec<T>` behaves much like [`Cow`](alloc::borrow::Cow), where it can be constructed from
37
/// owned data (and then mutated!) but can also borrow from some buffer.
38
///
39
/// The `F` type parameter is a [`VarZeroVecFormat`] (see its docs for more details), which can be used to select the
40
/// precise format of the backing buffer with various size and performance tradeoffs. It defaults to [`Index16`].
41
///
42
/// # Bytes and Equality
43
///
44
/// Two [`VarZeroVec`]s are equal if and only if their bytes are equal, as described in the trait
45
/// [`VarULE`]. However, we do not guarantee stability of byte equality or serialization format
46
/// across major SemVer releases.
47
///
48
/// To compare a [`Vec<T>`] to a [`VarZeroVec<T>`], it is generally recommended to use
49
/// [`Iterator::eq`], since it is somewhat expensive at runtime to convert from a [`Vec<T>`] to a
50
/// [`VarZeroVec<T>`] or vice-versa.
51
///
52
/// Prior to zerovec reaching 1.0, the precise byte representation of [`VarZeroVec`] is still
53
/// under consideration, with different options along the space-time spectrum. See
54
/// [#1410](https://github.com/unicode-org/icu4x/issues/1410).
55
///
56
/// # Example
57
///
58
/// ```rust
59
/// # use zerovec::ule::ZeroVecError;
60
/// use zerovec::VarZeroVec;
61
///
62
/// // The little-endian bytes correspond to the list of strings.
63
/// let strings = vec!["w", "ω", "文", "𑄃"];
64
///
65
/// #[derive(serde::Serialize, serde::Deserialize)]
66
/// struct Data<'a> {
67
///     #[serde(borrow)]
68
///     strings: VarZeroVec<'a, str>,
69
/// }
70
///
71
/// let data = Data {
72
///     strings: VarZeroVec::from(&strings),
73
/// };
74
///
75
/// let bincode_bytes =
76
///     bincode::serialize(&data).expect("Serialization should be successful");
77
///
78
/// // Will deserialize without allocations
79
/// let deserialized: Data = bincode::deserialize(&bincode_bytes)
80
///     .expect("Deserialization should be successful");
81
///
82
/// assert_eq!(deserialized.strings.get(2), Some("文"));
83
/// assert_eq!(deserialized.strings, &*strings);
84
/// # Ok::<(), ZeroVecError>(())
85
/// ```
86
///
87
/// Here's another example with `ZeroSlice<T>` (similar to `[T]`):
88
///
89
/// ```rust
90
/// # use zerovec::ule::ZeroVecError;
91
/// use zerovec::VarZeroVec;
92
/// use zerovec::ZeroSlice;
93
///
94
/// // The structured list correspond to the list of integers.
95
/// let numbers: &[&[u32]] = &[
96
///     &[12, 25, 38],
97
///     &[39179, 100],
98
///     &[42, 55555],
99
///     &[12345, 54321, 9],
100
/// ];
101
///
102
/// #[derive(serde::Serialize, serde::Deserialize)]
103
/// struct Data<'a> {
104
///     #[serde(borrow)]
105
///     vecs: VarZeroVec<'a, ZeroSlice<u32>>,
106
/// }
107
///
108
/// let data = Data {
109
///     vecs: VarZeroVec::from(numbers),
110
/// };
111
///
112
/// let bincode_bytes =
113
///     bincode::serialize(&data).expect("Serialization should be successful");
114
///
115
/// let deserialized: Data = bincode::deserialize(&bincode_bytes)
116
///     .expect("Deserialization should be successful");
117
///
118
/// assert_eq!(deserialized.vecs[0].get(1).unwrap(), 25);
119
/// assert_eq!(deserialized.vecs[1], *numbers[1]);
120
///
121
/// # Ok::<(), ZeroVecError>(())
122
/// ```
123
///
124
/// [`VarZeroVec`]s can be nested infinitely via a similar mechanism, see the docs of [`VarZeroSlice`]
125
/// for more information.
126
///
127
/// # How it Works
128
///
129
/// `VarZeroVec<T>`, when used with non-human-readable serializers (like `bincode`), will
130
/// serialize to a specially formatted list of bytes. The format is:
131
///
132
/// - 4 bytes for `length` (interpreted as a little-endian u32)
133
/// - `4 * length` bytes of `indices` (interpreted as little-endian u32)
134
/// - Remaining bytes for actual `data`
135
///
136
/// Each element in the `indices` array points to the starting index of its corresponding
137
/// data part in the `data` list. The ending index can be calculated from the starting index
138
/// of the next element (or the length of the slice if dealing with the last element).
139
///
140
/// See [the design doc](https://github.com/unicode-org/icu4x/blob/main/utils/zerovec/design_doc.md) for more details.
141
///
142
/// [`ule`]: crate::ule
143
#[non_exhaustive]
144
pub enum VarZeroVec<'a, T: ?Sized, F = Index16> {
145
    /// An allocated VarZeroVec, allowing for mutations.
146
    ///
147
    /// # Examples
148
    ///
149
    /// ```
150
    /// use zerovec::VarZeroVec;
151
    ///
152
    /// let mut vzv = VarZeroVec::<str>::default();
153
    /// vzv.make_mut().push("foo");
154
    /// vzv.make_mut().push("bar");
155
    /// assert!(matches!(vzv, VarZeroVec::Owned(_)));
156
    /// ```
157
    Owned(VarZeroVecOwned<T, F>),
158
    /// A borrowed VarZeroVec, requiring no allocations.
159
    ///
160
    /// If a mutating operation is invoked on VarZeroVec, the Borrowed is converted to Owned.
161
    ///
162
    /// # Examples
163
    ///
164
    /// ```
165
    /// use zerovec::VarZeroVec;
166
    ///
167
    /// let bytes = &[
168
    ///     4, 0, 0, 0, 0, 0, 1, 0, 3, 0, 6, 0, 119, 207, 137, 230, 150, 135, 240,
169
    ///     145, 132, 131,
170
    /// ];
171
    ///
172
    /// let vzv: VarZeroVec<str> = VarZeroVec::parse_byte_slice(bytes).unwrap();
173
    /// assert!(matches!(vzv, VarZeroVec::Borrowed(_)));
174
    /// ```
175
    Borrowed(&'a VarZeroSlice<T, F>),
176
}
177
178
impl<'a, T: ?Sized, F> Clone for VarZeroVec<'a, T, F> {
179
0
    fn clone(&self) -> Self {
180
0
        match *self {
181
0
            VarZeroVec::Owned(ref o) => o.clone().into(),
182
0
            VarZeroVec::Borrowed(b) => b.into(),
183
        }
184
0
    }
185
}
186
187
impl<T: VarULE + ?Sized, F: VarZeroVecFormat> fmt::Debug for VarZeroVec<'_, T, F>
188
where
189
    T: fmt::Debug,
190
{
191
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192
0
        VarZeroSlice::fmt(self, f)
193
0
    }
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<str> as core::fmt::Debug>::fmt
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<_, _> as core::fmt::Debug>::fmt
194
}
195
196
impl<'a, T: ?Sized, F> From<VarZeroVecOwned<T, F>> for VarZeroVec<'a, T, F> {
197
    #[inline]
198
0
    fn from(other: VarZeroVecOwned<T, F>) -> Self {
199
0
        VarZeroVec::Owned(other)
200
0
    }
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_locid_transform::provider::LanguageStrStrPairVarULE> as core::convert::From<zerovec::varzerovec::owned::VarZeroVecOwned<icu_locid_transform::provider::LanguageStrStrPairVarULE>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<_, _> as core::convert::From<zerovec::varzerovec::owned::VarZeroVecOwned<_, _>>>::from
201
}
202
203
impl<'a, T: ?Sized, F> From<&'a VarZeroSlice<T, F>> for VarZeroVec<'a, T, F> {
204
0
    fn from(other: &'a VarZeroSlice<T, F>) -> Self {
205
0
        VarZeroVec::Borrowed(other)
206
0
    }
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::zerovec::slice::ZeroSlice<icu_properties::props::Script>> as core::convert::From<&zerovec::varzerovec::slice::VarZeroSlice<zerovec::zerovec::slice::ZeroSlice<icu_properties::props::Script>>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_properties::provider::names::NormalizedPropertyNameStr> as core::convert::From<&zerovec::varzerovec::slice::VarZeroSlice<icu_properties::provider::names::NormalizedPropertyNameStr>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::zerovec::slice::ZeroSlice<icu_locid::subtags::region::Region>> as core::convert::From<&zerovec::varzerovec::slice::VarZeroSlice<zerovec::zerovec::slice::ZeroSlice<icu_locid::subtags::region::Region>>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_locid_transform::provider::StrStrPairVarULE> as core::convert::From<&zerovec::varzerovec::slice::VarZeroSlice<icu_locid_transform::provider::StrStrPairVarULE>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_locid_transform::provider::LanguageStrStrPairVarULE> as core::convert::From<&zerovec::varzerovec::slice::VarZeroSlice<icu_locid_transform::provider::LanguageStrStrPairVarULE>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::ule::unvalidated::UnvalidatedStr> as core::convert::From<&zerovec::varzerovec::slice::VarZeroSlice<zerovec::ule::unvalidated::UnvalidatedStr>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<str> as core::convert::From<&zerovec::varzerovec::slice::VarZeroSlice<str>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<str> as core::convert::From<&zerovec::varzerovec::slice::VarZeroSlice<str>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<_, _> as core::convert::From<&zerovec::varzerovec::slice::VarZeroSlice<_, _>>>::from
207
}
208
209
impl<'a, T: ?Sized + VarULE, F: VarZeroVecFormat> From<VarZeroVec<'a, T, F>>
210
    for VarZeroVecOwned<T, F>
211
{
212
    #[inline]
213
0
    fn from(other: VarZeroVec<'a, T, F>) -> Self {
214
0
        match other {
215
0
            VarZeroVec::Owned(o) => o,
216
0
            VarZeroVec::Borrowed(b) => b.into(),
217
        }
218
0
    }
219
}
220
221
impl<T: VarULE + ?Sized> Default for VarZeroVec<'_, T> {
222
    #[inline]
223
0
    fn default() -> Self {
224
0
        Self::new()
225
0
    }
226
}
227
228
impl<T: VarULE + ?Sized, F: VarZeroVecFormat> Deref for VarZeroVec<'_, T, F> {
229
    type Target = VarZeroSlice<T, F>;
230
0
    fn deref(&self) -> &VarZeroSlice<T, F> {
231
0
        self.as_slice()
232
0
    }
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::zerovec::slice::ZeroSlice<icu_properties::props::Script>> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_properties::provider::names::NormalizedPropertyNameStr> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::zerovec::slice::ZeroSlice<icu_locid::subtags::region::Region>> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_locid_transform::provider::StrStrPairVarULE> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_locid_transform::provider::LanguageStrStrPairVarULE> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::ule::unvalidated::UnvalidatedStr> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<str> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<str> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<_, _> as core::ops::deref::Deref>::deref
233
}
234
235
impl<'a, T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVec<'a, T, F> {
236
    /// Creates a new, empty `VarZeroVec<T>`.
237
    ///
238
    /// # Examples
239
    ///
240
    /// ```
241
    /// use zerovec::VarZeroVec;
242
    ///
243
    /// let vzv: VarZeroVec<str> = VarZeroVec::new();
244
    /// assert!(vzv.is_empty());
245
    /// ```
246
    #[inline]
247
0
    pub const fn new() -> Self {
248
0
        Self::Borrowed(VarZeroSlice::new_empty())
249
0
    }
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::ule::unvalidated::UnvalidatedStr>>::new
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<_, _>>::new
250
251
    /// Parse a VarZeroVec from a slice of the appropriate format
252
    ///
253
    /// Slices of the right format can be obtained via [`VarZeroSlice::as_bytes()`].
254
    ///
255
    /// # Example
256
    ///
257
    /// ```rust
258
    /// # use zerovec::ule::ZeroVecError;
259
    /// # use zerovec::VarZeroVec;
260
    ///
261
    /// let strings = vec!["foo", "bar", "baz", "quux"];
262
    /// let vec = VarZeroVec::<str>::from(&strings);
263
    ///
264
    /// assert_eq!(&vec[0], "foo");
265
    /// assert_eq!(&vec[1], "bar");
266
    /// assert_eq!(&vec[2], "baz");
267
    /// assert_eq!(&vec[3], "quux");
268
    /// # Ok::<(), ZeroVecError>(())
269
    /// ```
270
0
    pub fn parse_byte_slice(slice: &'a [u8]) -> Result<Self, ZeroVecError> {
271
0
        let borrowed = VarZeroSlice::<T, F>::parse_byte_slice(slice)?;
272
273
0
        Ok(VarZeroVec::Borrowed(borrowed))
274
0
    }
275
276
    /// Uses a `&[u8]` buffer as a `VarZeroVec<T>` without any verification.
277
    ///
278
    /// # Safety
279
    ///
280
    /// `bytes` need to be an output from [`VarZeroSlice::as_bytes()`].
281
0
    pub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
282
0
        Self::Borrowed(core::mem::transmute::<&[u8], &VarZeroSlice<T, F>>(bytes))
283
0
    }
284
285
    /// Convert this into a mutable vector of the owned `T` type, cloning if necessary.
286
    ///
287
    ///
288
    /// # Example
289
    ///
290
    /// ```rust,ignore
291
    /// # use zerovec::ule::ZeroVecError;
292
    /// # use zerovec::VarZeroVec;
293
    ///
294
    /// let strings = vec!["foo", "bar", "baz", "quux"];
295
    /// let mut vec = VarZeroVec::<str>::from(&strings);
296
    ///
297
    /// assert_eq!(vec.len(), 4);
298
    /// let mutvec = vec.make_mut();
299
    /// mutvec.push("lorem ipsum".into());
300
    /// mutvec[2] = "dolor sit".into();
301
    /// assert_eq!(&vec[0], "foo");
302
    /// assert_eq!(&vec[1], "bar");
303
    /// assert_eq!(&vec[2], "dolor sit");
304
    /// assert_eq!(&vec[3], "quux");
305
    /// assert_eq!(&vec[4], "lorem ipsum");
306
    /// # Ok::<(), ZeroVecError>(())
307
    /// ```
308
    //
309
    // This function is crate-public for now since we don't yet want to stabilize
310
    // the internal implementation details
311
0
    pub fn make_mut(&mut self) -> &mut VarZeroVecOwned<T, F> {
312
0
        match self {
313
0
            VarZeroVec::Owned(ref mut vec) => vec,
314
0
            VarZeroVec::Borrowed(slice) => {
315
0
                let new_self = VarZeroVecOwned::from_slice(slice);
316
0
                *self = new_self.into();
317
0
                // recursion is limited since we are guaranteed to hit the Owned branch
318
0
                self.make_mut()
319
            }
320
        }
321
0
    }
322
323
    /// Converts a borrowed ZeroVec to an owned ZeroVec. No-op if already owned.
324
    ///
325
    /// # Example
326
    ///
327
    /// ```
328
    /// # use zerovec::ule::ZeroVecError;
329
    /// # use zerovec::VarZeroVec;
330
    ///
331
    /// let strings = vec!["foo", "bar", "baz", "quux"];
332
    /// let vec = VarZeroVec::<str>::from(&strings);
333
    ///
334
    /// assert_eq!(vec.len(), 4);
335
    /// // has 'static lifetime
336
    /// let owned = vec.into_owned();
337
    /// # Ok::<(), ZeroVecError>(())
338
    /// ```
339
0
    pub fn into_owned(mut self) -> VarZeroVec<'static, T, F> {
340
0
        self.make_mut();
341
0
        match self {
342
0
            VarZeroVec::Owned(vec) => vec.into(),
343
0
            _ => unreachable!(),
344
        }
345
0
    }
346
347
    /// Obtain this `VarZeroVec` as a [`VarZeroSlice`]
348
0
    pub fn as_slice(&self) -> &VarZeroSlice<T, F> {
349
0
        match *self {
350
0
            VarZeroVec::Owned(ref owned) => owned,
351
0
            VarZeroVec::Borrowed(b) => b,
352
        }
353
0
    }
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::zerovec::slice::ZeroSlice<icu_properties::props::Script>>>::as_slice
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_properties::provider::names::NormalizedPropertyNameStr>>::as_slice
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::zerovec::slice::ZeroSlice<icu_locid::subtags::region::Region>>>::as_slice
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_locid_transform::provider::StrStrPairVarULE>>::as_slice
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_locid_transform::provider::LanguageStrStrPairVarULE>>::as_slice
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<zerovec::ule::unvalidated::UnvalidatedStr>>::as_slice
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<str>>::as_slice
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<str>>::as_slice
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<_, _>>::as_slice
354
355
    /// Takes the byte vector representing the encoded data of this VarZeroVec. If borrowed,
356
    /// this function allocates a byte vector and copies the borrowed bytes into it.
357
    ///
358
    /// The bytes can be passed back to [`Self::parse_byte_slice()`].
359
    ///
360
    /// To get a reference to the bytes without moving, see [`VarZeroSlice::as_bytes()`].
361
    ///
362
    /// # Example
363
    ///
364
    /// ```rust
365
    /// # use zerovec::ule::ZeroVecError;
366
    /// # use zerovec::VarZeroVec;
367
    ///
368
    /// let strings = vec!["foo", "bar", "baz"];
369
    /// let bytes = VarZeroVec::<str>::from(&strings).into_bytes();
370
    ///
371
    /// let mut borrowed: VarZeroVec<str> = VarZeroVec::parse_byte_slice(&bytes)?;
372
    /// assert_eq!(borrowed, &*strings);
373
    ///
374
    /// # Ok::<(), ZeroVecError>(())
375
    /// ```
376
0
    pub fn into_bytes(self) -> Vec<u8> {
377
0
        match self {
378
0
            VarZeroVec::Owned(vec) => vec.into_bytes(),
379
0
            VarZeroVec::Borrowed(vec) => vec.as_bytes().to_vec(),
380
        }
381
0
    }
382
383
    /// Return whether the [`VarZeroVec`] is operating on owned or borrowed
384
    /// data. [`VarZeroVec::into_owned()`] and [`VarZeroVec::make_mut()`] can
385
    /// be used to force it into an owned type
386
0
    pub fn is_owned(&self) -> bool {
387
0
        match self {
388
0
            VarZeroVec::Owned(..) => true,
389
0
            VarZeroVec::Borrowed(..) => false,
390
        }
391
0
    }
392
393
    #[cfg(feature = "bench")]
394
    #[doc(hidden)]
395
    pub fn as_components<'b>(&'b self) -> VarZeroVecComponents<'b, T, F> {
396
        self.as_slice().as_components()
397
    }
398
}
399
400
impl<A, T, F> From<&Vec<A>> for VarZeroVec<'static, T, F>
401
where
402
    T: VarULE + ?Sized,
403
    A: EncodeAsVarULE<T>,
404
    F: VarZeroVecFormat,
405
{
406
    #[inline]
407
0
    fn from(elements: &Vec<A>) -> Self {
408
0
        Self::from(elements.as_slice())
409
0
    }
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_locid_transform::provider::LanguageStrStrPairVarULE> as core::convert::From<&alloc::vec::Vec<icu_locid_transform::provider::LanguageStrStrPair>>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<_, _> as core::convert::From<&alloc::vec::Vec<_>>>::from
410
}
411
412
impl<A, T, F> From<&[A]> for VarZeroVec<'static, T, F>
413
where
414
    T: VarULE + ?Sized,
415
    A: EncodeAsVarULE<T>,
416
    F: VarZeroVecFormat,
417
{
418
    #[inline]
419
0
    fn from(elements: &[A]) -> Self {
420
0
        if elements.is_empty() {
421
0
            VarZeroSlice::new_empty().into()
422
        } else {
423
            #[allow(clippy::unwrap_used)] // TODO(#1410) Better story for fallibility
424
0
            VarZeroVecOwned::try_from_elements(elements).unwrap().into()
425
        }
426
0
    }
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<icu_locid_transform::provider::LanguageStrStrPairVarULE> as core::convert::From<&[icu_locid_transform::provider::LanguageStrStrPair]>>::from
Unexecuted instantiation: <zerovec::varzerovec::vec::VarZeroVec<_, _> as core::convert::From<&[_]>>::from
427
}
428
429
impl<A, T, F, const N: usize> From<&[A; N]> for VarZeroVec<'static, T, F>
430
where
431
    T: VarULE + ?Sized,
432
    A: EncodeAsVarULE<T>,
433
    F: VarZeroVecFormat,
434
{
435
    #[inline]
436
0
    fn from(elements: &[A; N]) -> Self {
437
0
        Self::from(elements.as_slice())
438
0
    }
439
}
440
441
impl<'a, 'b, T, F> PartialEq<VarZeroVec<'b, T, F>> for VarZeroVec<'a, T, F>
442
where
443
    T: VarULE,
444
    T: ?Sized,
445
    T: PartialEq,
446
    F: VarZeroVecFormat,
447
{
448
    #[inline]
449
0
    fn eq(&self, other: &VarZeroVec<'b, T, F>) -> bool {
450
0
        // VZV::from_elements used to produce a non-canonical representation of the
451
0
        // empty VZV, so we cannot use byte equality for empty vecs.
452
0
        if self.is_empty() || other.is_empty() {
453
0
            return self.is_empty() && other.is_empty();
454
0
        }
455
0
        // VarULE has an API guarantee that byte equality is semantic equality.
456
0
        // For non-empty VZVs, there's only a single metadata representation,
457
0
        // so this guarantee extends to the whole VZV representation.
458
0
        self.as_bytes().eq(other.as_bytes())
459
0
    }
460
}
461
462
impl<'a, T, F> Eq for VarZeroVec<'a, T, F>
463
where
464
    T: VarULE,
465
    T: ?Sized,
466
    T: Eq,
467
    F: VarZeroVecFormat,
468
{
469
}
470
471
impl<T, A, F> PartialEq<&'_ [A]> for VarZeroVec<'_, T, F>
472
where
473
    T: VarULE + ?Sized,
474
    T: PartialEq,
475
    A: AsRef<T>,
476
    F: VarZeroVecFormat,
477
{
478
    #[inline]
479
0
    fn eq(&self, other: &&[A]) -> bool {
480
0
        self.iter().eq(other.iter().map(|t| t.as_ref()))
481
0
    }
482
}
483
484
impl<T, A, F, const N: usize> PartialEq<[A; N]> for VarZeroVec<'_, T, F>
485
where
486
    T: VarULE + ?Sized,
487
    T: PartialEq,
488
    A: AsRef<T>,
489
    F: VarZeroVecFormat,
490
{
491
    #[inline]
492
0
    fn eq(&self, other: &[A; N]) -> bool {
493
0
        self.iter().eq(other.iter().map(|t| t.as_ref()))
494
0
    }
495
}
496
497
impl<'a, T: VarULE + ?Sized + PartialOrd, F: VarZeroVecFormat> PartialOrd for VarZeroVec<'a, T, F> {
498
0
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
499
0
        self.iter().partial_cmp(other.iter())
500
0
    }
501
}
502
503
impl<'a, T: VarULE + ?Sized + Ord, F: VarZeroVecFormat> Ord for VarZeroVec<'a, T, F> {
504
0
    fn cmp(&self, other: &Self) -> Ordering {
505
0
        self.iter().cmp(other.iter())
506
0
    }
507
}
508
509
#[test]
510
fn assert_single_empty_representation() {
511
    assert_eq!(
512
        VarZeroVec::<str>::new().as_bytes(),
513
        VarZeroVec::<str>::from(&[] as &[&str]).as_bytes()
514
    );
515
}
516
517
#[test]
518
fn weird_empty_representation_equality() {
519
    assert_eq!(
520
        VarZeroVec::<str>::parse_byte_slice(&[0, 0, 0, 0]).unwrap(),
521
        VarZeroVec::<str>::parse_byte_slice(&[]).unwrap()
522
    );
523
}