/// A borrowed-only version of [`ZeroMap`](super::ZeroMap) /// /// This is useful for fully-zero-copy deserialization from non-human-readable /// serialization formats. It also has the advantage that it can return references that live for /// the lifetime of the backing buffer as opposed to that of the [`ZeroMapBorrowed`] instance. /// /// # Examples /// /// ``` /// use zerovec::maps::ZeroMapBorrowed; /// /// // Example byte buffer representing the map { 1: "one" } /// let BINCODE_BYTES: &[u8; 29] = &[ /// 4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, /// 0, 0, 111, 110, 101, /// ]; /// /// // Deserializing to ZeroMap requires no heap allocations. /// let zero_map: ZeroMapBorrowed<u32, str> = /// bincode::deserialize(BINCODE_BYTES) /// .expect("Should deserialize successfully"); /// assert_eq!(zero_map.get(&1), Some("one")); /// ``` /// /// This can be obtained from a [`ZeroMap`](super::ZeroMap) via [`ZeroMap::as_borrowed`](super::ZeroMap::as_borrowed) pubstruct ZeroMapBorrowed<'a, K, V> where
K: ZeroMapKV<'a>,
V: ZeroMapKV<'a>,
K: ?Sized,
V: ?Sized,
{ pub(crate) keys: &'a <K as ZeroMapKV<'a>>::Slice, pub(crate) values: &'a <V as ZeroMapKV<'a>>::Slice,
}
/// The number of elements in the [`ZeroMapBorrowed`] pubfn len(&self) -> usize { self.values.zvl_len()
}
/// Whether the [`ZeroMapBorrowed`] is empty pubfn is_empty(&self) -> bool { self.values.zvl_len() == 0
}
}
impl<'a, K, V> ZeroMapBorrowed<'a, K, V> where
K: ZeroMapKV<'a> + Ord,
V: ZeroMapKV<'a>,
K: ?Sized,
V: ?Sized,
{ /// Get the value associated with `key`, if it exists. /// /// This is able to return values that live longer than the map itself /// since they borrow directly from the backing buffer. This is the /// primary advantage of using [`ZeroMapBorrowed`](super::ZeroMapBorrowed) over [`ZeroMap`](super::ZeroMap). /// /// ```rust /// use zerovec::ZeroMap; /// /// let mut map = ZeroMap::new(); /// map.insert(&1, "one"); /// map.insert(&2, "two"); /// let borrowed = map.as_borrowed(); /// assert_eq!(borrowed.get(&1), Some("one")); /// assert_eq!(borrowed.get(&3), None); /// ``` pubfn get(&self, key: &K) -> Option<&'a V::GetType> { let index = self.keys.zvl_binary_search(key).ok()?; self.values.zvl_get(index)
}
/// Binary search the map with `predicate` to find a key, returning the value. /// /// This is able to return values that live longer than the map itself /// since they borrow directly from the backing buffer. This is the /// primary advantage of using [`ZeroMapBorrowed`](super::ZeroMapBorrowed) over [`ZeroMap`](super::ZeroMap). /// /// ```rust /// use zerovec::ZeroMap; /// /// let mut map = ZeroMap::new(); /// map.insert(&1, "one"); /// map.insert(&2, "two"); /// let borrowed = map.as_borrowed(); /// assert_eq!(borrowed.get_by(|probe| probe.cmp(&1)), Some("one")); /// assert_eq!(borrowed.get_by(|probe| probe.cmp(&3)), None); /// ``` pubfn get_by(&self, predicate: impl FnMut(&K) -> Ordering) -> Option<&'a V::GetType> { let index = self.keys.zvl_binary_search_by(predicate).ok()?; self.values.zvl_get(index)
}
/// Returns whether `key` is contained in this map /// /// ```rust /// use zerovec::ZeroMap; /// /// let mut map = ZeroMap::new(); /// map.insert(&1, "one"); /// map.insert(&2, "two"); /// let borrowed = map.as_borrowed(); /// assert!(borrowed.contains_key(&1)); /// assert!(!borrowed.contains_key(&3)); /// ``` pubfn contains_key(&self, key: &K) -> bool { self.keys.zvl_binary_search(key).is_ok()
}
}
impl<'a, K, V> ZeroMapBorrowed<'a, K, V> where
K: ZeroMapKV<'a> + ?Sized,
V: ZeroMapKV<'a> + ?Sized,
{ /// Produce an ordered iterator over key-value pairs pubfn iter<'b>(
&'b self,
) -> impl Iterator<
Item = (
&'a <K as ZeroMapKV<'a>>::GetType,
&'a <V as ZeroMapKV<'a>>::GetType,
),
> + 'b { self.iter_keys().zip(self.iter_values())
}
/// Produce an ordered iterator over keys pubfn iter_keys<'b>(&'b self) -> impl Iterator<Item = &'a <K as ZeroMapKV<'a>>::GetType> + 'b { #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len()
(0..self.keys.zvl_len()).map(move |idx| self.keys.zvl_get(idx).unwrap())
}
/// Produce an iterator over values, ordered by keys pubfn iter_values<'b>(
&'b self,
) -> impl Iterator<Item = &'a <V as ZeroMapKV<'a>>::GetType> + 'b { #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() == values.zvl_len()
(0..self.values.zvl_len()).map(move |idx| self.values.zvl_get(idx).unwrap())
}
}
impl<'a, K, V> ZeroMapBorrowed<'a, K, V> where
K: ZeroMapKV<'a> + Ord + ?Sized,
V: ZeroMapKV<'a, Slice = ZeroSlice<V>> + AsULE + Copy + 'static,
{ /// For cases when `V` is fixed-size, obtain a direct copy of `V` instead of `V::ULE` pubfn get_copied(&self, key: &K) -> Option<V> { let index = self.keys.zvl_binary_search(key).ok()?; self.values.get(index)
}
/// For cases when `V` is fixed-size, obtain a direct copy of `V` instead of `V::ULE` pubfn get_copied_by(&self, predicate: impl FnMut(&K) -> Ordering) -> Option<V> { let index = self.keys.zvl_binary_search_by(predicate).ok()?; self.values.get(index)
}
/// Similar to [`Self::iter()`] except it returns a direct copy of the values instead of references /// to `V::ULE`, in cases when `V` is fixed-size pubfn iter_copied_values<'b>(
&'b self,
) -> impl Iterator<Item = (&'b <K as ZeroMapKV<'a>>::GetType, V)> {
(0..self.keys.zvl_len()).map(move |idx| {
( #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() self.keys.zvl_get(idx).unwrap(), #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len() self.values.get(idx).unwrap(),
)
})
}
}
impl<'a, K, V> ZeroMapBorrowed<'a, K, V> where
K: ZeroMapKV<'a, Slice = ZeroSlice<K>> + AsULE + Copy + Ord + 'static,
V: ZeroMapKV<'a, Slice = ZeroSlice<V>> + AsULE + Copy + 'static,
{ /// Similar to [`Self::iter()`] except it returns a direct copy of the keys values instead of references /// 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 pubfn iter_copied<'b: 'a>(&'b self) -> impl Iterator<Item = (K, V)> + 'b { let keys = &self.keys; let values = &self.values; let len = self.keys.zvl_len();
(0..len).map(move |idx| {
( #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len()
ZeroSlice::get(keys, idx).unwrap(), #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len()
ZeroSlice::get(values, idx).unwrap(),
)
})
}
}
// We can't use the default PartialEq because ZeroMap is invariant // so otherwise rustc will not automatically allow you to compare ZeroMaps // with different lifetimes impl<'a, 'b, K, V> PartialEq<ZeroMapBorrowed<'b, K, V>> for ZeroMapBorrowed<'a, K, V> where
K: for<'c> ZeroMapKV<'c> + ?Sized,
V: for<'c> ZeroMapKV<'c> + ?Sized,
<K as ZeroMapKV<'a>>::Slice: PartialEq<<K as ZeroMapKV<'b>>::Slice>,
<V as ZeroMapKV<'a>>::Slice: PartialEq<<V as ZeroMapKV<'b>>::Slice>,
{ fn eq(&self, other: &ZeroMapBorrowed<'b, K, V>) -> bool { self.keys.eq(other.keys) && self.values.eq(other.values)
}
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.19Bemerkung:
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.