• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of ICU4X. For terms of use, please see the file
2 // called LICENSE at the top level of the ICU4X source tree
3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4 
5 use crate::ule::*;
6 use crate::varzerovec::owned::VarZeroVecOwned;
7 use crate::varzerovec::vec::VarZeroVecInner;
8 use crate::vecs::VarZeroVecFormat;
9 use crate::{VarZeroSlice, VarZeroVec};
10 use crate::{ZeroSlice, ZeroVec};
11 use alloc::boxed::Box;
12 use alloc::vec::Vec;
13 use core::cmp::Ordering;
14 use core::mem;
15 use core::ops::Range;
16 
17 /// Trait abstracting over [`ZeroVec`] and [`VarZeroVec`], for use in [`ZeroMap`](super::ZeroMap). **You
18 /// should not be implementing or calling this trait directly.**
19 ///
20 /// The T type is the type received by [`Self::zvl_binary_search()`], as well as the one used
21 /// for human-readable serialization.
22 ///
23 /// Methods are prefixed with `zvl_*` to avoid clashes with methods on the types themselves
24 pub trait ZeroVecLike<T: ?Sized> {
25     /// The type returned by `Self::get()`
26     type GetType: ?Sized + 'static;
27     /// A fully borrowed version of this
28     type SliceVariant: ZeroVecLike<T, GetType = Self::GetType> + ?Sized;
29 
30     /// Create a new, empty borrowed variant
zvl_new_borrowed() -> &'static Self::SliceVariant31     fn zvl_new_borrowed() -> &'static Self::SliceVariant;
32 
33     /// Search for a key in a sorted vector, returns `Ok(index)` if found,
34     /// returns `Err(insert_index)` if not found, where `insert_index` is the
35     /// index where it should be inserted to maintain sort order.
zvl_binary_search(&self, k: &T) -> Result<usize, usize> where T: Ord36     fn zvl_binary_search(&self, k: &T) -> Result<usize, usize>
37     where
38         T: Ord;
39     /// Search for a key within a certain range in a sorted vector.
40     /// Returns `None` if the range is out of bounds, and
41     /// `Ok` or `Err` in the same way as `zvl_binary_search`.
42     /// Indices are returned relative to the start of the range.
zvl_binary_search_in_range( &self, k: &T, range: Range<usize>, ) -> Option<Result<usize, usize>> where T: Ord43     fn zvl_binary_search_in_range(
44         &self,
45         k: &T,
46         range: Range<usize>,
47     ) -> Option<Result<usize, usize>>
48     where
49         T: Ord;
50 
51     /// Search for a key in a sorted vector by a predicate, returns `Ok(index)` if found,
52     /// returns `Err(insert_index)` if not found, where `insert_index` is the
53     /// index where it should be inserted to maintain sort order.
zvl_binary_search_by(&self, predicate: impl FnMut(&T) -> Ordering) -> Result<usize, usize>54     fn zvl_binary_search_by(&self, predicate: impl FnMut(&T) -> Ordering) -> Result<usize, usize>;
55     /// Search for a key within a certain range in a sorted vector by a predicate.
56     /// Returns `None` if the range is out of bounds, and
57     /// `Ok` or `Err` in the same way as `zvl_binary_search`.
58     /// Indices are returned relative to the start of the range.
zvl_binary_search_in_range_by( &self, predicate: impl FnMut(&T) -> Ordering, range: Range<usize>, ) -> Option<Result<usize, usize>>59     fn zvl_binary_search_in_range_by(
60         &self,
61         predicate: impl FnMut(&T) -> Ordering,
62         range: Range<usize>,
63     ) -> Option<Result<usize, usize>>;
64 
65     /// Get element at `index`
zvl_get(&self, index: usize) -> Option<&Self::GetType>66     fn zvl_get(&self, index: usize) -> Option<&Self::GetType>;
67     /// The length of this vector
zvl_len(&self) -> usize68     fn zvl_len(&self) -> usize;
69     /// Check if this vector is in ascending order according to `T`s `Ord` impl
zvl_is_ascending(&self) -> bool where T: Ord,70     fn zvl_is_ascending(&self) -> bool
71     where
72         T: Ord,
73     {
74         if let Some(first) = self.zvl_get(0) {
75             let mut prev = first;
76             for i in 1..self.zvl_len() {
77                 #[allow(clippy::unwrap_used)] // looping over the valid indices
78                 let curr = self.zvl_get(i).unwrap();
79                 if Self::get_cmp_get(prev, curr) != Ordering::Less {
80                     return false;
81                 }
82                 prev = curr;
83             }
84         }
85         true
86     }
87     /// Check if this vector is empty
zvl_is_empty(&self) -> bool88     fn zvl_is_empty(&self) -> bool {
89         self.zvl_len() == 0
90     }
91 
92     /// Construct a borrowed variant by borrowing from `&self`.
93     ///
94     /// This function behaves like `&'b self -> Self::SliceVariant<'b>`,
95     /// where `'b` is the lifetime of the reference to this object.
96     ///
97     /// Note: We rely on the compiler recognizing `'a` and `'b` as covariant and
98     /// casting `&'b Self<'a>` to `&'b Self<'b>` when this gets called, which works
99     /// out for `ZeroVec` and `VarZeroVec` containers just fine.
zvl_as_borrowed(&self) -> &Self::SliceVariant100     fn zvl_as_borrowed(&self) -> &Self::SliceVariant;
101 
102     /// Compare this type with a `Self::GetType`. This must produce the same result as
103     /// if `g` were converted to `Self`
104     #[inline]
t_cmp_get(t: &T, g: &Self::GetType) -> Ordering where T: Ord,105     fn t_cmp_get(t: &T, g: &Self::GetType) -> Ordering
106     where
107         T: Ord,
108     {
109         Self::zvl_get_as_t(g, |g| t.cmp(g))
110     }
111 
112     /// Compare two values of `Self::GetType`. This must produce the same result as
113     /// if both `a` and `b` were converted to `Self`
114     #[inline]
get_cmp_get(a: &Self::GetType, b: &Self::GetType) -> Ordering where T: Ord,115     fn get_cmp_get(a: &Self::GetType, b: &Self::GetType) -> Ordering
116     where
117         T: Ord,
118     {
119         Self::zvl_get_as_t(a, |a| Self::zvl_get_as_t(b, |b| a.cmp(b)))
120     }
121 
122     /// Obtain a reference to T, passed to a closure
123     ///
124     /// This uses a callback because it's not possible to return owned-or-borrowed
125     /// types without GATs
126     ///
127     /// Impls should guarantee that the callback function is be called exactly once.
zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R128     fn zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R;
129 }
130 
131 /// Trait abstracting over [`ZeroVec`] and [`VarZeroVec`], for use in [`ZeroMap`](super::ZeroMap). **You
132 /// should not be implementing or calling this trait directly.**
133 ///
134 /// This trait augments [`ZeroVecLike`] with methods allowing for mutation of the underlying
135 /// vector for owned vector types.
136 ///
137 /// Methods are prefixed with `zvl_*` to avoid clashes with methods on the types themselves
138 pub trait MutableZeroVecLike<'a, T: ?Sized>: ZeroVecLike<T> {
139     /// The type returned by `Self::remove()` and `Self::replace()`
140     type OwnedType;
141 
142     /// Insert an element at `index`
zvl_insert(&mut self, index: usize, value: &T)143     fn zvl_insert(&mut self, index: usize, value: &T);
144     /// Remove the element at `index` (panicking if nonexistant)
zvl_remove(&mut self, index: usize) -> Self::OwnedType145     fn zvl_remove(&mut self, index: usize) -> Self::OwnedType;
146     /// Replace the element at `index` with another one, returning the old element
zvl_replace(&mut self, index: usize, value: &T) -> Self::OwnedType147     fn zvl_replace(&mut self, index: usize, value: &T) -> Self::OwnedType;
148     /// Push an element to the end of this vector
zvl_push(&mut self, value: &T)149     fn zvl_push(&mut self, value: &T);
150     /// Create a new, empty vector, with given capacity
zvl_with_capacity(cap: usize) -> Self151     fn zvl_with_capacity(cap: usize) -> Self;
152     /// Remove all elements from the vector
zvl_clear(&mut self)153     fn zvl_clear(&mut self);
154     /// Reserve space for `addl` additional elements
zvl_reserve(&mut self, addl: usize)155     fn zvl_reserve(&mut self, addl: usize);
156     /// Applies the permutation such that `before.zvl_get(permutation[i]) == after.zvl_get(i)`.
157     ///
158     /// # Panics
159     /// If `permutation` is not a valid permutation of length `zvl_len()`.
zvl_permute(&mut self, permutation: &mut [usize])160     fn zvl_permute(&mut self, permutation: &mut [usize]);
161 
162     /// Convert an owned value to a borrowed T
owned_as_t(o: &Self::OwnedType) -> &T163     fn owned_as_t(o: &Self::OwnedType) -> &T;
164 
165     /// Construct from the borrowed version of the type
166     ///
167     /// These are useful to ensure serialization parity between borrowed and owned versions
zvl_from_borrowed(b: &'a Self::SliceVariant) -> Self168     fn zvl_from_borrowed(b: &'a Self::SliceVariant) -> Self;
169     /// Extract the inner borrowed variant if possible. Returns `None` if the data is owned.
170     ///
171     /// This function behaves like `&'_ self -> Self::SliceVariant<'a>`,
172     /// where `'a` is the lifetime of this object's borrowed data.
173     ///
174     /// This function is similar to matching the `Borrowed` variant of `ZeroVec`
175     /// or `VarZeroVec`, returning the inner borrowed type.
zvl_as_borrowed_inner(&self) -> Option<&'a Self::SliceVariant>176     fn zvl_as_borrowed_inner(&self) -> Option<&'a Self::SliceVariant>;
177 }
178 
179 impl<'a, T> ZeroVecLike<T> for ZeroVec<'a, T>
180 where
181     T: 'a + AsULE + Copy,
182 {
183     type GetType = T::ULE;
184     type SliceVariant = ZeroSlice<T>;
185 
zvl_new_borrowed() -> &'static Self::SliceVariant186     fn zvl_new_borrowed() -> &'static Self::SliceVariant {
187         ZeroSlice::<T>::new_empty()
188     }
zvl_binary_search(&self, k: &T) -> Result<usize, usize> where T: Ord,189     fn zvl_binary_search(&self, k: &T) -> Result<usize, usize>
190     where
191         T: Ord,
192     {
193         ZeroSlice::binary_search(self, k)
194     }
zvl_binary_search_in_range(&self, k: &T, range: Range<usize>) -> Option<Result<usize, usize>> where T: Ord,195     fn zvl_binary_search_in_range(&self, k: &T, range: Range<usize>) -> Option<Result<usize, usize>>
196     where
197         T: Ord,
198     {
199         let zs: &ZeroSlice<T> = self;
200         zs.zvl_binary_search_in_range(k, range)
201     }
zvl_binary_search_by( &self, mut predicate: impl FnMut(&T) -> Ordering, ) -> Result<usize, usize>202     fn zvl_binary_search_by(
203         &self,
204         mut predicate: impl FnMut(&T) -> Ordering,
205     ) -> Result<usize, usize> {
206         ZeroSlice::binary_search_by(self, |probe| predicate(&probe))
207     }
zvl_binary_search_in_range_by( &self, predicate: impl FnMut(&T) -> Ordering, range: Range<usize>, ) -> Option<Result<usize, usize>>208     fn zvl_binary_search_in_range_by(
209         &self,
210         predicate: impl FnMut(&T) -> Ordering,
211         range: Range<usize>,
212     ) -> Option<Result<usize, usize>> {
213         let zs: &ZeroSlice<T> = self;
214         zs.zvl_binary_search_in_range_by(predicate, range)
215     }
zvl_get(&self, index: usize) -> Option<&T::ULE>216     fn zvl_get(&self, index: usize) -> Option<&T::ULE> {
217         self.get_ule_ref(index)
218     }
zvl_len(&self) -> usize219     fn zvl_len(&self) -> usize {
220         ZeroSlice::len(self)
221     }
zvl_as_borrowed(&self) -> &ZeroSlice<T>222     fn zvl_as_borrowed(&self) -> &ZeroSlice<T> {
223         self
224     }
225     #[inline]
zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R226     fn zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R {
227         f(&T::from_unaligned(*g))
228     }
229 }
230 
231 impl<T> ZeroVecLike<T> for ZeroSlice<T>
232 where
233     T: AsULE + Copy,
234 {
235     type GetType = T::ULE;
236     type SliceVariant = ZeroSlice<T>;
237 
zvl_new_borrowed() -> &'static Self::SliceVariant238     fn zvl_new_borrowed() -> &'static Self::SliceVariant {
239         ZeroSlice::<T>::new_empty()
240     }
zvl_binary_search(&self, k: &T) -> Result<usize, usize> where T: Ord,241     fn zvl_binary_search(&self, k: &T) -> Result<usize, usize>
242     where
243         T: Ord,
244     {
245         ZeroSlice::binary_search(self, k)
246     }
zvl_binary_search_in_range(&self, k: &T, range: Range<usize>) -> Option<Result<usize, usize>> where T: Ord,247     fn zvl_binary_search_in_range(&self, k: &T, range: Range<usize>) -> Option<Result<usize, usize>>
248     where
249         T: Ord,
250     {
251         let subslice = self.get_subslice(range)?;
252         Some(ZeroSlice::binary_search(subslice, k))
253     }
zvl_binary_search_by( &self, mut predicate: impl FnMut(&T) -> Ordering, ) -> Result<usize, usize>254     fn zvl_binary_search_by(
255         &self,
256         mut predicate: impl FnMut(&T) -> Ordering,
257     ) -> Result<usize, usize> {
258         ZeroSlice::binary_search_by(self, |probe| predicate(&probe))
259     }
zvl_binary_search_in_range_by( &self, mut predicate: impl FnMut(&T) -> Ordering, range: Range<usize>, ) -> Option<Result<usize, usize>>260     fn zvl_binary_search_in_range_by(
261         &self,
262         mut predicate: impl FnMut(&T) -> Ordering,
263         range: Range<usize>,
264     ) -> Option<Result<usize, usize>> {
265         let subslice = self.get_subslice(range)?;
266         Some(ZeroSlice::binary_search_by(subslice, |probe| {
267             predicate(&probe)
268         }))
269     }
zvl_get(&self, index: usize) -> Option<&T::ULE>270     fn zvl_get(&self, index: usize) -> Option<&T::ULE> {
271         self.get_ule_ref(index)
272     }
zvl_len(&self) -> usize273     fn zvl_len(&self) -> usize {
274         ZeroSlice::len(self)
275     }
zvl_as_borrowed(&self) -> &ZeroSlice<T>276     fn zvl_as_borrowed(&self) -> &ZeroSlice<T> {
277         self
278     }
279 
280     #[inline]
zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R281     fn zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R {
282         f(&T::from_unaligned(*g))
283     }
284 }
285 
286 impl<'a, T> MutableZeroVecLike<'a, T> for ZeroVec<'a, T>
287 where
288     T: AsULE + Copy + 'static,
289 {
290     type OwnedType = T;
zvl_insert(&mut self, index: usize, value: &T)291     fn zvl_insert(&mut self, index: usize, value: &T) {
292         self.with_mut(|v| v.insert(index, value.to_unaligned()))
293     }
zvl_remove(&mut self, index: usize) -> T294     fn zvl_remove(&mut self, index: usize) -> T {
295         T::from_unaligned(self.with_mut(|v| v.remove(index)))
296     }
zvl_replace(&mut self, index: usize, value: &T) -> T297     fn zvl_replace(&mut self, index: usize, value: &T) -> T {
298         #[allow(clippy::indexing_slicing)]
299         let unaligned = self.with_mut(|vec| {
300             debug_assert!(index < vec.len());
301             mem::replace(&mut vec[index], value.to_unaligned())
302         });
303         T::from_unaligned(unaligned)
304     }
zvl_push(&mut self, value: &T)305     fn zvl_push(&mut self, value: &T) {
306         self.with_mut(|v| v.push(value.to_unaligned()))
307     }
zvl_with_capacity(cap: usize) -> Self308     fn zvl_with_capacity(cap: usize) -> Self {
309         if cap == 0 {
310             ZeroVec::new()
311         } else {
312             ZeroVec::new_owned(Vec::with_capacity(cap))
313         }
314     }
zvl_clear(&mut self)315     fn zvl_clear(&mut self) {
316         self.with_mut(|v| v.clear())
317     }
zvl_reserve(&mut self, addl: usize)318     fn zvl_reserve(&mut self, addl: usize) {
319         self.with_mut(|v| v.reserve(addl))
320     }
321 
owned_as_t(o: &Self::OwnedType) -> &T322     fn owned_as_t(o: &Self::OwnedType) -> &T {
323         o
324     }
325 
zvl_from_borrowed(b: &'a ZeroSlice<T>) -> Self326     fn zvl_from_borrowed(b: &'a ZeroSlice<T>) -> Self {
327         b.as_zerovec()
328     }
zvl_as_borrowed_inner(&self) -> Option<&'a ZeroSlice<T>>329     fn zvl_as_borrowed_inner(&self) -> Option<&'a ZeroSlice<T>> {
330         self.as_maybe_borrowed()
331     }
332 
333     #[allow(clippy::indexing_slicing)] // documented panic
zvl_permute(&mut self, permutation: &mut [usize])334     fn zvl_permute(&mut self, permutation: &mut [usize]) {
335         assert_eq!(permutation.len(), self.zvl_len());
336 
337         let vec = self.to_mut_slice();
338 
339         for cycle_start in 0..permutation.len() {
340             let mut curr = cycle_start;
341             let mut next = permutation[curr];
342 
343             while next != cycle_start {
344                 vec.swap(curr, next);
345                 // Make curr a self-cycle so we don't use it as a cycle_start later
346                 permutation[curr] = curr;
347                 curr = next;
348                 next = permutation[next];
349             }
350             permutation[curr] = curr;
351         }
352     }
353 }
354 
355 impl<'a, T, F> ZeroVecLike<T> for VarZeroVec<'a, T, F>
356 where
357     T: VarULE,
358     T: ?Sized,
359     F: VarZeroVecFormat,
360 {
361     type GetType = T;
362     type SliceVariant = VarZeroSlice<T, F>;
363 
zvl_new_borrowed() -> &'static Self::SliceVariant364     fn zvl_new_borrowed() -> &'static Self::SliceVariant {
365         VarZeroSlice::<T, F>::new_empty()
366     }
zvl_binary_search(&self, k: &T) -> Result<usize, usize> where T: Ord,367     fn zvl_binary_search(&self, k: &T) -> Result<usize, usize>
368     where
369         T: Ord,
370     {
371         self.binary_search(k)
372     }
zvl_binary_search_in_range(&self, k: &T, range: Range<usize>) -> Option<Result<usize, usize>> where T: Ord,373     fn zvl_binary_search_in_range(&self, k: &T, range: Range<usize>) -> Option<Result<usize, usize>>
374     where
375         T: Ord,
376     {
377         self.binary_search_in_range(k, range)
378     }
zvl_binary_search_by(&self, predicate: impl FnMut(&T) -> Ordering) -> Result<usize, usize>379     fn zvl_binary_search_by(&self, predicate: impl FnMut(&T) -> Ordering) -> Result<usize, usize> {
380         self.binary_search_by(predicate)
381     }
zvl_binary_search_in_range_by( &self, predicate: impl FnMut(&T) -> Ordering, range: Range<usize>, ) -> Option<Result<usize, usize>>382     fn zvl_binary_search_in_range_by(
383         &self,
384         predicate: impl FnMut(&T) -> Ordering,
385         range: Range<usize>,
386     ) -> Option<Result<usize, usize>> {
387         self.binary_search_in_range_by(predicate, range)
388     }
zvl_get(&self, index: usize) -> Option<&T>389     fn zvl_get(&self, index: usize) -> Option<&T> {
390         self.get(index)
391     }
zvl_len(&self) -> usize392     fn zvl_len(&self) -> usize {
393         self.len()
394     }
395 
zvl_as_borrowed(&self) -> &VarZeroSlice<T, F>396     fn zvl_as_borrowed(&self) -> &VarZeroSlice<T, F> {
397         self.as_slice()
398     }
399 
400     #[inline]
zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R401     fn zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R {
402         f(g)
403     }
404 }
405 
406 impl<T, F> ZeroVecLike<T> for VarZeroSlice<T, F>
407 where
408     T: VarULE,
409     T: ?Sized,
410     F: VarZeroVecFormat,
411 {
412     type GetType = T;
413     type SliceVariant = VarZeroSlice<T, F>;
414 
zvl_new_borrowed() -> &'static Self::SliceVariant415     fn zvl_new_borrowed() -> &'static Self::SliceVariant {
416         VarZeroSlice::<T, F>::new_empty()
417     }
zvl_binary_search(&self, k: &T) -> Result<usize, usize> where T: Ord,418     fn zvl_binary_search(&self, k: &T) -> Result<usize, usize>
419     where
420         T: Ord,
421     {
422         self.binary_search(k)
423     }
zvl_binary_search_in_range(&self, k: &T, range: Range<usize>) -> Option<Result<usize, usize>> where T: Ord,424     fn zvl_binary_search_in_range(&self, k: &T, range: Range<usize>) -> Option<Result<usize, usize>>
425     where
426         T: Ord,
427     {
428         self.binary_search_in_range(k, range)
429     }
zvl_binary_search_by(&self, predicate: impl FnMut(&T) -> Ordering) -> Result<usize, usize>430     fn zvl_binary_search_by(&self, predicate: impl FnMut(&T) -> Ordering) -> Result<usize, usize> {
431         self.binary_search_by(predicate)
432     }
zvl_binary_search_in_range_by( &self, predicate: impl FnMut(&T) -> Ordering, range: Range<usize>, ) -> Option<Result<usize, usize>>433     fn zvl_binary_search_in_range_by(
434         &self,
435         predicate: impl FnMut(&T) -> Ordering,
436         range: Range<usize>,
437     ) -> Option<Result<usize, usize>> {
438         self.binary_search_in_range_by(predicate, range)
439     }
zvl_get(&self, index: usize) -> Option<&T>440     fn zvl_get(&self, index: usize) -> Option<&T> {
441         self.get(index)
442     }
zvl_len(&self) -> usize443     fn zvl_len(&self) -> usize {
444         self.len()
445     }
446 
zvl_as_borrowed(&self) -> &VarZeroSlice<T, F>447     fn zvl_as_borrowed(&self) -> &VarZeroSlice<T, F> {
448         self
449     }
450 
451     #[inline]
zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R452     fn zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R {
453         f(g)
454     }
455 }
456 
457 impl<'a, T, F> MutableZeroVecLike<'a, T> for VarZeroVec<'a, T, F>
458 where
459     T: VarULE,
460     T: ?Sized,
461     F: VarZeroVecFormat,
462 {
463     type OwnedType = Box<T>;
zvl_insert(&mut self, index: usize, value: &T)464     fn zvl_insert(&mut self, index: usize, value: &T) {
465         self.make_mut().insert(index, value)
466     }
zvl_remove(&mut self, index: usize) -> Box<T>467     fn zvl_remove(&mut self, index: usize) -> Box<T> {
468         let vec = self.make_mut();
469         debug_assert!(index < vec.len());
470         #[allow(clippy::unwrap_used)]
471         let old = vec.get(index).unwrap().to_boxed();
472         vec.remove(index);
473         old
474     }
zvl_replace(&mut self, index: usize, value: &T) -> Box<T>475     fn zvl_replace(&mut self, index: usize, value: &T) -> Box<T> {
476         let vec = self.make_mut();
477         debug_assert!(index < vec.len());
478         #[allow(clippy::unwrap_used)]
479         let old = vec.get(index).unwrap().to_boxed();
480         vec.replace(index, value);
481         old
482     }
zvl_push(&mut self, value: &T)483     fn zvl_push(&mut self, value: &T) {
484         let len = self.len();
485         self.make_mut().insert(len, value)
486     }
zvl_with_capacity(cap: usize) -> Self487     fn zvl_with_capacity(cap: usize) -> Self {
488         if cap == 0 {
489             VarZeroVec::new()
490         } else {
491             Self::from(VarZeroVecOwned::with_capacity(cap))
492         }
493     }
zvl_clear(&mut self)494     fn zvl_clear(&mut self) {
495         self.make_mut().clear()
496     }
zvl_reserve(&mut self, addl: usize)497     fn zvl_reserve(&mut self, addl: usize) {
498         self.make_mut().reserve(addl)
499     }
500 
owned_as_t(o: &Self::OwnedType) -> &T501     fn owned_as_t(o: &Self::OwnedType) -> &T {
502         o
503     }
504 
zvl_from_borrowed(b: &'a VarZeroSlice<T, F>) -> Self505     fn zvl_from_borrowed(b: &'a VarZeroSlice<T, F>) -> Self {
506         b.as_varzerovec()
507     }
zvl_as_borrowed_inner(&self) -> Option<&'a VarZeroSlice<T, F>>508     fn zvl_as_borrowed_inner(&self) -> Option<&'a VarZeroSlice<T, F>> {
509         if let Self(VarZeroVecInner::Borrowed(b)) = *self {
510             Some(b)
511         } else {
512             None
513         }
514     }
515 
516     #[allow(clippy::unwrap_used)] // documented panic
zvl_permute(&mut self, permutation: &mut [usize])517     fn zvl_permute(&mut self, permutation: &mut [usize]) {
518         assert_eq!(permutation.len(), self.zvl_len());
519 
520         let mut result = VarZeroVecOwned::new();
521         for &i in permutation.iter() {
522             result.push(self.get(i).unwrap());
523         }
524         *self = Self(VarZeroVecInner::Owned(result));
525     }
526 }
527 
528 #[cfg(test)]
529 mod test {
530     use super::*;
531 
532     #[test]
test_zerovec_binary_search_in_range()533     fn test_zerovec_binary_search_in_range() {
534         let zv: ZeroVec<u16> = ZeroVec::from_slice_or_alloc(&[11, 22, 33, 44, 55, 66, 77]);
535 
536         // Full range search
537         assert_eq!(zv.zvl_binary_search_in_range(&11, 0..7), Some(Ok(0)));
538         assert_eq!(zv.zvl_binary_search_in_range(&12, 0..7), Some(Err(1)));
539         assert_eq!(zv.zvl_binary_search_in_range(&44, 0..7), Some(Ok(3)));
540         assert_eq!(zv.zvl_binary_search_in_range(&45, 0..7), Some(Err(4)));
541         assert_eq!(zv.zvl_binary_search_in_range(&77, 0..7), Some(Ok(6)));
542         assert_eq!(zv.zvl_binary_search_in_range(&78, 0..7), Some(Err(7)));
543 
544         // Out-of-range search
545         assert_eq!(zv.zvl_binary_search_in_range(&44, 0..2), Some(Err(2)));
546         assert_eq!(zv.zvl_binary_search_in_range(&44, 5..7), Some(Err(0)));
547 
548         // Offset search
549         assert_eq!(zv.zvl_binary_search_in_range(&44, 2..5), Some(Ok(1)));
550         assert_eq!(zv.zvl_binary_search_in_range(&45, 2..5), Some(Err(2)));
551 
552         // Out-of-bounds
553         assert_eq!(zv.zvl_binary_search_in_range(&44, 0..100), None);
554         assert_eq!(zv.zvl_binary_search_in_range(&44, 100..200), None);
555     }
556 
557     #[test]
test_permute()558     fn test_permute() {
559         let mut zv: ZeroVec<u16> = ZeroVec::from_slice_or_alloc(&[11, 22, 33, 44, 55, 66, 77]);
560         let mut permutation = vec![3, 2, 1, 0, 6, 5, 4];
561         zv.zvl_permute(&mut permutation);
562         assert_eq!(&zv, &[44, 33, 22, 11, 77, 66, 55]);
563 
564         let mut vzv: VarZeroVec<str> = VarZeroVec::from(
565             VarZeroVecOwned::try_from_elements(&["11", "22", "33", "44", "55", "66", "77"])
566                 .unwrap(),
567         );
568         let mut permutation = vec![3, 2, 1, 0, 6, 5, 4];
569         vzv.zvl_permute(&mut permutation);
570         assert_eq!(&vzv, &["44", "33", "22", "11", "77", "66", "55"]);
571     }
572 }
573