diff --git a/utils/zerovec/src/map/kv.rs b/utils/zerovec/src/map/kv.rs index 06816bf161e..415dbe671e7 100644 --- a/utils/zerovec/src/map/kv.rs +++ b/utils/zerovec/src/map/kv.rs @@ -8,18 +8,38 @@ use crate::VarZeroVec; use crate::ZeroVec; use std::cmp::Ordering; +/// Trait marking types which are allowed to be keys or values in [`ZeroMap`]. +/// +/// Users should not be calling methods of this trait directly, however if you are +/// implementing your own [`AsULE`] or [`AsVarULE`] type you may wish to implement +/// this trait. // this lifetime should be a GAT on Container once that is possible pub trait ZeroMapKV<'a>: Sized { + /// The container that can be used with this type: [`ZeroVec`] or [`VarZeroVec`]. type Container: ZeroVecLike<'a, Self, NeedleType = Self::NeedleType, GetType = Self::GetType> + Sized; + /// The type to use with `Container::binary_search()` + /// + /// This type will be predetermined by the choice of `Self::Container` type NeedleType: ?Sized; + /// The type produces by `Container::get()` + /// + /// This type will be predetermined by the choice of `Self::Container` type GetType: ?Sized; + /// The type to use whilst serializing. This may not necessarily be `Self`, however it + /// must serialize to the exact same thing as `Self` type SerializeType: ?Sized; + /// Convert to a needle for searching fn as_needle(&self) -> &Self::NeedleType; + /// Compare this type with a `Self::GetType`. This must produce the same result as + /// if `g` were converted to `Self` fn cmp_get(&self, g: &Self::GetType) -> Ordering; + /// Compare two `Self::GetType`s, as if they were both converted to `Self` fn cmp_two_gets(g1: &Self::GetType, g2: &Self::GetType) -> Ordering; - // This uses a callback because it's not possible to return owned-or-borrowed - // types without GATs + /// Obtain a version of this type suitable for serialization + /// + /// This uses a callback because it's not possible to return owned-or-borrowed + /// types without GATs fn get_as_ser(g: &Self::GetType, f: impl FnOnce(&Self::SerializeType) -> R) -> R; } diff --git a/utils/zerovec/src/map/mod.rs b/utils/zerovec/src/map/mod.rs index 93106827afa..47138c05abe 100644 --- a/utils/zerovec/src/map/mod.rs +++ b/utils/zerovec/src/map/mod.rs @@ -2,6 +2,8 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). +//! See [`ZeroMap`] for details. + use std::cmp::Ordering; mod kv; @@ -12,6 +14,12 @@ mod vecs; pub use kv::ZeroMapKV; pub use vecs::ZeroVecLike; +/// A zero-copy map datastructure, built on sorted binary-searchable [`ZeroVec`](crate::ZeroVec) +/// and [`VarZeroVec`](crate::VarZeroVec). +/// +/// This type, like [`ZeroVec`](crate::ZeroVec) and [`VarZeroVec`](crate::VarZeroVec), is able to zero-copy +/// deserialize from appropriately formatted byte buffers. It is internally copy-on-write, so it can be mutated +/// afterwards as necessary. pub struct ZeroMap<'a, K, V> where K: ZeroMapKV<'a>, diff --git a/utils/zerovec/src/map/vecs.rs b/utils/zerovec/src/map/vecs.rs index 38accbe013c..1071dadb0c3 100644 --- a/utils/zerovec/src/map/vecs.rs +++ b/utils/zerovec/src/map/vecs.rs @@ -7,19 +7,36 @@ use crate::VarZeroVec; use crate::ZeroVec; use std::mem; +/// Trait abstracting over [`ZeroVec`] and [`VarZeroVec`], for use in [`ZeroMap`]. You +/// should not be implementing or calling this trait directly. pub trait ZeroVecLike<'a, T> { + /// The type received by `Self::binary_search()` type NeedleType: ?Sized; + /// The type returned by `Self::get()` type GetType: ?Sized; + /// Search for a key in a sorted vector, returns `Ok(index)` if found, + /// returns `Err(insert_index)` if not found, where `insert_index` is the + /// index where it should be inserted to maintain sort order. fn binary_search(&self, k: &Self::NeedleType) -> Result; + /// Get element at `index` fn get(&self, index: usize) -> Option<&Self::GetType>; + /// Insert an element at `index` fn insert(&mut self, index: usize, value: T); + /// Remove the element at `index` (panicking if nonexistant) fn remove(&mut self, index: usize) -> T; + /// Replace the element at `index` with another one, returning the old element fn replace(&mut self, index: usize, value: T) -> T; + /// Push an element to the end of this vector fn push(&mut self, value: T); + /// The length of this vector fn len(&self) -> usize; + /// Create a new, empty vector fn new() -> Self; + /// Create a new, empty vector, with given capacity fn with_capacity(cap: usize) -> Self; + /// Remove all elements from the vector fn clear(&mut self); + /// Reserve space for `addl` additional elements fn reserve(&mut self, addl: usize); }