diff options
Diffstat (limited to 'vendor/zerovec/src')
29 files changed, 800 insertions, 235 deletions
diff --git a/vendor/zerovec/src/error.rs b/vendor/zerovec/src/error.rs index 457a0d650..85de3ecc8 100644 --- a/vendor/zerovec/src/error.rs +++ b/vendor/zerovec/src/error.rs @@ -22,10 +22,10 @@ impl fmt::Display for ZeroVecError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match *self { ZeroVecError::InvalidLength { ty, len } => { - write!(f, "Invalid length {} for slice of type {}", len, ty) + write!(f, "Invalid length {len} for slice of type {ty}") } ZeroVecError::ParseError { ty } => { - write!(f, "Could not parse bytes to slice of type {}", ty) + write!(f, "Could not parse bytes to slice of type {ty}") } ZeroVecError::VarZeroVecFormatError => { write!(f, "Invalid format for VarZeroVec buffer") diff --git a/vendor/zerovec/src/flexzerovec/databake.rs b/vendor/zerovec/src/flexzerovec/databake.rs index 23bf156ef..4ce5f7dea 100644 --- a/vendor/zerovec/src/flexzerovec/databake.rs +++ b/vendor/zerovec/src/flexzerovec/databake.rs @@ -8,16 +8,24 @@ use databake::*; impl Bake for FlexZeroVec<'_> { fn bake(&self, env: &CrateEnv) -> TokenStream { env.insert("zerovec"); - let bytes = self.as_bytes(); - quote! { unsafe { ::zerovec::vecs::FlexZeroSlice::from_byte_slice_unchecked(&[#(#bytes),*]).as_flexzerovec() } } + if self.is_empty() { + quote! { ::zerovec::vecs::FlexZeroVec::new() } + } else { + let slice = self.as_ref().bake(env); + quote! { #slice.as_flexzerovec() } + } } } impl Bake for &FlexZeroSlice { fn bake(&self, env: &CrateEnv) -> TokenStream { env.insert("zerovec"); - let bytes = self.as_bytes(); - quote! { unsafe { ::zerovec::vecs::FlexZeroSlice::from_byte_slice_unchecked(&[#(#bytes),*]) } } + if self.is_empty() { + quote! { ::zerovec::vecs::FlexZeroSlice::new_empty() } + } else { + let bytes = databake::Bake::bake(&self.as_bytes(), env); + quote! { unsafe { ::zerovec::vecs::FlexZeroSlice::from_byte_slice_unchecked(#bytes) } } + } } } @@ -25,12 +33,16 @@ impl Bake for &FlexZeroSlice { fn test_baked_vec() { test_bake!( FlexZeroVec, + const: crate::vecs::FlexZeroVec::new(), + zerovec + ); + test_bake!( + FlexZeroVec, const: unsafe { - crate::vecs::FlexZeroSlice::from_byte_slice_unchecked(&[ - 2u8, 1u8, 0u8, 22u8, 0u8, 77u8, 1u8, 92u8, 17u8, - ]) - .as_flexzerovec() - }, + crate::vecs::FlexZeroSlice::from_byte_slice_unchecked( + b"\x02\x01\0\x16\0M\x01\x11" + ) + }.as_flexzerovec(), zerovec ); } @@ -39,10 +51,15 @@ fn test_baked_vec() { fn test_baked_slice() { test_bake!( &FlexZeroSlice, + const: crate::vecs::FlexZeroSlice::new_empty(), + zerovec + ); + test_bake!( + &FlexZeroSlice, const: unsafe { - crate::vecs::FlexZeroSlice::from_byte_slice_unchecked(&[ - 2u8, 1u8, 0u8, 22u8, 0u8, 77u8, 1u8, 92u8, 17u8, - ]) + crate::vecs::FlexZeroSlice::from_byte_slice_unchecked( + b"\x02\x01\0\x16\0M\x01\x11" + ) }, zerovec ); diff --git a/vendor/zerovec/src/flexzerovec/owned.rs b/vendor/zerovec/src/flexzerovec/owned.rs index 1039c59ae..7d7bfb33d 100644 --- a/vendor/zerovec/src/flexzerovec/owned.rs +++ b/vendor/zerovec/src/flexzerovec/owned.rs @@ -30,7 +30,7 @@ impl FlexZeroVecOwned { /// Obtains this [`FlexZeroVecOwned`] as a [`FlexZeroSlice`]. pub fn as_slice(&self) -> &FlexZeroSlice { - let slice: &[u8] = &*self.0; + let slice: &[u8] = &self.0; unsafe { // safety: the slice is known to come from a valid parsed FlexZeroSlice FlexZeroSlice::from_byte_slice_unchecked(slice) @@ -39,7 +39,7 @@ impl FlexZeroVecOwned { /// Mutably obtains this `FlexZeroVecOwned` as a [`FlexZeroSlice`]. pub(crate) fn as_mut_slice(&mut self) -> &mut FlexZeroSlice { - let slice: &mut [u8] = &mut *self.0; + let slice: &mut [u8] = &mut self.0; unsafe { // safety: the slice is known to come from a valid parsed FlexZeroSlice FlexZeroSlice::from_byte_slice_mut_unchecked(slice) @@ -255,42 +255,27 @@ mod test { use super::*; fn check_contents(fzv: &FlexZeroSlice, expected: &[usize]) { - assert_eq!( - fzv.len(), - expected.len(), - "len: {:?} != {:?}", - fzv, - expected - ); + assert_eq!(fzv.len(), expected.len(), "len: {fzv:?} != {expected:?}"); assert_eq!( fzv.is_empty(), expected.is_empty(), - "is_empty: {:?} != {:?}", - fzv, - expected + "is_empty: {fzv:?} != {expected:?}" ); assert_eq!( fzv.first(), expected.first().copied(), - "first: {:?} != {:?}", - fzv, - expected + "first: {fzv:?} != {expected:?}" ); assert_eq!( fzv.last(), expected.last().copied(), - "last: {:?} != {:?}", - fzv, - expected + "last: {fzv:?} != {expected:?}" ); for i in 0..(expected.len() + 1) { assert_eq!( fzv.get(i), expected.get(i).copied(), - "@{}: {:?} != {:?}", - i, - fzv, - expected + "@{i}: {fzv:?} != {expected:?}" ); } } diff --git a/vendor/zerovec/src/flexzerovec/slice.rs b/vendor/zerovec/src/flexzerovec/slice.rs index ee164d05b..fb58d6215 100644 --- a/vendor/zerovec/src/flexzerovec/slice.rs +++ b/vendor/zerovec/src/flexzerovec/slice.rs @@ -22,6 +22,12 @@ pub struct FlexZeroSlice { data: [u8], } +impl fmt::Debug for FlexZeroSlice { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.to_vec().fmt(f) + } +} + impl PartialEq for FlexZeroSlice { fn eq(&self, other: &Self) -> bool { self.width == other.width && self.data == other.data @@ -507,12 +513,6 @@ impl FlexZeroSlice { } } -impl fmt::Debug for &FlexZeroSlice { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.to_vec()) - } -} - #[inline] pub(crate) fn get_item_width(item_bytes: &[u8; USIZE_WIDTH]) -> usize { USIZE_WIDTH - item_bytes.iter().rev().take_while(|b| **b == 0).count() diff --git a/vendor/zerovec/src/flexzerovec/vec.rs b/vendor/zerovec/src/flexzerovec/vec.rs index a08f54e5d..dfd64ce65 100644 --- a/vendor/zerovec/src/flexzerovec/vec.rs +++ b/vendor/zerovec/src/flexzerovec/vec.rs @@ -134,7 +134,7 @@ impl<'a> FlexZeroVec<'a> { /// let zv: FlexZeroVec = FlexZeroVec::new(); /// assert!(zv.is_empty()); /// ``` - pub fn new() -> Self { + pub const fn new() -> Self { Self::Borrowed(FlexZeroSlice::new_empty()) } diff --git a/vendor/zerovec/src/hashmap/algorithms.rs b/vendor/zerovec/src/hashmap/algorithms.rs new file mode 100644 index 000000000..58ffc48f4 --- /dev/null +++ b/vendor/zerovec/src/hashmap/algorithms.rs @@ -0,0 +1,162 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use alloc::vec; +use alloc::vec::Vec; +use core::hash::{Hash, Hasher}; +use t1ha::T1haHasher; + +// Const seed to be used with [`T1haHasher::with_seed`]. +const SEED: u64 = 0xaabbccdd; + +/// Split the 64bit `hash` into (g, f0, f1). +/// g denotes the highest 16bits of the hash modulo `m`, and is referred to as first level hash. +/// (f0, f1) denotes the middle, and lower 24bits of the hash respectively. +/// (f0, f1) are used to distribute the keys with same g, into distinct slots. +/// +/// # Arguments +/// +/// * `hash` - The hash to split. +/// * `m` - The modulo used to split the hash. +pub const fn split_hash64(hash: u64, m: usize) -> (usize, u32, u32) { + ( + ((hash >> 48) as usize % m), + ((hash >> 24) as u32 & 0xffffff), + ((hash & 0xffffff) as u32), + ) +} + +/// Compute hash using [`T1haHasher`]. +pub fn compute_hash<K: Hash + ?Sized>(key: &K) -> u64 { + let mut hasher = T1haHasher::with_seed(SEED); + key.hash(&mut hasher); + hasher.finish() +} + +/// Calculate the index using (f0, f1), (d0, d1) in modulo m. +/// Returns [`None`] if d is (0, 0) or modulo is 0 +/// else returns the index computed using (f0 + f1 * d0 + d1) mod m. +pub fn compute_index(f: (u32, u32), d: (u32, u32), m: u32) -> Option<usize> { + if d == (0, 0) || m == 0 { + None + } else { + Some((f.1.wrapping_mul(d.0).wrapping_add(f.0).wrapping_add(d.1) % m) as usize) + } +} + +/// Compute displacements for the given `key_hashes`, which split the keys into distinct slots by a +/// two-level hashing schema. +/// Returns a tuple of where the first item is the displacement array and the second item is the +/// reverse mapping used to permute keys, values into their slots. +/// +/// 1. Split the hashes into (g, f0, f1). +/// 2. Bucket and sort the split hash on g in descending order. +/// 3. In decreasing order of bucket size, try until a (d0, d1) is found that splits the keys +/// in the bucket into distinct slots. +/// 4. Mark the slots for current bucket as occupied and store the reverse mapping. +/// 5. Repeat untill all the keys have been assigned distinct slots. +/// +/// # Arguments +/// +/// * `key_hashes` - [`ExactSizeIterator`] over the hashed key values +#[allow(clippy::indexing_slicing, clippy::unwrap_used)] +pub fn compute_displacements( + key_hashes: impl ExactSizeIterator<Item = u64>, +) -> (Vec<(u32, u32)>, Vec<usize>) { + let len = key_hashes.len(); + + // A vector to track the size of buckets for sorting. + let mut bucket_sizes = vec![0; len]; + + // A flattened representation of items in the buckets after applying first level hash function + let mut bucket_flatten = Vec::with_capacity(len); + + // Compute initial displacement and bucket sizes + + key_hashes.into_iter().enumerate().for_each(|(i, kh)| { + let h = split_hash64(kh, len); + bucket_sizes[h.0] += 1; + bucket_flatten.push((h, i)) + }); + + // Sort by decreasing order of bucket_sizes. + bucket_flatten.sort_by(|&(ha, _), &(hb, _)| { + // ha.0, hb.0 are always within bounds of `bucket_sizes` + (bucket_sizes[hb.0], hb).cmp(&(bucket_sizes[ha.0], ha)) + }); + + // Generation count while iterating buckets. + // Each trial of ((d0, d1), bucket chain) is a new generation. + // We use this to track which all slots are assigned for the current bucket chain. + let mut generation = 0; + + // Whether a slot has been occupied by previous buckets with a different first level hash (different + // bucket chain). + let mut occupied = vec![false; len]; + + // Track generation count for the slots. + // A slot is empty if either it is unoccupied by the previous bucket chains and the + // assignment is not equal to generation. + let mut assignments = vec![0; len]; + + // Vec to store the displacements (saves us a recomputation of hash while assigning slots). + let mut current_displacements = Vec::with_capacity(16); + + // (d0, d1) which splits the bucket into different slots + let mut displacements = vec![(0, 0); len]; + + // Vec to store mapping to the original order of keys. + // This is a permutation which will be applied to keys, values at the end. + let mut reverse_mapping = vec![0; len]; + + let mut start = 0; + while start < len { + // Bucket span with the same first level hash + // start is always within bounds of `bucket_flatten` + let g = bucket_flatten[start].0 .0; + // g is always within bounds of `bucket_sizes` + let end = start + bucket_sizes[g]; + // start, end - 1 are always within bounds of `bucket_sizes` + let buckets = &bucket_flatten[start..end]; + + 'd0: for d0 in 0..len as u32 { + 'd1: for d1 in 0..len as u32 { + if (d0, d1) == (0, 0) { + continue; + } + current_displacements.clear(); + generation += 1; + + for ((_, f0, f1), _) in buckets { + let displacement_idx = compute_index((*f0, *f1), (d0, d1), len as u32).unwrap(); + + // displacement_idx is always within bounds + if occupied[displacement_idx] || assignments[displacement_idx] == generation { + continue 'd1; + } + assignments[displacement_idx] = generation; + current_displacements.push(displacement_idx); + } + + // Successfully found a (d0, d1), store it as index g. + // g < displacements.len() due to modulo operation + displacements[g] = (d0, d1); + + for (i, displacement_idx) in current_displacements.iter().enumerate() { + // `current_displacements` has same size as `buckets` + let (_, idx) = &buckets[i]; + + // displacement_idx is always within bounds + occupied[*displacement_idx] = true; + reverse_mapping[*displacement_idx] = *idx; + } + break 'd0; + } + } + + start = end; + } + + (displacements, reverse_mapping) +} diff --git a/vendor/zerovec/src/hashmap/mod.rs b/vendor/zerovec/src/hashmap/mod.rs new file mode 100644 index 000000000..5d91114ad --- /dev/null +++ b/vendor/zerovec/src/hashmap/mod.rs @@ -0,0 +1,238 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::map::{MutableZeroVecLike, ZeroMapKV, ZeroVecLike}; +use crate::ZeroVec; +use alloc::borrow::Borrow; +use alloc::vec; +use core::hash::Hash; + +pub mod algorithms; +use algorithms::*; + +#[cfg(feature = "serde")] +mod serde; + +/// A perfect zerohashmap optimized for lookups over immutable keys. +/// +/// # Examples +/// ``` +/// use zerovec::ZeroHashMap; +/// +/// let kv = vec![(0, "a"), (1, "b"), (2, "c")]; +/// let hashmap: ZeroHashMap<i32, str> = ZeroHashMap::from_iter(kv.into_iter()); +/// assert_eq!(hashmap.get(&0), Some("a")); +/// assert_eq!(hashmap.get(&2), Some("c")); +/// assert_eq!(hashmap.get(&4), None); +/// ``` +#[derive(Debug)] +pub struct ZeroHashMap<'a, K, V> +where + K: ZeroMapKV<'a> + ?Sized, + V: ZeroMapKV<'a> + ?Sized, +{ + /// Array of (d0, d1) which splits the keys with same first level hash into distinct + /// slots. + /// The ith index of the array splits the keys with first level hash i. + /// If no key with first level hash is found in the original keys, (0, 0) is used as an empty + /// placeholder. + displacements: ZeroVec<'a, (u32, u32)>, + keys: K::Container, + values: V::Container, +} + +impl<'a, K, V> ZeroHashMap<'a, K, V> +where + K: ZeroMapKV<'a> + ?Sized, + V: ZeroMapKV<'a> + ?Sized, +{ + /// The number of elements in the [`ZeroHashMap`]. + pub fn len(&self) -> usize { + self.values.zvl_len() + } + + /// Whether the [`ZeroHashMap`] is empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +impl<'a, K, V> ZeroHashMap<'a, K, V> +where + K: ZeroMapKV<'a> + ?Sized + Hash + Eq, + V: ZeroMapKV<'a> + ?Sized, +{ + /// Given a `key` return the index for the key or [`None`] if the key is absent. + fn index<A>(&self, key: &A) -> Option<usize> + where + A: Borrow<K> + ?Sized, + { + let hash = compute_hash(key.borrow()); + let (g, f0, f1) = split_hash64(hash, self.len()); + + #[allow(clippy::unwrap_used)] // g is in-range + let (d0, d1) = self.displacements.get(g).unwrap(); + let index = compute_index((f0, f1), (d0, d1), self.displacements.len() as u32)?; + + #[allow(clippy::unwrap_used)] // index is in 0..self.keys.len() + let found = self.keys.zvl_get(index).unwrap(); + if K::Container::zvl_get_as_t(found, |found| found == key.borrow()) { + Some(index) + } else { + None + } + } + + /// Get the value corresponding to `key`. + /// If absent [`None`] is returned. + /// + /// # Example + /// ``` + /// use zerovec::ZeroHashMap; + /// + /// let hashmap: ZeroHashMap<str, str> = + /// ZeroHashMap::from_iter(vec![("a", "A"), ("z", "Z")].into_iter()); + /// + /// assert_eq!(hashmap.get("a"), Some("A")); + /// assert_eq!(hashmap.get("z"), Some("Z")); + /// assert_eq!(hashmap.get("0"), None); + /// ``` + pub fn get<'b, A>(&'b self, key: &A) -> Option<&'b V::GetType> + where + A: Borrow<K> + ?Sized + 'b, + { + self.index(key).and_then(|i| self.values.zvl_get(i)) + } + + /// Returns whether `key` is contained in this hashmap + /// + /// # Example + /// ```rust + /// use zerovec::ZeroHashMap; + /// + /// let hashmap: ZeroHashMap<str, str> = + /// ZeroHashMap::from_iter(vec![("a", "A"), ("z", "Z")].into_iter()); + /// + /// assert!(hashmap.contains_key("a")); + /// assert!(!hashmap.contains_key("p")); + /// ``` + pub fn contains_key(&self, key: &K) -> bool { + self.index(key).is_some() + } +} + +impl<'a, K, V> ZeroHashMap<'a, K, V> +where + K: ZeroMapKV<'a> + ?Sized, + V: ZeroMapKV<'a> + ?Sized, +{ + // Produce an iterator over (key, value) pairs. + pub fn iter<'b>( + &'b self, + ) -> impl ExactSizeIterator< + Item = ( + &'b <K as ZeroMapKV<'a>>::GetType, + &'b <V as ZeroMapKV<'a>>::GetType, + ), + > { + (0..self.len()).map(|index| { + ( + #[allow(clippy::unwrap_used)] // index is in range + self.keys.zvl_get(index).unwrap(), + #[allow(clippy::unwrap_used)] // index is in range + self.values.zvl_get(index).unwrap(), + ) + }) + } + + // Produce an iterator over keys. + pub fn iter_keys<'b>( + &'b self, + ) -> impl ExactSizeIterator<Item = &'b <K as ZeroMapKV<'a>>::GetType> { + #[allow(clippy::unwrap_used)] // index is in range + (0..self.len()).map(|index| self.keys.zvl_get(index).unwrap()) + } + + // Produce an iterator over values. + pub fn iter_values<'b>( + &'b self, + ) -> impl ExactSizeIterator<Item = &'b <V as ZeroMapKV<'a>>::GetType> { + #[allow(clippy::unwrap_used)] // index is in range + (0..self.len()).map(|index| self.values.zvl_get(index).unwrap()) + } +} + +impl<'a, K, V, A, B> FromIterator<(A, B)> for ZeroHashMap<'a, K, V> +where + K: ZeroMapKV<'a> + ?Sized + Hash + Eq, + V: ZeroMapKV<'a> + ?Sized, + B: Borrow<V>, + A: Borrow<K>, +{ + /// Build a [`ZeroHashMap`] from an iterator returning (K, V) tuples. + /// + /// # Example + /// ``` + /// use zerovec::ZeroHashMap; + /// + /// let kv: Vec<(i32, &str)> = vec![(1, "a"), (2, "b"), (3, "c"), (4, "d")]; + /// let hashmap: ZeroHashMap<i32, str> = ZeroHashMap::from_iter(kv.into_iter()); + /// assert_eq!(hashmap.get(&1), Some("a")); + /// assert_eq!(hashmap.get(&2), Some("b")); + /// assert_eq!(hashmap.get(&3), Some("c")); + /// assert_eq!(hashmap.get(&4), Some("d")); + /// ``` + fn from_iter<T: IntoIterator<Item = (A, B)>>(iter: T) -> Self { + let iter = iter.into_iter(); + let size_hint = match iter.size_hint() { + (_, Some(upper)) => upper, + (lower, None) => lower, + }; + + let mut key_hashes = vec![]; + key_hashes.reserve(size_hint); + let mut keys = K::Container::zvl_with_capacity(size_hint); + let mut values = V::Container::zvl_with_capacity(size_hint); + for (k, v) in iter { + keys.zvl_push(k.borrow()); + key_hashes.push(compute_hash(k.borrow())); + values.zvl_push(v.borrow()); + } + + let (displacements, mut reverse_mapping) = compute_displacements(key_hashes.into_iter()); + + keys.zvl_permute(&mut reverse_mapping.clone()); + values.zvl_permute(&mut reverse_mapping); + + Self { + displacements: ZeroVec::alloc_from_slice(&displacements), + values, + keys, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::ule::AsULE; + use rand::{distributions::Standard, Rng, SeedableRng}; + use rand_pcg::Lcg64Xsh32; + + #[test] + fn test_zhms_u64k_u64v() { + const N: usize = 65530; + let seed = u64::from_le_bytes(*b"testseed"); + let rng = Lcg64Xsh32::seed_from_u64(seed); + let kv: Vec<(u64, u64)> = rng.sample_iter(&Standard).take(N).collect(); + let hashmap: ZeroHashMap<u64, u64> = + ZeroHashMap::from_iter(kv.iter().map(|e| (&e.0, &e.1))); + for (k, v) in kv { + assert_eq!( + hashmap.get(&k).copied().map(<u64 as AsULE>::from_unaligned), + Some(v), + ); + } + } +} diff --git a/vendor/zerovec/src/hashmap/serde.rs b/vendor/zerovec/src/hashmap/serde.rs new file mode 100644 index 000000000..2d724ac05 --- /dev/null +++ b/vendor/zerovec/src/hashmap/serde.rs @@ -0,0 +1,147 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use super::ZeroHashMap; +use crate::{ + map::{ZeroMapKV, ZeroVecLike}, + ZeroVec, +}; + +use serde::{de, Deserialize, Serialize}; + +impl<'a, K, V> Serialize for ZeroHashMap<'a, K, V> +where + K: ZeroMapKV<'a> + Serialize + ?Sized, + V: ZeroMapKV<'a> + Serialize + ?Sized, + K::Container: Serialize, + V::Container: Serialize, +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + (&self.displacements, &self.keys, &self.values).serialize(serializer) + } +} + +impl<'de, 'a, K, V> Deserialize<'de> for ZeroHashMap<'a, K, V> +where + K: ZeroMapKV<'a> + ?Sized, + V: ZeroMapKV<'a> + ?Sized, + K::Container: Deserialize<'de>, + V::Container: Deserialize<'de>, + 'de: 'a, +{ + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + let (displacements, keys, values): (ZeroVec<(u32, u32)>, K::Container, V::Container) = + Deserialize::deserialize(deserializer)?; + if keys.zvl_len() != values.zvl_len() { + return Err(de::Error::custom( + "Mismatched key and value sizes in ZeroHashMap", + )); + } + if displacements.zvl_len() != keys.zvl_len() { + return Err(de::Error::custom( + "Mismatched displacements and key, value sizes in ZeroHashMap", + )); + } + Ok(Self { + displacements, + keys, + values, + }) + } +} + +#[cfg(test)] +mod test { + use crate::{VarZeroVec, ZeroHashMap, ZeroVec}; + use serde::{Deserialize, Serialize}; + + const JSON_STR: &str = "[[[0,1],[0,0],[0,1]],[2,1,0],[\"c\",\"b\",\"a\"]]"; + + const BINCODE_BYTES: &[u8] = &[ + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 1, 0, 2, 0, 99, 98, 97, + ]; + + #[derive(Serialize, Deserialize)] + struct DeriveTestZeroHashMap<'data> { + #[serde(borrow)] + _data: ZeroHashMap<'data, str, [u8]>, + } + + fn make_zerohashmap() -> ZeroHashMap<'static, u32, str> { + ZeroHashMap::from_iter(vec![(0, "a"), (1, "b"), (2, "c")].into_iter()) + } + + fn build_invalid_hashmap_str( + displacements: Vec<(u32, u32)>, + keys: Vec<u32>, + values: Vec<&str>, + ) -> String { + let invalid_hm: ZeroHashMap<u32, str> = ZeroHashMap { + displacements: ZeroVec::alloc_from_slice(&displacements), + keys: ZeroVec::alloc_from_slice(&keys), + values: VarZeroVec::<str>::from(&values), + }; + serde_json::to_string(&invalid_hm).expect("serialize") + } + + #[test] + fn test_invalid_deser_zhm() { + // Invalid hashmap |keys| != |values| + let mut invalid_hm_str = + build_invalid_hashmap_str(vec![(0, 1), (0, 0)], vec![1, 2], vec!["a", "b", "c"]); + + assert_eq!( + serde_json::from_str::<ZeroHashMap<u32, str>>(&invalid_hm_str) + .unwrap_err() + .to_string(), + "Mismatched key and value sizes in ZeroHashMap" + ); + + // Invalid hashmap |displacements| != |keys| == |values| + // |displacements| = 2, |keys| = 3, |values| = 3 + invalid_hm_str = + build_invalid_hashmap_str(vec![(0, 1), (0, 0)], vec![2, 1, 0], vec!["a", "b", "c"]); + + assert_eq!( + serde_json::from_str::<ZeroHashMap<u32, str>>(&invalid_hm_str) + .unwrap_err() + .to_string(), + "Mismatched displacements and key, value sizes in ZeroHashMap" + ); + } + + #[test] + fn test_serde_valid_deser_zhm() { + let hm = make_zerohashmap(); + let json_str = serde_json::to_string(&hm).expect("serialize"); + assert_eq!(json_str, JSON_STR); + let deserialized_hm: ZeroHashMap<u32, str> = + serde_json::from_str(JSON_STR).expect("deserialize"); + assert_eq!( + hm.iter().collect::<Vec<_>>(), + deserialized_hm.iter().collect::<Vec<_>>() + ); + } + + #[test] + fn test_bincode_zhm() { + let hm = make_zerohashmap(); + let bincode_bytes = bincode::serialize(&hm).expect("serialize"); + assert_eq!(bincode_bytes, BINCODE_BYTES); + let deserialized_hm: ZeroHashMap<u32, str> = + bincode::deserialize(BINCODE_BYTES).expect("deserialize"); + assert_eq!( + hm.iter().collect::<Vec<_>>(), + deserialized_hm.iter().collect::<Vec<_>>() + ); + } +} diff --git a/vendor/zerovec/src/lib.rs b/vendor/zerovec/src/lib.rs index b8b292488..add52f113 100644 --- a/vendor/zerovec/src/lib.rs +++ b/vendor/zerovec/src/lib.rs @@ -204,7 +204,7 @@ clippy::panic, clippy::exhaustive_structs, clippy::exhaustive_enums, - // TODO(#2266): enable missing_debug_implementations, + missing_debug_implementations, ) )] // this crate does a lot of nuanced lifetime manipulation, being explicit @@ -215,6 +215,8 @@ extern crate alloc; mod error; mod flexzerovec; +#[cfg(feature = "hashmap")] +pub mod hashmap; mod map; mod map2d; #[cfg(test)] @@ -231,6 +233,8 @@ mod yoke_impls; mod zerofrom_impls; pub use crate::error::ZeroVecError; +#[cfg(feature = "hashmap")] +pub use crate::hashmap::ZeroHashMap; pub use crate::map::map::ZeroMap; pub use crate::map2d::map::ZeroMap2d; pub use crate::varzerovec::{slice::VarZeroSlice, vec::VarZeroVec}; diff --git a/vendor/zerovec/src/map/borrowed.rs b/vendor/zerovec/src/map/borrowed.rs index 9d0854601..bc93ee497 100644 --- a/vendor/zerovec/src/map/borrowed.rs +++ b/vendor/zerovec/src/map/borrowed.rs @@ -277,8 +277,8 @@ where /// to `K::ULE` and `V::ULE`, in cases when `K` and `V` are fixed-size #[allow(clippy::needless_lifetimes)] // Lifetime is necessary in impl Trait pub fn iter_copied<'b: 'a>(&'b self) -> impl Iterator<Item = (K, V)> + 'b { - let keys = &*self.keys; - let values = &*self.values; + let keys = &self.keys; + let values = &self.values; let len = self.keys.zvl_len(); (0..len).map(move |idx| { ( diff --git a/vendor/zerovec/src/map/databake.rs b/vendor/zerovec/src/map/databake.rs index d98b48f9f..fceb6a966 100644 --- a/vendor/zerovec/src/map/databake.rs +++ b/vendor/zerovec/src/map/databake.rs @@ -43,16 +43,14 @@ fn test_baked_map() { #[allow(unused_unsafe)] crate::ZeroMap::from_parts_unchecked( unsafe { - crate::VarZeroVec::from_bytes_unchecked(&[ - 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 97u8, - 100u8, 98u8, 99u8, - ]) + crate::VarZeroVec::from_bytes_unchecked( + b"\x02\0\0\0\0\0\0\0\x02\0\0\0adbc" + ) }, unsafe { - crate::VarZeroVec::from_bytes_unchecked(&[ - 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 69u8, 82u8, - 65u8, 49u8, 69u8, 82u8, 65u8, 48u8, - ]) + crate::VarZeroVec::from_bytes_unchecked( + b"\x02\0\0\0\0\0\0\0\x04\0\0\0ERA1ERA0" + ) }, ) }, @@ -68,16 +66,14 @@ fn test_baked_borrowed_map() { #[allow(unused_unsafe)] crate::maps::ZeroMapBorrowed::from_parts_unchecked( unsafe { - crate::VarZeroSlice::from_bytes_unchecked(&[ - 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 97u8, - 100u8, 98u8, 99u8, - ]) + crate::VarZeroSlice::from_bytes_unchecked( + b"\x02\0\0\0\0\0\0\0\x02\0\0\0adbc" + ) }, unsafe { - crate::VarZeroSlice::from_bytes_unchecked(&[ - 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 69u8, 82u8, - 65u8, 49u8, 69u8, 82u8, 65u8, 48u8, - ]) + crate::VarZeroSlice::from_bytes_unchecked( + b"\x02\0\0\0\0\0\0\0\x04\0\0\0ERA1ERA0" + ) }, ) }, diff --git a/vendor/zerovec/src/map/vecs.rs b/vendor/zerovec/src/map/vecs.rs index b460e5967..5ee93d3fe 100644 --- a/vendor/zerovec/src/map/vecs.rs +++ b/vendor/zerovec/src/map/vecs.rs @@ -195,7 +195,7 @@ where where T: Ord, { - let zs: &ZeroSlice<T> = &*self; + let zs: &ZeroSlice<T> = self; zs.zvl_binary_search_in_range(k, range) } fn zvl_binary_search_by( @@ -209,7 +209,7 @@ where predicate: impl FnMut(&T) -> Ordering, range: Range<usize>, ) -> Option<Result<usize, usize>> { - let zs: &ZeroSlice<T> = &*self; + let zs: &ZeroSlice<T> = self; zs.zvl_binary_search_in_range_by(predicate, range) } fn zvl_get(&self, index: usize) -> Option<&T::ULE> { @@ -218,11 +218,9 @@ where fn zvl_len(&self) -> usize { ZeroSlice::len(self) } - fn zvl_as_borrowed(&self) -> &ZeroSlice<T> { - &*self + self } - #[inline] fn zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R { f(&T::from_unaligned(*g)) @@ -274,7 +272,6 @@ where fn zvl_len(&self) -> usize { ZeroSlice::len(self) } - fn zvl_as_borrowed(&self) -> &ZeroSlice<T> { self } @@ -565,7 +562,7 @@ impl<'a> ZeroVecLike<usize> for FlexZeroVec<'a> { } fn zvl_as_borrowed(&self) -> &FlexZeroSlice { - &*self + self } #[inline] diff --git a/vendor/zerovec/src/map2d/databake.rs b/vendor/zerovec/src/map2d/databake.rs index 90ab970bb..65e475c32 100644 --- a/vendor/zerovec/src/map2d/databake.rs +++ b/vendor/zerovec/src/map2d/databake.rs @@ -51,49 +51,24 @@ fn test_baked_map() { #[allow(unused_unsafe)] crate::ZeroMap2d::from_parts_unchecked( unsafe { - crate::VarZeroVec::from_bytes_unchecked(&[ - 97u8, 114u8, 99u8, 97u8, 122u8, 0u8, 99u8, 117u8, 0u8, 101u8, 110u8, 0u8, - 102u8, 102u8, 0u8, 103u8, 114u8, 99u8, 107u8, 107u8, 0u8, 107u8, 117u8, - 0u8, 107u8, 121u8, 0u8, 108u8, 105u8, 102u8, 109u8, 97u8, 110u8, 109u8, - 110u8, 0u8, 112u8, 97u8, 0u8, 112u8, 97u8, 108u8, 115u8, 100u8, 0u8, 116u8, - 103u8, 0u8, 117u8, 103u8, 0u8, 117u8, 110u8, 114u8, 117u8, 122u8, 0u8, - 121u8, 117u8, 101u8, 122u8, 104u8, 0u8, - ]) + crate::VarZeroVec::from_bytes_unchecked( + b"arcaz\0cu\0en\0ff\0grckk\0ku\0ky\0lifmanmn\0pa\0palsd\0tg\0ug\0unruz\0yuezh\0" + ) }, unsafe { - crate::ZeroVec::from_bytes_unchecked(&[ - 2u8, 0u8, 0u8, 0u8, 3u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 5u8, 0u8, 0u8, - 0u8, 6u8, 0u8, 0u8, 0u8, 7u8, 0u8, 0u8, 0u8, 8u8, 0u8, 0u8, 0u8, 10u8, 0u8, - 0u8, 0u8, 12u8, 0u8, 0u8, 0u8, 13u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, - 15u8, 0u8, 0u8, 0u8, 16u8, 0u8, 0u8, 0u8, 17u8, 0u8, 0u8, 0u8, 20u8, 0u8, - 0u8, 0u8, 21u8, 0u8, 0u8, 0u8, 22u8, 0u8, 0u8, 0u8, 23u8, 0u8, 0u8, 0u8, - 24u8, 0u8, 0u8, 0u8, 25u8, 0u8, 0u8, 0u8, 28u8, 0u8, 0u8, 0u8, - ]) + crate::ZeroVec::from_bytes_unchecked( + b"\x02\0\0\0\x03\0\0\0\x04\0\0\0\x05\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\n\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x10\0\0\0\x11\0\0\0\x14\0\0\0\x15\0\0\0\x16\0\0\0\x17\0\0\0\x18\0\0\0\x19\0\0\0\x1C\0\0\0" + ) }, unsafe { - crate::VarZeroVec::from_bytes_unchecked(&[ - 78u8, 98u8, 97u8, 116u8, 80u8, 97u8, 108u8, 109u8, 65u8, 114u8, 97u8, 98u8, - 71u8, 108u8, 97u8, 103u8, 83u8, 104u8, 97u8, 119u8, 65u8, 100u8, 108u8, - 109u8, 76u8, 105u8, 110u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, - 97u8, 98u8, 89u8, 101u8, 122u8, 105u8, 65u8, 114u8, 97u8, 98u8, 76u8, 97u8, - 116u8, 110u8, 76u8, 105u8, 109u8, 98u8, 78u8, 107u8, 111u8, 111u8, 77u8, - 111u8, 110u8, 103u8, 65u8, 114u8, 97u8, 98u8, 80u8, 104u8, 108u8, 112u8, - 68u8, 101u8, 118u8, 97u8, 75u8, 104u8, 111u8, 106u8, 83u8, 105u8, 110u8, - 100u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8, 68u8, 101u8, - 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8, 115u8, 66u8, - 111u8, 112u8, 111u8, 72u8, 97u8, 110u8, 98u8, 72u8, 97u8, 110u8, 116u8, - ]) + crate::VarZeroVec::from_bytes_unchecked( + b"NbatPalmArabGlagShawAdlmLinbArabArabYeziArabLatnLimbNkooMongArabPhlpDevaKhojSindArabCyrlDevaArabHansBopoHanbHant" + ) }, unsafe { - crate::VarZeroVec::from_bytes_unchecked(&[ - 74u8, 79u8, 0u8, 83u8, 89u8, 0u8, 73u8, 82u8, 0u8, 66u8, 71u8, 0u8, 71u8, - 66u8, 0u8, 71u8, 78u8, 0u8, 71u8, 82u8, 0u8, 67u8, 78u8, 0u8, 73u8, 81u8, - 0u8, 71u8, 69u8, 0u8, 67u8, 78u8, 0u8, 84u8, 82u8, 0u8, 73u8, 78u8, 0u8, - 71u8, 78u8, 0u8, 67u8, 78u8, 0u8, 80u8, 75u8, 0u8, 67u8, 78u8, 0u8, 73u8, - 78u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 75u8, 90u8, - 0u8, 78u8, 80u8, 0u8, 65u8, 70u8, 0u8, 67u8, 78u8, 0u8, 84u8, 87u8, 0u8, - 84u8, 87u8, 0u8, 84u8, 87u8, 0u8, - ]) + crate::VarZeroVec::from_bytes_unchecked( + b"JO\0SY\0IR\0BG\0GB\0GN\0GR\0CN\0IQ\0GE\0CN\0TR\0IN\0GN\0CN\0PK\0CN\0IN\0IN\0IN\0PK\0KZ\0NP\0AF\0CN\0TW\0TW\0TW\0" + ) }, ) }, @@ -109,49 +84,24 @@ fn test_baked_borrowed_map() { #[allow(unused_unsafe)] crate::maps::ZeroMap2dBorrowed::from_parts_unchecked( unsafe { - crate::VarZeroSlice::from_bytes_unchecked(&[ - 97u8, 114u8, 99u8, 97u8, 122u8, 0u8, 99u8, 117u8, 0u8, 101u8, 110u8, 0u8, - 102u8, 102u8, 0u8, 103u8, 114u8, 99u8, 107u8, 107u8, 0u8, 107u8, 117u8, - 0u8, 107u8, 121u8, 0u8, 108u8, 105u8, 102u8, 109u8, 97u8, 110u8, 109u8, - 110u8, 0u8, 112u8, 97u8, 0u8, 112u8, 97u8, 108u8, 115u8, 100u8, 0u8, 116u8, - 103u8, 0u8, 117u8, 103u8, 0u8, 117u8, 110u8, 114u8, 117u8, 122u8, 0u8, - 121u8, 117u8, 101u8, 122u8, 104u8, 0u8, - ]) + crate::VarZeroSlice::from_bytes_unchecked( + b"arcaz\0cu\0en\0ff\0grckk\0ku\0ky\0lifmanmn\0pa\0palsd\0tg\0ug\0unruz\0yuezh\0" + ) }, unsafe { - crate::ZeroSlice::from_bytes_unchecked(&[ - 2u8, 0u8, 0u8, 0u8, 3u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 5u8, 0u8, 0u8, - 0u8, 6u8, 0u8, 0u8, 0u8, 7u8, 0u8, 0u8, 0u8, 8u8, 0u8, 0u8, 0u8, 10u8, 0u8, - 0u8, 0u8, 12u8, 0u8, 0u8, 0u8, 13u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, - 15u8, 0u8, 0u8, 0u8, 16u8, 0u8, 0u8, 0u8, 17u8, 0u8, 0u8, 0u8, 20u8, 0u8, - 0u8, 0u8, 21u8, 0u8, 0u8, 0u8, 22u8, 0u8, 0u8, 0u8, 23u8, 0u8, 0u8, 0u8, - 24u8, 0u8, 0u8, 0u8, 25u8, 0u8, 0u8, 0u8, 28u8, 0u8, 0u8, 0u8, - ]) + crate::ZeroSlice::from_bytes_unchecked( + b"\x02\0\0\0\x03\0\0\0\x04\0\0\0\x05\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\n\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x10\0\0\0\x11\0\0\0\x14\0\0\0\x15\0\0\0\x16\0\0\0\x17\0\0\0\x18\0\0\0\x19\0\0\0\x1C\0\0\0" + ) }, unsafe { - crate::VarZeroSlice::from_bytes_unchecked(&[ - 78u8, 98u8, 97u8, 116u8, 80u8, 97u8, 108u8, 109u8, 65u8, 114u8, 97u8, 98u8, - 71u8, 108u8, 97u8, 103u8, 83u8, 104u8, 97u8, 119u8, 65u8, 100u8, 108u8, - 109u8, 76u8, 105u8, 110u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, - 97u8, 98u8, 89u8, 101u8, 122u8, 105u8, 65u8, 114u8, 97u8, 98u8, 76u8, 97u8, - 116u8, 110u8, 76u8, 105u8, 109u8, 98u8, 78u8, 107u8, 111u8, 111u8, 77u8, - 111u8, 110u8, 103u8, 65u8, 114u8, 97u8, 98u8, 80u8, 104u8, 108u8, 112u8, - 68u8, 101u8, 118u8, 97u8, 75u8, 104u8, 111u8, 106u8, 83u8, 105u8, 110u8, - 100u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8, 68u8, 101u8, - 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8, 115u8, 66u8, - 111u8, 112u8, 111u8, 72u8, 97u8, 110u8, 98u8, 72u8, 97u8, 110u8, 116u8, - ]) + crate::VarZeroSlice::from_bytes_unchecked( + b"NbatPalmArabGlagShawAdlmLinbArabArabYeziArabLatnLimbNkooMongArabPhlpDevaKhojSindArabCyrlDevaArabHansBopoHanbHant" + ) }, unsafe { - crate::VarZeroSlice::from_bytes_unchecked(&[ - 74u8, 79u8, 0u8, 83u8, 89u8, 0u8, 73u8, 82u8, 0u8, 66u8, 71u8, 0u8, 71u8, - 66u8, 0u8, 71u8, 78u8, 0u8, 71u8, 82u8, 0u8, 67u8, 78u8, 0u8, 73u8, 81u8, - 0u8, 71u8, 69u8, 0u8, 67u8, 78u8, 0u8, 84u8, 82u8, 0u8, 73u8, 78u8, 0u8, - 71u8, 78u8, 0u8, 67u8, 78u8, 0u8, 80u8, 75u8, 0u8, 67u8, 78u8, 0u8, 73u8, - 78u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 75u8, 90u8, - 0u8, 78u8, 80u8, 0u8, 65u8, 70u8, 0u8, 67u8, 78u8, 0u8, 84u8, 87u8, 0u8, - 84u8, 87u8, 0u8, 84u8, 87u8, 0u8, - ]) + crate::VarZeroSlice::from_bytes_unchecked( + b"JO\0SY\0IR\0BG\0GB\0GN\0GR\0CN\0IQ\0GE\0CN\0TR\0IN\0GN\0CN\0PK\0CN\0IN\0IN\0IN\0PK\0KZ\0NP\0AF\0CN\0TW\0TW\0TW\0" + ) }, ) }, diff --git a/vendor/zerovec/src/map2d/map.rs b/vendor/zerovec/src/map2d/map.rs index e6545dfa5..8bdefe792 100644 --- a/vendor/zerovec/src/map2d/map.rs +++ b/vendor/zerovec/src/map2d/map.rs @@ -160,7 +160,7 @@ where pub fn as_borrowed(&'a self) -> ZeroMap2dBorrowed<'a, K0, K1, V> { ZeroMap2dBorrowed { keys0: self.keys0.zvl_as_borrowed(), - joiner: &*self.joiner, + joiner: &self.joiner, keys1: self.keys1.zvl_as_borrowed(), values: self.values.zvl_as_borrowed(), } @@ -710,7 +710,7 @@ mod test { let mut zm2d = ZeroMap2d::<u16, str, str>::new(); assert_eq!( - format!("{:?}", zm2d), + format!("{zm2d:?}"), "ZeroMap2d { keys0: ZeroVec([]), joiner: ZeroVec([]), keys1: [], values: [] }" ); assert_eq!(zm2d.get0(&0), None); @@ -718,7 +718,7 @@ mod test { let result = zm2d.try_append(&3, "ccc", "CCC"); assert!(matches!(result, None)); - assert_eq!(format!("{:?}", zm2d), "ZeroMap2d { keys0: ZeroVec([3]), joiner: ZeroVec([1]), keys1: [\"ccc\"], values: [\"CCC\"] }"); + assert_eq!(format!("{zm2d:?}"), "ZeroMap2d { keys0: ZeroVec([3]), joiner: ZeroVec([1]), keys1: [\"ccc\"], values: [\"CCC\"] }"); assert_eq!(zm2d.get0(&0), None); assert_eq!(zm2d.get0(&3).unwrap().get1(""), None); assert_eq!(zm2d.get_2d(&3, "ccc"), Some("CCC")); @@ -727,7 +727,7 @@ mod test { let result = zm2d.try_append(&3, "eee", "EEE"); assert!(matches!(result, None)); - assert_eq!(format!("{:?}", zm2d), "ZeroMap2d { keys0: ZeroVec([3]), joiner: ZeroVec([2]), keys1: [\"ccc\", \"eee\"], values: [\"CCC\", \"EEE\"] }"); + assert_eq!(format!("{zm2d:?}"), "ZeroMap2d { keys0: ZeroVec([3]), joiner: ZeroVec([2]), keys1: [\"ccc\", \"eee\"], values: [\"CCC\", \"EEE\"] }"); assert_eq!(zm2d.get0(&0), None); assert_eq!(zm2d.get0(&3).unwrap().get1(""), None); assert_eq!(zm2d.get_2d(&3, "ccc"), Some("CCC")); @@ -751,7 +751,7 @@ mod test { let result = zm2d.try_append(&9, "yyy", "YYY"); assert!(matches!(result, None)); - assert_eq!(format!("{:?}", zm2d), "ZeroMap2d { keys0: ZeroVec([3, 5, 7, 9]), joiner: ZeroVec([2, 3, 6, 7]), keys1: [\"ccc\", \"eee\", \"ddd\", \"ddd\", \"eee\", \"www\", \"yyy\"], values: [\"CCC\", \"EEE\", \"DD1\", \"DD2\", \"EEE\", \"WWW\", \"YYY\"] }"); + assert_eq!(format!("{zm2d:?}"), "ZeroMap2d { keys0: ZeroVec([3, 5, 7, 9]), joiner: ZeroVec([2, 3, 6, 7]), keys1: [\"ccc\", \"eee\", \"ddd\", \"ddd\", \"eee\", \"www\", \"yyy\"], values: [\"CCC\", \"EEE\", \"DD1\", \"DD2\", \"EEE\", \"WWW\", \"YYY\"] }"); assert_eq!(zm2d.get0(&0), None); assert_eq!(zm2d.get0(&3).unwrap().get1(""), None); assert_eq!(zm2d.get_2d(&3, "ccc"), Some("CCC")); @@ -782,7 +782,7 @@ mod test { zm2d.insert(&6, "mmm", "MM1"); zm2d.insert(&6, "nnn", "NNN"); - assert_eq!(format!("{:?}", zm2d), "ZeroMap2d { keys0: ZeroVec([3, 5, 6, 7, 9]), joiner: ZeroVec([3, 4, 7, 10, 11]), keys1: [\"ccc\", \"eee\", \"mmm\", \"ddd\", \"ddd\", \"mmm\", \"nnn\", \"ddd\", \"eee\", \"www\", \"yyy\"], values: [\"CCC\", \"EEE\", \"MM0\", \"DD1\", \"DD3\", \"MM1\", \"NNN\", \"DD2\", \"EEE\", \"WWW\", \"YYY\"] }"); + assert_eq!(format!("{zm2d:?}"), "ZeroMap2d { keys0: ZeroVec([3, 5, 6, 7, 9]), joiner: ZeroVec([3, 4, 7, 10, 11]), keys1: [\"ccc\", \"eee\", \"mmm\", \"ddd\", \"ddd\", \"mmm\", \"nnn\", \"ddd\", \"eee\", \"www\", \"yyy\"], values: [\"CCC\", \"EEE\", \"MM0\", \"DD1\", \"DD3\", \"MM1\", \"NNN\", \"DD2\", \"EEE\", \"WWW\", \"YYY\"] }"); assert_eq!(zm2d.get0(&0), None); assert_eq!(zm2d.get0(&3).unwrap().get1(""), None); assert_eq!(zm2d.get_2d(&3, "ccc"), Some("CCC")); @@ -822,6 +822,6 @@ mod test { let result = zm2d.remove(&9, "yyy"); // last element assert_eq!(result.as_deref(), Some("YYY")); - assert_eq!(format!("{:?}", zm2d), "ZeroMap2d { keys0: ZeroVec([3, 6, 7]), joiner: ZeroVec([1, 4, 7]), keys1: [\"eee\", \"ddd\", \"mmm\", \"nnn\", \"ddd\", \"eee\", \"www\"], values: [\"EEE\", \"DD3\", \"MM1\", \"NNN\", \"DD2\", \"EEE\", \"WWW\"] }"); + assert_eq!(format!("{zm2d:?}"), "ZeroMap2d { keys0: ZeroVec([3, 6, 7]), joiner: ZeroVec([1, 4, 7]), keys1: [\"eee\", \"ddd\", \"mmm\", \"nnn\", \"ddd\", \"eee\", \"www\"], values: [\"EEE\", \"DD3\", \"MM1\", \"NNN\", \"DD2\", \"EEE\", \"WWW\"] }"); } } diff --git a/vendor/zerovec/src/map2d/serde.rs b/vendor/zerovec/src/map2d/serde.rs index b5e913654..53e3284b3 100644 --- a/vendor/zerovec/src/map2d/serde.rs +++ b/vendor/zerovec/src/map2d/serde.rs @@ -388,7 +388,7 @@ mod test { assert_eq!(JSON_STR, json_str); let new_map: ZeroMap2d<u32, u16, str> = serde_json::from_str(&json_str).expect("deserialize"); - assert_eq!(format!("{:?}", new_map), format!("{:?}", map)); + assert_eq!(format!("{new_map:?}"), format!("{map:?}")); } #[test] @@ -399,15 +399,15 @@ mod test { let new_map: ZeroMap2d<u32, u16, str> = bincode::deserialize(&bincode_bytes).expect("deserialize"); assert_eq!( - format!("{:?}", new_map), - format!("{:?}", map).replace("Owned", "Borrowed"), + format!("{new_map:?}"), + format!("{map:?}").replace("Owned", "Borrowed"), ); let new_map: ZeroMap2dBorrowed<u32, u16, str> = bincode::deserialize(&bincode_bytes).expect("deserialize"); assert_eq!( - format!("{:?}", new_map), - format!("{:?}", map) + format!("{new_map:?}"), + format!("{map:?}") .replace("Owned", "Borrowed") .replace("ZeroMap2d", "ZeroMap2dBorrowed") ); diff --git a/vendor/zerovec/src/ule/chars.rs b/vendor/zerovec/src/ule/chars.rs index 4298d7338..7a4a97a4a 100644 --- a/vendor/zerovec/src/ule/chars.rs +++ b/vendor/zerovec/src/ule/chars.rs @@ -37,7 +37,7 @@ use core::convert::TryFrom; /// CharULE::parse_byte_slice(bytes).expect_err("Invalid bytes"); /// ``` #[repr(transparent)] -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CharULE([u8; 3]); // Safety (based on the safety checklist on the ULE trait): diff --git a/vendor/zerovec/src/ule/encode.rs b/vendor/zerovec/src/ule/encode.rs index 3043bbd0a..2091cf06b 100644 --- a/vendor/zerovec/src/ule/encode.rs +++ b/vendor/zerovec/src/ule/encode.rs @@ -121,7 +121,7 @@ where unsafe impl<T: VarULE + ?Sized> EncodeAsVarULE<T> for Box<T> { fn encode_var_ule_as_slices<R>(&self, cb: impl FnOnce(&[&[u8]]) -> R) -> R { - cb(&[T::as_byte_slice(&*self)]) + cb(&[T::as_byte_slice(self)]) } } @@ -138,7 +138,7 @@ where T: ULE, { fn encode_var_ule_as_slices<R>(&self, cb: impl FnOnce(&[&[u8]]) -> R) -> R { - cb(&[<[T] as VarULE>::as_byte_slice(&*self)]) + cb(&[<[T] as VarULE>::as_byte_slice(self)]) } } diff --git a/vendor/zerovec/src/ule/multi.rs b/vendor/zerovec/src/ule/multi.rs index 1eacfac69..0ba0aea89 100644 --- a/vendor/zerovec/src/ule/multi.rs +++ b/vendor/zerovec/src/ule/multi.rs @@ -15,7 +15,7 @@ use core::mem; /// where `V1` etc are potentially different [`VarULE`] types. /// /// Internally, it is represented by a VarZeroSlice. -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Debug)] #[repr(transparent)] pub struct MultiFieldsULE(VarZeroSlice<[u8], Index32>); diff --git a/vendor/zerovec/src/ule/niche.rs b/vendor/zerovec/src/ule/niche.rs index 688357f77..ae61faca0 100644 --- a/vendor/zerovec/src/ule/niche.rs +++ b/vendor/zerovec/src/ule/niche.rs @@ -10,7 +10,7 @@ use super::{AsULE, ULE}; /// can never occur as a valid byte representation of the type. /// /// Guarantees for a valid implementation. -/// 1. N must be equal to core::mem::sizeo_of::<Self>() or else it will +/// 1. N must be equal to `core::mem::sizeo_of::<Self>()` or else it will /// cause panics. /// 2. The bit pattern [`NicheBytes::NICHE_BIT_PATTERN`] must not be incorrect as it would lead to /// weird behaviour. @@ -54,8 +54,16 @@ pub union NichedOptionULE<U: NicheBytes<N> + ULE, const N: usize> { valid: U, } +impl<U: NicheBytes<N> + ULE + core::fmt::Debug, const N: usize> core::fmt::Debug + for NichedOptionULE<U, N> +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.get().fmt(f) + } +} + impl<U: NicheBytes<N> + ULE, const N: usize> NichedOptionULE<U, N> { - /// New NichedOptionULE<U, N> from Option<U> + /// New `NichedOptionULE<U, N>` from `Option<U>` pub fn new(opt: Option<U>) -> Self { assert!(N == core::mem::size_of::<U>()); match opt { @@ -66,7 +74,7 @@ impl<U: NicheBytes<N> + ULE, const N: usize> NichedOptionULE<U, N> { } } - /// Convert to an Option<U> + /// Convert to an `Option<U>` pub fn get(self) -> Option<U> { // Safety: The union stores NICHE_BIT_PATTERN when None otherwise a valid U unsafe { @@ -131,7 +139,7 @@ unsafe impl<U: NicheBytes<N> + ULE, const N: usize> ULE for NichedOptionULE<U, N } /// Optional type which uses [`NichedOptionULE<U,N>`] as ULE type. -/// The implementors guarantee that N == core::mem::sizeo_of::<Self>() +/// The implementors guarantee that `N == core::mem::sizeo_of::<Self>()` /// [`repr(transparent)`] guarantees that the layout is same as [`Option<U>`] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[repr(transparent)] diff --git a/vendor/zerovec/src/ule/option.rs b/vendor/zerovec/src/ule/option.rs index a6b1966a5..50b193aac 100644 --- a/vendor/zerovec/src/ule/option.rs +++ b/vendor/zerovec/src/ule/option.rs @@ -32,7 +32,7 @@ use core::mem::{self, MaybeUninit}; pub struct OptionULE<U>(bool, MaybeUninit<U>); impl<U: Copy> OptionULE<U> { - /// Obtain this as an Option<T> + /// Obtain this as an `Option<T>` pub fn get(self) -> Option<U> { if self.0 { unsafe { @@ -44,7 +44,7 @@ impl<U: Copy> OptionULE<U> { } } - /// Construct an OptionULE<U> from an equivalent Option<T> + /// Construct an `OptionULE<U>` from an equivalent `Option<T>` pub fn new(opt: Option<U>) -> Self { if let Some(inner) = opt { Self(true, MaybeUninit::new(inner)) @@ -54,6 +54,12 @@ impl<U: Copy> OptionULE<U> { } } +impl<U: Copy + core::fmt::Debug> core::fmt::Debug for OptionULE<U> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.get().fmt(f) + } +} + // Safety (based on the safety checklist on the ULE trait): // 1. OptionULE does not include any uninitialized or padding bytes. // (achieved by `#[repr(packed)]` on a struct containing only ULE fields, @@ -152,6 +158,12 @@ impl<U: VarULE + ?Sized> OptionVarULE<U> { } } +impl<U: VarULE + ?Sized + core::fmt::Debug> core::fmt::Debug for OptionVarULE<U> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.as_ref().fmt(f) + } +} + // Safety (based on the safety checklist on the VarULE trait): // 1. OptionVarULE<T> does not include any uninitialized or padding bytes // (achieved by being repr(packed) on ULE types) diff --git a/vendor/zerovec/src/varzerovec/components.rs b/vendor/zerovec/src/varzerovec/components.rs index bf70c83c5..ff26d9029 100644 --- a/vendor/zerovec/src/varzerovec/components.rs +++ b/vendor/zerovec/src/varzerovec/components.rs @@ -85,7 +85,7 @@ unsafe impl VarZeroVecFormat for Index16 { unsafe impl VarZeroVecFormat for Index32 { const INDEX_WIDTH: usize = 4; - const MAX_VALUE: u32 = u32::MAX as u32; + const MAX_VALUE: u32 = u32::MAX; type RawBytes = RawBytesULE<4>; #[inline] fn rawbytes_to_usize(raw: Self::RawBytes) -> usize { @@ -110,6 +110,7 @@ unsafe impl VarZeroVecFormat for Index32 { /// exist. /// /// See [`VarZeroVecComponents::parse_byte_slice()`] for information on the internal invariants involved +#[derive(Debug)] pub struct VarZeroVecComponents<'a, T: ?Sized, F> { /// The number of elements len: u32, @@ -197,7 +198,7 @@ impl<'a, T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecComponents<'a, T, F> .ok_or(ZeroVecError::VarZeroVecFormatError)?; let borrowed = VarZeroVecComponents { - len: len as u32, + len, indices: indices_bytes, things, entire_slice: slice, @@ -392,7 +393,7 @@ impl<'a, T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecComponents<'a, T, F> .copied() .map(F::rawbytes_to_usize) .collect::<Vec<_>>(); - format!("VarZeroVecComponents {{ indices: {:?} }}", indices) + format!("VarZeroVecComponents {{ indices: {indices:?} }}") } } diff --git a/vendor/zerovec/src/varzerovec/databake.rs b/vendor/zerovec/src/varzerovec/databake.rs index 2c3d506b3..8d9fc0bfc 100644 --- a/vendor/zerovec/src/varzerovec/databake.rs +++ b/vendor/zerovec/src/varzerovec/databake.rs @@ -8,18 +8,26 @@ use databake::*; impl<T: VarULE + ?Sized> Bake for VarZeroVec<'_, T> { fn bake(&self, env: &CrateEnv) -> TokenStream { env.insert("zerovec"); - let bytes = self.as_bytes(); - // Safe because self.as_bytes is a safe input - quote! { unsafe { ::zerovec::VarZeroVec::from_bytes_unchecked(&[#(#bytes),*]) } } + if self.is_empty() { + quote! { ::zerovec::VarZeroVec::new() } + } else { + let bytes = databake::Bake::bake(&self.as_bytes(), env); + // Safe because self.as_bytes is a safe input + quote! { unsafe { ::zerovec::VarZeroVec::from_bytes_unchecked(#bytes) } } + } } } impl<T: VarULE + ?Sized> Bake for &VarZeroSlice<T> { fn bake(&self, env: &CrateEnv) -> TokenStream { env.insert("zerovec"); - let bytes = self.as_bytes(); - // Safe because self.as_bytes is a safe input - quote! { unsafe { ::zerovec::VarZeroSlice::from_bytes_unchecked(&[#(#bytes),*]) } } + if self.is_empty() { + quote! { ::zerovec::VarZeroSlice::new_empty() } + } else { + let bytes = databake::Bake::bake(&self.as_bytes(), env); + // Safe because self.as_bytes is a safe input + quote! { unsafe { ::zerovec::VarZeroSlice::from_bytes_unchecked(#bytes) } } + } } } @@ -27,10 +35,15 @@ impl<T: VarULE + ?Sized> Bake for &VarZeroSlice<T> { fn test_baked_vec() { test_bake!( VarZeroVec<str>, + const: crate::VarZeroVec::new(), + zerovec + ); + test_bake!( + VarZeroVec<str>, const: unsafe { - crate::VarZeroVec::from_bytes_unchecked(&[ - 2u8, 1u8, 0u8, 22u8, 0u8, 77u8, 1u8, 92u8, 17u8, - ]) + crate::VarZeroVec::from_bytes_unchecked( + b"\x02\x01\0\x16\0M\x01\\\x11" + ) }, zerovec ); @@ -40,10 +53,15 @@ fn test_baked_vec() { fn test_baked_slice() { test_bake!( &VarZeroSlice<str>, + const: crate::VarZeroSlice::new_empty(), + zerovec + ); + test_bake!( + &VarZeroSlice<str>, const: unsafe { - crate::VarZeroSlice::from_bytes_unchecked(&[ - 2u8, 1u8, 0u8, 22u8, 0u8, 77u8, 1u8, 92u8, 17u8, - ]) + crate::VarZeroSlice::from_bytes_unchecked( + b"\x02\x01\0\x16\0M\x01\\\x11" + ) }, zerovec ); diff --git a/vendor/zerovec/src/varzerovec/owned.rs b/vendor/zerovec/src/varzerovec/owned.rs index af4692d48..76de48760 100644 --- a/vendor/zerovec/src/varzerovec/owned.rs +++ b/vendor/zerovec/src/varzerovec/owned.rs @@ -96,7 +96,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecOwned<T, F> { /// Obtain this `VarZeroVec` as a [`VarZeroSlice`] pub fn as_slice(&self) -> &VarZeroSlice<T, F> { - let slice: &[u8] = &*self.entire_slice; + let slice: &[u8] = &self.entire_slice; unsafe { // safety: the slice is known to come from a valid parsed VZV VarZeroSlice::from_byte_slice_unchecked(slice) @@ -146,7 +146,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecOwned<T, F> { unsafe fn element_range_unchecked(&self, idx: usize) -> core::ops::Range<usize> { let start = self.element_position_unchecked(idx); let end = self.element_position_unchecked(idx + 1); - debug_assert!(start <= end, "{} > {}", start, end); + debug_assert!(start <= end, "{start} > {end}"); start..end } @@ -353,7 +353,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecOwned<T, F> { + METADATA_WIDTH + self.len() * F::INDEX_WIDTH + self.element_position_unchecked(index); - &mut self.entire_slice[element_pos..element_pos + new_size as usize] + &mut self.entire_slice[element_pos..element_pos + new_size] } /// Checks the internal invariants of the vec to ensure safe code will not cause UB. @@ -423,10 +423,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecOwned<T, F> { pub fn insert<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A) { let len = self.len(); if index > len { - panic!( - "Called out-of-bounds insert() on VarZeroVec, index {} len {}", - index, len - ); + panic!("Called out-of-bounds insert() on VarZeroVec, index {index} len {len}"); } let value_len = element.encode_var_ule_len(); @@ -451,10 +448,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecOwned<T, F> { pub fn remove(&mut self, index: usize) { let len = self.len(); if index >= len { - panic!( - "Called out-of-bounds remove() on VarZeroVec, index {} len {}", - index, len - ); + panic!("Called out-of-bounds remove() on VarZeroVec, index {index} len {len}"); } if len == 1 { // This is removing the last element. Set the slice to empty to ensure all empty vecs have empty data slices. @@ -470,10 +464,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecOwned<T, F> { pub fn replace<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A) { let len = self.len(); if index >= len { - panic!( - "Called out-of-bounds replace() on VarZeroVec, index {} len {}", - index, len - ); + panic!("Called out-of-bounds replace() on VarZeroVec, index {index} len {len}"); } let value_len = element.encode_var_ule_len(); diff --git a/vendor/zerovec/src/varzerovec/vec.rs b/vendor/zerovec/src/varzerovec/vec.rs index 7edb48a96..1401a180a 100644 --- a/vendor/zerovec/src/varzerovec/vec.rs +++ b/vendor/zerovec/src/varzerovec/vec.rs @@ -248,7 +248,7 @@ impl<'a, T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVec<'a, T, F> { /// assert!(vzv.is_empty()); /// ``` #[inline] - pub fn new() -> Self { + pub const fn new() -> Self { Self::Borrowed(VarZeroSlice::new_empty()) } @@ -354,7 +354,7 @@ impl<'a, T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVec<'a, T, F> { /// Obtain this `VarZeroVec` as a [`VarZeroSlice`] pub fn as_slice(&self) -> &VarZeroSlice<T, F> { match *self { - VarZeroVec::Owned(ref owned) => &**owned, + VarZeroVec::Owned(ref owned) => owned, VarZeroVec::Borrowed(b) => b, } } @@ -413,8 +413,7 @@ where { #[inline] fn from(elements: &Vec<A>) -> Self { - #[allow(clippy::unwrap_used)] // TODO(#1410) Better story for fallibility - VarZeroVecOwned::try_from_elements(elements).unwrap().into() + Self::from(elements.as_slice()) } } @@ -439,8 +438,7 @@ where { #[inline] fn from(elements: &[A; N]) -> Self { - #[allow(clippy::unwrap_used)] // TODO(#1410) Better story for fallibility - VarZeroVecOwned::try_from_elements(elements).unwrap().into() + Self::from(elements.as_slice()) } } diff --git a/vendor/zerovec/src/yoke_impls.rs b/vendor/zerovec/src/yoke_impls.rs index 0efb47a2d..a5064a554 100644 --- a/vendor/zerovec/src/yoke_impls.rs +++ b/vendor/zerovec/src/yoke_impls.rs @@ -4,6 +4,7 @@ // This way we can copy-paste Yokeable impls #![allow(clippy::forget_copy)] +#![allow(clippy::forget_non_drop)] use crate::flexzerovec::FlexZeroVec; use crate::map::ZeroMapBorrowed; @@ -305,11 +306,12 @@ mod test { } #[test] + #[ignore] // https://github.com/rust-lang/rust/issues/98906 fn bake_ZeroVec() { test_bake!( DeriveTest_ZeroVec<'static>, crate::yoke_impls::test::DeriveTest_ZeroVec { - _data: unsafe { crate::ZeroVec::from_bytes_unchecked(&[]) }, + _data: crate::ZeroVec::new(), }, zerovec, ); @@ -328,7 +330,7 @@ mod test { test_bake!( DeriveTest_ZeroSlice<'static>, crate::yoke_impls::test::DeriveTest_ZeroSlice { - _data: unsafe { crate::ZeroSlice::from_bytes_unchecked(&[]) }, + _data: crate::ZeroSlice::new_empty(), }, zerovec, ); @@ -343,13 +345,13 @@ mod test { } #[test] + #[ignore] // https://github.com/rust-lang/rust/issues/98906 fn bake_FlexZeroVec() { test_bake!( DeriveTest_FlexZeroVec<'static>, crate::yoke_impls::test::DeriveTest_FlexZeroVec { - _data: unsafe { - crate::vecs::FlexZeroSlice::from_byte_slice_unchecked(&[1u8]).as_flexzerovec() - }, + _data: unsafe { crate::vecs::FlexZeroSlice::from_byte_slice_unchecked(b"\x01") } + .as_flexzerovec(), }, zerovec, ); @@ -368,7 +370,7 @@ mod test { test_bake!( DeriveTest_FlexZeroSlice<'static>, crate::yoke_impls::test::DeriveTest_FlexZeroSlice { - _data: unsafe { crate::vecs::FlexZeroSlice::from_byte_slice_unchecked(&[1u8]) }, + _data: unsafe { crate::vecs::FlexZeroSlice::from_byte_slice_unchecked(b"\x01\0") }, }, zerovec, ); @@ -387,7 +389,7 @@ mod test { test_bake!( DeriveTest_VarZeroVec<'static>, crate::yoke_impls::test::DeriveTest_VarZeroVec { - _data: unsafe { crate::VarZeroVec::from_bytes_unchecked(&[]) }, + _data: crate::VarZeroVec::new(), }, zerovec, ); @@ -406,7 +408,7 @@ mod test { test_bake!( DeriveTest_VarZeroSlice<'static>, crate::yoke_impls::test::DeriveTest_VarZeroSlice { - _data: unsafe { crate::VarZeroSlice::from_bytes_unchecked(&[]) } + _data: crate::VarZeroSlice::new_empty() }, zerovec, ); @@ -429,8 +431,8 @@ mod test { _data: unsafe { #[allow(unused_unsafe)] crate::ZeroMap::from_parts_unchecked( - unsafe { crate::VarZeroVec::from_bytes_unchecked(&[]) }, - unsafe { crate::VarZeroVec::from_bytes_unchecked(&[]) }, + crate::VarZeroVec::new(), + crate::VarZeroVec::new(), ) }, }, @@ -455,8 +457,8 @@ mod test { _data: unsafe { #[allow(unused_unsafe)] crate::maps::ZeroMapBorrowed::from_parts_unchecked( - unsafe { crate::VarZeroSlice::from_bytes_unchecked(&[]) }, - unsafe { crate::VarZeroSlice::from_bytes_unchecked(&[]) }, + crate::VarZeroSlice::new_empty(), + crate::VarZeroSlice::new_empty(), ) }, }, @@ -481,8 +483,8 @@ mod test { _data: unsafe { #[allow(unused_unsafe)] crate::ZeroMap::from_parts_unchecked( - unsafe { crate::VarZeroVec::from_bytes_unchecked(&[]) }, - unsafe { crate::VarZeroVec::from_bytes_unchecked(&[]) }, + crate::VarZeroVec::new(), + crate::VarZeroVec::new(), ) }, }, @@ -507,10 +509,10 @@ mod test { _data: unsafe { #[allow(unused_unsafe)] crate::ZeroMap2d::from_parts_unchecked( - unsafe { crate::ZeroVec::from_bytes_unchecked(&[]) }, - unsafe { crate::ZeroVec::from_bytes_unchecked(&[]) }, - unsafe { crate::ZeroVec::from_bytes_unchecked(&[]) }, - unsafe { crate::VarZeroVec::from_bytes_unchecked(&[]) }, + crate::ZeroVec::new(), + crate::ZeroVec::new(), + crate::ZeroVec::new(), + crate::VarZeroVec::new(), ) }, }, @@ -535,10 +537,10 @@ mod test { _data: unsafe { #[allow(unused_unsafe)] crate::maps::ZeroMap2dBorrowed::from_parts_unchecked( - unsafe { crate::ZeroSlice::from_bytes_unchecked(&[]) }, - unsafe { crate::ZeroSlice::from_bytes_unchecked(&[]) }, - unsafe { crate::ZeroSlice::from_bytes_unchecked(&[]) }, - unsafe { crate::VarZeroSlice::from_bytes_unchecked(&[]) }, + crate::ZeroSlice::new_empty(), + crate::ZeroSlice::new_empty(), + crate::ZeroSlice::new_empty(), + crate::VarZeroSlice::new_empty(), ) }, }, diff --git a/vendor/zerovec/src/zerofrom_impls.rs b/vendor/zerovec/src/zerofrom_impls.rs index dfb3da187..d17e432c4 100644 --- a/vendor/zerovec/src/zerofrom_impls.rs +++ b/vendor/zerovec/src/zerofrom_impls.rs @@ -41,14 +41,14 @@ where impl<'zf> ZeroFrom<'zf, FlexZeroVec<'_>> for FlexZeroVec<'zf> { #[inline] fn zero_from(other: &'zf FlexZeroVec<'_>) -> Self { - FlexZeroVec::Borrowed(&*other) + FlexZeroVec::Borrowed(other) } } impl<'zf> ZeroFrom<'zf, FlexZeroSlice> for FlexZeroVec<'zf> { #[inline] fn zero_from(other: &'zf FlexZeroSlice) -> Self { - FlexZeroVec::Borrowed(&*other) + FlexZeroVec::Borrowed(other) } } diff --git a/vendor/zerovec/src/zerovec/databake.rs b/vendor/zerovec/src/zerovec/databake.rs index 0643ddb40..e46065c38 100644 --- a/vendor/zerovec/src/zerovec/databake.rs +++ b/vendor/zerovec/src/zerovec/databake.rs @@ -12,8 +12,12 @@ where { fn bake(&self, env: &CrateEnv) -> TokenStream { env.insert("zerovec"); - let bytes = self.as_bytes(); - quote! { unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(&[#(#bytes),*]) } } + if self.is_empty() { + quote! { ::zerovec::ZeroVec::new() } + } else { + let bytes = databake::Bake::bake(&self.as_bytes(), env); + quote! { unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(#bytes) } } + } } } @@ -23,8 +27,12 @@ where { fn bake(&self, env: &CrateEnv) -> TokenStream { env.insert("zerovec"); - let bytes = self.as_bytes(); - quote! { unsafe { ::zerovec::ZeroSlice::from_bytes_unchecked(&[#(#bytes),*]) } } + if self.is_empty() { + quote! { ::zerovec::ZeroSlice::new_empty() } + } else { + let bytes = databake::Bake::bake(&self.as_bytes(), env); + quote! { unsafe { ::zerovec::ZeroSlice::from_bytes_unchecked(#bytes) } } + } } } @@ -32,8 +40,13 @@ where fn test_baked_vec() { test_bake!( ZeroVec<u32>, + const: crate::ZeroVec::new(), + zerovec + ); + test_bake!( + ZeroVec<u32>, const: unsafe { - crate::ZeroVec::from_bytes_unchecked(&[2u8, 1u8, 0u8, 22u8, 0u8, 77u8, 1u8, 92u8]) + crate::ZeroVec::from_bytes_unchecked(b"\x02\x01\0\x16\0M\x01\\") }, zerovec ); @@ -43,8 +56,13 @@ fn test_baked_vec() { fn test_baked_slice() { test_bake!( &ZeroSlice<u32>, + const: crate::ZeroSlice::new_empty(), + zerovec + ); + test_bake!( + &ZeroSlice<u32>, const: unsafe { - crate::ZeroSlice::from_bytes_unchecked(&[2u8, 1u8, 0u8, 22u8, 0u8, 77u8, 1u8, 92u8]) + crate::ZeroSlice::from_bytes_unchecked(b"\x02\x01\0\x16\0M\x01\\") }, zerovec ); diff --git a/vendor/zerovec/src/zerovec/mod.rs b/vendor/zerovec/src/zerovec/mod.rs index 371450e21..e7c87f68e 100644 --- a/vendor/zerovec/src/zerovec/mod.rs +++ b/vendor/zerovec/src/zerovec/mod.rs @@ -284,7 +284,7 @@ where // Deconstruct the vector into parts // This is the only part of the code that goes from Vec // to ZeroVec, all other such operations should use this function - let slice: &[T::ULE] = &*vec; + let slice: &[T::ULE] = &vec; let slice = slice as *const [_] as *mut [_]; let capacity = vec.capacity(); mem::forget(vec); diff --git a/vendor/zerovec/src/zerovec/slice.rs b/vendor/zerovec/src/zerovec/slice.rs index 847705304..52ddc184b 100644 --- a/vendor/zerovec/src/zerovec/slice.rs +++ b/vendor/zerovec/src/zerovec/slice.rs @@ -191,6 +191,27 @@ where .map(T::from_unaligned) } + /// Gets the entire slice as an array of length `N`. Returns None if the slice + /// does not have exactly `N` elements. + /// + /// # Example + /// + /// ``` + /// use zerovec::ZeroVec; + /// + /// let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80]; + /// let zerovec: ZeroVec<u16> = + /// ZeroVec::parse_byte_slice(bytes).expect("infallible"); + /// let array: [u16; 4] = + /// zerovec.get_as_array().expect("should be 4 items in array"); + /// + /// assert_eq!(array[2], 421); + /// ``` + pub fn get_as_array<const N: usize>(&self) -> Option<[T; N]> { + let ule_array = <&[T::ULE; N]>::try_from(self.as_ule_slice()).ok()?; + Some(ule_array.map(|u| T::from_unaligned(u))) + } + /// Gets a subslice of elements within a certain range. Returns None if the range /// is out of bounds of this `ZeroSlice`. /// @@ -510,7 +531,7 @@ where } } -impl<'a, T: AsULE + PartialOrd> PartialOrd for ZeroSlice<T> { +impl<T: AsULE + PartialOrd> PartialOrd for ZeroSlice<T> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.iter().partial_cmp(other.iter()) } @@ -524,13 +545,13 @@ impl<T: AsULE + Ord> Ord for ZeroSlice<T> { impl<T: AsULE> AsRef<ZeroSlice<T>> for Vec<T::ULE> { fn as_ref(&self) -> &ZeroSlice<T> { - ZeroSlice::<T>::from_ule_slice(&**self) + ZeroSlice::<T>::from_ule_slice(self) } } impl<T: AsULE> AsRef<ZeroSlice<T>> for &[T::ULE] { fn as_ref(&self) -> &ZeroSlice<T> { - ZeroSlice::<T>::from_ule_slice(&**self) + ZeroSlice::<T>::from_ule_slice(self) } } |