Skip to content

Commit

Permalink
Remove AsVarULE (unicode-org#1126)
Browse files Browse the repository at this point in the history
  • Loading branch information
Manishearth authored and robertbastian committed Oct 4, 2021
1 parent f312726 commit 77185f4
Show file tree
Hide file tree
Showing 17 changed files with 392 additions and 383 deletions.
4 changes: 2 additions & 2 deletions utils/yoke/derive/examples/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct CowExample<'a> {

#[derive(Yokeable, ZeroCopyFrom)]
pub struct ZeroVecExample<'a> {
var: VarZeroVec<'a, String>,
var: VarZeroVec<'a, str>,
vec: ZeroVec<'a, u16>,
}

Expand All @@ -34,7 +34,7 @@ pub struct ZeroVecExample<'a> {
#[derive(Yokeable)]
#[yoke(prove_covariance_manually)]
pub struct ZeroMapExample<'a> {
map: ZeroMap<'a, String, u16>,
map: ZeroMap<'a, str, u16>,
}

fn main() {}
4 changes: 2 additions & 2 deletions utils/zerovec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ pub struct DataStruct<'data> {
#[serde(borrow)]
nums: ZeroVec<'data, u32>,
#[serde(borrow)]
strs: VarZeroVec<'data, String>,
strs: VarZeroVec<'data, str>,
}

let data = DataStruct {
nums: ZeroVec::from_slice(&[211, 281, 421, 461]),
strs: VarZeroVec::from(&["hello".to_string(), "world".to_string()] as &[_]),
strs: VarZeroVec::from(&["hello", "world"] as &[_]),
};
let bincode_bytes = bincode::serialize(&data)
.expect("Serialization should be successful");
Expand Down
19 changes: 11 additions & 8 deletions utils/zerovec/benches/vzv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ fn overview_bench(c: &mut Criterion) {
// Same as vzv/char_count/vzv but with different inputs
let seed = 42;
let (string_vec, _) = random_alphanums(2..=10, 100, seed);
let bytes: Vec<u8> = VarZeroVec::get_serializable_bytes(string_vec.as_slice()).unwrap();
let vzv = VarZeroVec::<String>::parse_byte_slice(black_box(bytes.as_slice())).unwrap();
let bytes: Vec<u8> =
VarZeroVec::<str>::get_serializable_bytes::<String>(string_vec.as_slice()).unwrap();
let vzv = VarZeroVec::<str>::parse_byte_slice(black_box(bytes.as_slice())).unwrap();

c.bench_function("vzv/overview", |b| {
b.iter(|| {
Expand All @@ -72,8 +73,9 @@ fn overview_bench(c: &mut Criterion) {
fn char_count_benches(c: &mut Criterion) {
let seed = 2021;
let (string_vec, _) = random_alphanums(2..=20, 100, seed);
let bytes: Vec<u8> = VarZeroVec::get_serializable_bytes(string_vec.as_slice()).unwrap();
let vzv = VarZeroVec::<String>::parse_byte_slice(black_box(bytes.as_slice())).unwrap();
let bytes: Vec<u8> =
VarZeroVec::<str>::get_serializable_bytes::<String>(string_vec.as_slice()).unwrap();
let vzv = VarZeroVec::<str>::parse_byte_slice(black_box(bytes.as_slice())).unwrap();

// *** Count chars in vec of 100 strings ***
c.bench_function("vzv/char_count/slice", |b| {
Expand All @@ -99,8 +101,9 @@ fn binary_search_benches(c: &mut Criterion) {
let seed = 2021;
let (string_vec, seed) = random_alphanums(2..=20, 500, seed);
let (needles, _) = random_alphanums(2..=20, 10, seed);
let bytes: Vec<u8> = VarZeroVec::get_serializable_bytes(string_vec.as_slice()).unwrap();
let vzv = VarZeroVec::<String>::parse_byte_slice(black_box(bytes.as_slice())).unwrap();
let bytes: Vec<u8> =
VarZeroVec::<str>::get_serializable_bytes::<String>(string_vec.as_slice()).unwrap();
let vzv = VarZeroVec::<str>::parse_byte_slice(black_box(bytes.as_slice())).unwrap();
let single_needle = "lmnop".to_string();

// *** Binary search vec of 500 strings 10 times ***
Expand Down Expand Up @@ -139,7 +142,7 @@ fn serde_benches(c: &mut Criterion) {
let seed = 2021;
let (string_vec, _) = random_alphanums(2..=20, 100, seed);
let bincode_vec = bincode::serialize(&string_vec).unwrap();
let vzv = VarZeroVec::from(&*string_vec);
let vzv: VarZeroVec<str> = VarZeroVec::from(&*string_vec);
let bincode_vzv = bincode::serialize(&vzv).unwrap();

// *** Deserialize vec of 100 strings ***
Expand All @@ -154,7 +157,7 @@ fn serde_benches(c: &mut Criterion) {

// *** Deserialize vec of 100 strings ***
c.bench_function("vzv/deserialize/string/vzv", |b| {
b.iter(|| bincode::deserialize::<VarZeroVec<String>>(black_box(&bincode_vzv)));
b.iter(|| bincode::deserialize::<VarZeroVec<str>>(black_box(&bincode_vzv)));
});
}

Expand Down
4 changes: 2 additions & 2 deletions utils/zerovec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@
//! #[serde(borrow)]
//! nums: ZeroVec<'data, u32>,
//! #[serde(borrow)]
//! strs: VarZeroVec<'data, String>,
//! strs: VarZeroVec<'data, str>,
//! }
//!
//! let data = DataStruct {
//! nums: ZeroVec::from_slice(&[211, 281, 421, 461]),
//! strs: VarZeroVec::from(&["hello".to_string(), "world".to_string()] as &[_]),
//! strs: VarZeroVec::from(&["hello", "world"] as &[_]),
//! };
//! let bincode_bytes = bincode::serialize(&data)
//! .expect("Serialization should be successful");
Expand Down
71 changes: 58 additions & 13 deletions utils/zerovec/src/map/kv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,41 @@ use super::vecs::ZeroVecLike;
use crate::ule::*;
use crate::VarZeroVec;
use crate::ZeroVec;
use alloc::string::String;
use alloc::vec::Vec;
use alloc::boxed::Box;
use core::cmp::Ordering;

/// Trait marking types which are allowed to be keys or values in [`ZeroMap`](super::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
/// implementing your own [`AsULE`] or [`VarULE`] type you may wish to implement
/// this trait.
// this lifetime should be a GAT on Container once that is possible
#[allow(clippy::upper_case_acronyms)] // KV is not an acronym
pub trait ZeroMapKV<'a>: Sized {
pub trait ZeroMapKV<'a> {
/// The container that can be used with this type: [`ZeroVec`] or [`VarZeroVec`].
type Container: ZeroVecLike<'a, Self, NeedleType = Self::NeedleType, GetType = Self::GetType>
+ Sized;
type Container: ZeroVecLike<
'a,
Self,
NeedleType = Self::NeedleType,
GetType = Self::GetType,
OwnedType = Self::OwnedType,
> + 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()`
/// The type produced 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;
/// The type produced by `Container::replace()` and `Container::remove()`,
/// also used during deserialization. If `Self` is human readable serialized,
/// deserializing to `Self::OwnedType` should produce the same value once
/// passed through `Self::owned_as_self()`
type OwnedType;
/// 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
Expand All @@ -42,6 +51,9 @@ pub trait ZeroMapKV<'a>: Sized {
/// This uses a callback because it's not possible to return owned-or-borrowed
/// types without GATs
fn with_ser<R>(g: &Self::GetType, f: impl FnOnce(&Self::SerializeType) -> R) -> R;

/// Convert an owned value to a borrowed Self
fn owned_as_self(o: &Self::OwnedType) -> &Self;
}

macro_rules! impl_sized_kv {
Expand All @@ -51,16 +63,27 @@ macro_rules! impl_sized_kv {
type NeedleType = $ty;
type GetType = <$ty as AsULE>::ULE;
type SerializeType = $ty;
type OwnedType = $ty;

#[inline]
fn as_needle(&self) -> &Self {
self
}

#[inline]
fn cmp_get(&self, g: &Self::GetType) -> Ordering {
self.cmp(&$ty::from_unaligned(g))
}

#[inline]
fn with_ser<R>(g: &Self::GetType, f: impl FnOnce(&Self) -> R) -> R {
f(&Self::from_unaligned(g))
}

#[inline]
fn owned_as_self(o: &Self::OwnedType) -> &Self {
o
}
}
};
}
Expand All @@ -75,36 +98,58 @@ impl_sized_kv!(i64);
impl_sized_kv!(i128);
impl_sized_kv!(char);

impl<'a> ZeroMapKV<'a> for String {
type Container = VarZeroVec<'a, String>;
impl<'a> ZeroMapKV<'a> for str {
type Container = VarZeroVec<'a, str>;
type NeedleType = str;
type GetType = str;
type SerializeType = str;
type OwnedType = Box<str>;

#[inline]
fn as_needle(&self) -> &str {
self
}

#[inline]
fn cmp_get(&self, g: &str) -> Ordering {
(&**self).cmp(g)
(&*self).cmp(g)
}

#[inline]
fn with_ser<R>(g: &str, f: impl FnOnce(&str) -> R) -> R {
f(g)
}

#[inline]
fn owned_as_self(o: &Self::OwnedType) -> &Self {
o
}
}

impl<'a> ZeroMapKV<'a> for Vec<u8> {
type Container = VarZeroVec<'a, Vec<u8>>;
impl<'a> ZeroMapKV<'a> for [u8] {
type Container = VarZeroVec<'a, [u8]>;
type NeedleType = [u8];
type GetType = [u8];
type SerializeType = [u8];
type OwnedType = Box<[u8]>;

#[inline]
fn as_needle(&self) -> &[u8] {
self
}

#[inline]
fn cmp_get(&self, g: &[u8]) -> Ordering {
(&**self).cmp(g)
(&*self).cmp(g)
}

#[inline]
fn with_ser<R>(g: &[u8], f: impl FnOnce(&[u8]) -> R) -> R {
f(g)
}

#[inline]
fn owned_as_self(o: &Self::OwnedType) -> &Self {
o
}
}
40 changes: 23 additions & 17 deletions utils/zerovec/src/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub use vecs::ZeroVecLike;
/// ];
///
/// // Deserializing to ZeroMap requires no heap allocations.
/// let zero_map: ZeroMap<u32, String> = bincode::deserialize(BINCODE_BYTES)
/// let zero_map: ZeroMap<u32, str> = bincode::deserialize(BINCODE_BYTES)
/// .expect("Should deserialize successfully");
/// assert_eq!(zero_map.get(&1), Some("one"));
/// ```
Expand All @@ -49,6 +49,8 @@ pub struct ZeroMap<'a, K, V>
where
K: ZeroMapKV<'a>,
V: ZeroMapKV<'a>,
K: ?Sized,
V: ?Sized,
{
pub(crate) keys: K::Container,
pub(crate) values: V::Container,
Expand All @@ -58,6 +60,8 @@ impl<'a, K, V> Default for ZeroMap<'a, K, V>
where
K: ZeroMapKV<'a>,
V: ZeroMapKV<'a>,
K: ?Sized,
V: ?Sized,
{
fn default() -> Self {
Self {
Expand All @@ -71,6 +75,8 @@ impl<'a, K, V> ZeroMap<'a, K, V>
where
K: ZeroMapKV<'a>,
V: ZeroMapKV<'a>,
K: ?Sized,
V: ?Sized,
{
/// Construct a new [`ZeroMap`]
pub fn new() -> Self {
Expand Down Expand Up @@ -116,8 +122,8 @@ where
/// use zerovec::ZeroMap;
///
/// let mut map = ZeroMap::new();
/// map.insert(1, "one".to_owned());
/// map.insert(2, "two".to_owned());
/// map.insert(&1, "one");
/// map.insert(&2, "two");
/// assert_eq!(map.get(&1), Some("one"));
/// assert_eq!(map.get(&3), None);
/// ```
Expand All @@ -132,8 +138,8 @@ where
/// use zerovec::ZeroMap;
///
/// let mut map = ZeroMap::new();
/// map.insert(1, "one".to_owned());
/// map.insert(2, "two".to_owned());
/// map.insert(&1, "one");
/// map.insert(&2, "two");
/// assert_eq!(map.contains_key(&1), true);
/// assert_eq!(map.contains_key(&3), false);
/// ```
Expand All @@ -147,12 +153,12 @@ where
/// use zerovec::ZeroMap;
///
/// let mut map = ZeroMap::new();
/// map.insert(1, "one".to_owned());
/// map.insert(2, "two".to_owned());
/// map.insert(&1, "one");
/// map.insert(&2, "two");
/// assert_eq!(map.get(&1), Some("one"));
/// assert_eq!(map.get(&3), None);
/// ```
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
pub fn insert(&mut self, key: &K, value: &V) -> Option<V::OwnedType> {
let key_needle = key.as_needle();
match self.keys.binary_search(key_needle) {
Ok(index) => Some(self.values.replace(index, value)),
Expand All @@ -170,12 +176,12 @@ where
/// use zerovec::ZeroMap;
///
/// let mut map = ZeroMap::new();
/// map.insert(1, "one".to_owned());
/// map.insert(2, "two".to_owned());
/// assert_eq!(map.remove(&1), Some("one".to_owned()));
/// map.insert(&1, "one");
/// map.insert(&2, "two");
/// assert_eq!(map.remove(&1), Some("one".to_owned().into_boxed_str()));
/// assert_eq!(map.get(&1), None);
/// ```
pub fn remove(&mut self, key: &K::NeedleType) -> Option<V> {
pub fn remove(&mut self, key: &K::NeedleType) -> Option<V::OwnedType> {
let idx = self.keys.binary_search(key).ok()?;
self.keys.remove(idx);
Some(self.values.remove(idx))
Expand All @@ -188,13 +194,13 @@ where
/// use zerovec::ZeroMap;
///
/// let mut map = ZeroMap::new();
/// assert!(map.try_append(1, "uno".to_owned()).is_none());
/// assert!(map.try_append(3, "tres".to_owned()).is_none());
/// assert!(map.try_append(&1, "uno").is_none());
/// assert!(map.try_append(&3, "tres").is_none());
///
/// let unsuccessful = map.try_append(3, "tres-updated".to_owned());
/// let unsuccessful = map.try_append(&3, "tres-updated");
/// assert!(unsuccessful.is_some(), "append duplicate of last key");
///
/// let unsuccessful = map.try_append(2, "dos".to_owned());
/// let unsuccessful = map.try_append(&2, "dos");
/// assert!(unsuccessful.is_some(), "append out of order");
///
/// assert_eq!(map.get(&1), Some("uno"));
Expand All @@ -206,7 +212,7 @@ where
/// assert_eq!(map.get(&2), None);
/// ```
#[must_use]
pub fn try_append(&mut self, key: K, value: V) -> Option<(K, V)> {
pub fn try_append<'b>(&mut self, key: &'b K, value: &'b V) -> Option<(&'b K, &'b V)> {
if self.keys.len() != 0 {
if let Some(last) = self.keys.get(self.keys.len() - 1) {
if key.cmp_get(last) != Ordering::Greater {
Expand Down
Loading

0 comments on commit 77185f4

Please sign in to comment.