diff --git a/variadics/Cargo.toml b/variadics/Cargo.toml index 182161686148..0871e76a2134 100644 --- a/variadics/Cargo.toml +++ b/variadics/Cargo.toml @@ -12,7 +12,6 @@ workspace = true [dependencies] sealed = "0.5.0" -hashbrown = "0.14.0" [dev-dependencies] trybuild = "1.0" diff --git a/variadics/src/lib.rs b/variadics/src/lib.rs index d812483f7991..548cbf1d153e 100644 --- a/variadics/src/lib.rs +++ b/variadics/src/lib.rs @@ -11,8 +11,6 @@ //! ## [`var_args!`] #![doc = include_str!("../var_args.md")] -/// module of collection types for variadics -pub mod variadic_collections; use std::any::Any; use sealed::sealed; @@ -127,18 +125,6 @@ pub trait VariadicExt: Variadic { type Reverse: VariadicExt; /// Reverses this variadic value. fn reverse(self) -> Self::Reverse; - /// Reverses an AsRefVar variadic value - fn reverse_ref(this: Self::AsRefVar<'_>) -> ::AsRefVar<'_>; - - /// The length of this variadic type - fn len(&self) -> usize { - Self::LEN - } - - /// Checks if this variadic type is empty. - fn is_empty(&self) -> bool { - Self::LEN == 0 - } /// This as a variadic of references. type AsRefVar<'a>: RefVariadic< @@ -190,18 +176,7 @@ pub trait VariadicExt: Variadic { fn iter_any_mut(&mut self) -> Self::IterAnyMut<'_> where Self: 'static; - - /// type for all elements of the variadic being wrapped in Option - type IntoOption; - /// wrap all elements of the variadic in Option - fn into_option(self) -> Self::IntoOption; - - /// type for all elements of the variadic being wrapped in Vec - type IntoVec: VecVariadic + Default; - /// wrap all elements of the variadic in a Vec - fn into_singleton_vec(self) -> Self::IntoVec; } - #[sealed] impl VariadicExt for (Item, Rest) where @@ -223,14 +198,6 @@ where let (item, rest) = self; rest.reverse().extend((item, ())) } - fn reverse_ref(this: Self::AsRefVar<'_>) -> ::AsRefVar<'_> { - let (item, rest) = this; - let out = Rest::reverse_ref(rest).extend((item, ())); - // TODO!!! - let out2 = unsafe { std::mem::transmute_copy(&out) }; - std::mem::forget(out); - out2 - } type AsRefVar<'a> = (&'a Item, Rest::AsRefVar<'a>) where @@ -271,20 +238,7 @@ where let item: &mut dyn Any = item; std::iter::once(item).chain(rest.iter_any_mut()) } - - type IntoOption = (Option, Rest::IntoOption); - fn into_option(self) -> Self::IntoOption { - let var_args!(item, ...rest) = self; - var_expr!(Some(item), ...rest.into_option()) - } - - type IntoVec = (Vec, Rest::IntoVec); - fn into_singleton_vec(self) -> Self::IntoVec { - let var_args!(item, ...rest) = self; - var_expr!(vec!(item), ...rest.into_singleton_vec()) - } } - #[sealed] impl VariadicExt for () { const LEN: usize = 0; @@ -299,7 +253,6 @@ impl VariadicExt for () { type Reverse = (); fn reverse(self) -> Self::Reverse {} - fn reverse_ref(_this: Self::AsRefVar<'_>) -> ::AsRefVar<'_> {} type AsRefVar<'a> = (); fn as_ref_var(&self) -> Self::AsRefVar<'_> {} @@ -326,12 +279,6 @@ impl VariadicExt for () { { std::iter::empty() } - - type IntoOption = (); - fn into_option(self) -> Self::IntoOption {} - - type IntoVec = (); - fn into_singleton_vec(self) -> Self::IntoVec {} } /// A variadic of either shared references, exclusive references, or both. @@ -340,7 +287,7 @@ impl VariadicExt for () { /// /// This is a sealed trait. #[sealed] -pub trait EitherRefVariadic: VariadicExt { +pub trait EitherRefVariadic: Variadic { /// The un-referenced variadic. Each item will have one layer of shared references removed. /// /// The inverse of [`VariadicExt::AsRefVar`] and [`VariadicExt::AsMutVar`]. @@ -350,7 +297,7 @@ pub trait EitherRefVariadic: VariadicExt { /// let un_ref: ::UnRefVar = /// var_expr!(1_u32, "Hello".to_owned(), false); /// ``` - type UnRefVar: for<'a> VariadicExt; + type UnRefVar: VariadicExt; /// This type with all exclusive `&mut` references replaced with shared `&` references. /// @@ -372,9 +319,6 @@ pub trait EitherRefVariadic: VariadicExt { /// /// Conversion from `&` to `&mut` is generally invalid, so a `ref_to_mut()` method does not exist. type MutVar: MutVariadic; - - /// convert entries to ::AsRefVar - fn unref_ref(&self) -> ::AsRefVar<'_>; } #[sealed] impl<'a, Item, Rest> EitherRefVariadic for (&'a Item, Rest) @@ -390,11 +334,6 @@ where } type MutVar = (&'a mut Item, Rest::MutVar); - - fn unref_ref(&self) -> ::AsRefVar<'_> { - let var_args!(item, ...rest) = self; - var_expr!(item, ...rest.unref_ref()) - } } #[sealed] impl<'a, Item, Rest> EitherRefVariadic for (&'a mut Item, Rest) @@ -410,11 +349,6 @@ where } type MutVar = (&'a mut Item, Rest::MutVar); - - fn unref_ref(&self) -> ::AsRefVar<'_> { - let var_args!(item, ...rest) = self; - var_expr!(item, ...rest.unref_ref()) - } } #[sealed] impl EitherRefVariadic for () { @@ -424,8 +358,6 @@ impl EitherRefVariadic for () { fn mut_to_ref(self) -> Self::RefVar {} type MutVar = (); - - fn unref_ref(&self) -> ::AsRefVar<'_> {} } /// A variadic where each item is a shared reference `&item`. @@ -506,39 +438,50 @@ impl CopyRefVariadic for () { fn copy_var(&self) -> Self::UnRefVar {} } -/// Clone a variadic of references [`AsRefVar`] into a variadic of owned values. +/// Clone a variadic of references [`EitherRefVariadic`] into a variadic of owned values [`EitherRefVariadic::UnRefVar`]. /// /// ```rust /// # use variadics::*; /// let ref_var = var_expr!(&1, &format!("hello {}", "world"), &vec![1, 2, 3]); -/// let clone_var = CloneVariadic::clone_ref_var(ref_var); +/// let clone_var = ref_var.clone_var(); /// assert_eq!( /// var_expr!(1, "hello world".to_owned(), vec![1, 2, 3]), /// clone_var /// ); /// ``` #[sealed] -pub trait CloneVariadic: VariadicExt + Clone { - /// Clone a variadic of references [`AsRefVar`] into a variadic of owned values. - fn clone_ref_var(this: Self::AsRefVar<'_>) -> Self; +pub trait CloneRefVariadic: EitherRefVariadic { + /// Clone self per-value. + fn clone_var(&self) -> Self::UnRefVar; } #[sealed] -impl CloneVariadic for (Item, Rest) +impl CloneRefVariadic for (&Item, Rest) where Item: Clone, - Rest: CloneVariadic, + Rest: CloneRefVariadic, { - fn clone_ref_var(this: Self::AsRefVar<'_>) -> Self { - let var_args!(item, ...rest) = this; - var_expr!(item.clone(), ...Rest::clone_ref_var(rest)) + fn clone_var(&self) -> Self::UnRefVar { + let var_args!(item, ...rest) = self; + var_expr!((*item).clone(), ...rest.clone_var()) } } #[sealed] -impl CloneVariadic for () { - fn clone_ref_var(_this: Self::AsRefVar<'_>) -> Self {} +impl CloneRefVariadic for (&mut Item, Rest) +where + Item: Clone, + Rest: CloneRefVariadic, +{ + fn clone_var(&self) -> Self::UnRefVar { + let var_args!(item, ...rest) = self; + var_expr!((*item).clone(), ...rest.clone_var()) + } +} +#[sealed] +impl CloneRefVariadic for () { + fn clone_var(&self) -> Self::UnRefVar {} } -/// A variadic where all item implement [`PartialEq`]. +/// A variadic where all item implement `PartialEq`. #[sealed] pub trait PartialEqVariadic: VariadicExt { /// `PartialEq` between a referenced variadic and a variadic of references, of the same types. @@ -645,218 +588,36 @@ where /// /// This is a sealed trait. #[sealed] -pub trait Split: VariadicExt +pub trait Split: Variadic where - Prefix: VariadicExt, + Prefix: Variadic, { /// The second part when splitting this variadic by `Prefix`. - type Suffix: VariadicExt; + type Suffix: Variadic; /// Splits this variadic into two parts, first the `Prefix`, and second the `Suffix`. fn split(self) -> (Prefix, Self::Suffix); - /// Splits a refvar variadic - fn split_ref( - this: Self::AsRefVar<'_>, - ) -> ( - Prefix::AsRefVar<'_>, - ::AsRefVar<'_>, - ); } #[sealed] impl Split<(Item, PrefixRest)> for (Item, Rest) where - PrefixRest: VariadicExt, + PrefixRest: Variadic, Rest: Split, { - /// The second part when splitting this variadic by `Prefix`. type Suffix = >::Suffix; - /// Splits this variadic into two parts, first the `Prefix`, and second the `Suffix`. fn split(self) -> ((Item, PrefixRest), Self::Suffix) { let (item, rest) = self; let (prefix_rest, suffix) = rest.split(); ((item, prefix_rest), suffix) } - /// Splits a refvar variadic - fn split_ref( - this: Self::AsRefVar<'_>, - ) -> ( - <(Item, PrefixRest) as VariadicExt>::AsRefVar<'_>, - ::AsRefVar<'_>, - ) { - let (item, rest) = this; - let (prefix_rest, suffix) = Rest::split_ref(rest); - ((item, prefix_rest), suffix) - } } #[sealed] -impl Split for Rest +impl Split<()> for Rest where - Rest: VariadicExt, + Rest: Variadic, { type Suffix = Rest; - fn split(self) -> (var_type!(), Self::Suffix) { - (var_expr!(), self) - } - fn split_ref( - this: Self::AsRefVar<'_>, - ) -> (var_type!(), ::AsRefVar<'_>) { - (var_expr!(), this) - } -} - -#[sealed] -/// Helper trait for splitting a variadic into two parts. `Prefix` is the first part, everything -/// after is the `Suffix` or second part. -/// -/// This is a sealed trait. -pub trait SplitBySuffix: VariadicExt -where - Suffix: VariadicExt, -{ - /// The first part when splitting this variadic by `Suffix`. - type Prefix: VariadicExt; - /// Splits this variadic into two parts, first the `Prefix`, and second the `Suffix`. - fn split_by_suffix(self) -> (Self::Prefix, Suffix); - /// Splits a refvar variadic - fn split_by_suffix_ref( - this: Self::AsRefVar<'_>, - ) -> ( - ::AsRefVar<'_>, - Suffix::AsRefVar<'_>, - ); -} -#[sealed] -impl SplitBySuffix for This -where - Suffix: VariadicExt, - This: VariadicExt, - This::Reverse: Split, - Suffix::Reverse: VariadicExt, -{ - /// The second part when splitting this variadic by `Prefix`. - type Prefix = <>::Suffix as VariadicExt>::Reverse; - /// Splits this variadic into two parts, first the `Prefix`, and second the `Suffix`. - fn split_by_suffix(self) -> (Self::Prefix, Suffix) { - let (rsuffix, rprefix) = self.reverse().split(); - (rprefix.reverse(), rsuffix.reverse()) - } - - fn split_by_suffix_ref( - this: Self::AsRefVar<'_>, - ) -> ( - ::AsRefVar<'_>, - Suffix::AsRefVar<'_>, - ) { - let rev = This::reverse_ref(this); - let (rsuffix, rprefix) = >::split_ref(rev); - let out = (rprefix.reverse(), rsuffix.reverse()); - // TODO!!!! - let out2 = unsafe { std::mem::transmute_copy(&out) }; - std::mem::forget(out); - out2 - } -} - -/// trait for Variadic of vecs, as formed by `VariadicExt::into_vec()` -#[sealed] -pub trait VecVariadic: VariadicExt { - /// Individual variadic items without the Vec wrapper - type UnVec: VariadicExt; - - /// zip across all the vecs in this VariadicVec - fn zip_vecs(&self) -> impl Iterator::AsRefVar<'_>>; - - /// append an unvec'ed Variadic into this VariadicVec - fn push(&mut self, item: Self::UnVec); - - /// get the unvec'ed Variadic at position `index` - fn get(&mut self, index: usize) -> Option<::AsRefVar<'_>>; - - /// result type from into_zip - type IntoZip: Iterator; - /// Turns into an iterator of items `UnVec` -- i.e. iterate through rows (not columns!). - fn into_zip(self) -> Self::IntoZip; - - /// result type from drain - type Drain<'a>: Iterator - where - Self: 'a; - /// Turns into a Drain of items `UnVec` -- i.e. iterate through rows (not columns!). - fn drain(&mut self, range: R) -> Self::Drain<'_> - where - R: std::ops::RangeBounds + Clone; -} - -#[sealed] -impl VecVariadic for (Vec, Rest) -where - Rest: VecVariadic, - // Item: 'static, - // Rest: 'static, -{ - type UnVec = var_type!(Item, ...Rest::UnVec); - - fn zip_vecs(&self) -> impl Iterator::AsRefVar<'_>> { - let (this, rest) = self; - std::iter::zip(this.iter(), rest.zip_vecs()) - } - - fn push(&mut self, row: Self::UnVec) { - let (this_vec, rest_vecs) = self; - let (this_col, rest_cols) = row; - this_vec.push(this_col); - rest_vecs.push(rest_cols); - } - - fn get(&mut self, index: usize) -> Option<::AsRefVar<'_>> { - let (this_vec, rest_vecs) = self; - if let Some(rest) = VecVariadic::get(rest_vecs, index) { - this_vec.get(index).map(|item| var_expr!(item, ...rest)) - } else { - None - } - } - - type IntoZip = std::iter::Zip, Rest::IntoZip>; - fn into_zip(self) -> Self::IntoZip { - let (this, rest) = self; - std::iter::zip(this, rest.into_zip()) - } - - type Drain<'a> = std::iter::Zip, Rest::Drain<'a>> where Self: 'a; - fn drain(&mut self, range: R) -> Self::Drain<'_> - where - R: std::ops::RangeBounds + Clone, - { - let (this, rest) = self; - std::iter::zip(this.drain(range.clone()), rest.drain(range)) - } -} - -#[sealed] -impl VecVariadic for var_type!() { - type UnVec = var_type!(); - - fn zip_vecs(&self) -> impl Iterator::AsRefVar<'_>> { - std::iter::repeat(var_expr!()) - } - - fn push(&mut self, _item: Self::UnVec) {} - - fn get(&mut self, _index: usize) -> Option<::AsRefVar<'_>> { - Some(()) - } - - type IntoZip = std::iter::Repeat; - fn into_zip(self) -> Self::IntoZip { - std::iter::repeat(var_expr!()) - } - - type Drain<'a> = std::iter::Repeat where Self: 'a; - fn drain(&mut self, _range: R) -> Self::Drain<'_> - where - R: std::ops::RangeBounds, - { - std::iter::repeat(var_expr!()) + fn split(self) -> ((), Self::Suffix) { + ((), self) } } @@ -867,13 +628,12 @@ mod test { type MyList = var_type!(u8, u16, u32, u64); type MyPrefix = var_type!(u8, u16); + #[expect(dead_code, reason = "compilation test code")] type MySuffix = >::Suffix; - #[allow(dead_code)] const _: MySuffix = var_expr!(0_u32, 0_u64); #[test] - #[allow(clippy::let_unit_value)] fn test_basic_expr() { let _ = var_expr!(); let _ = var_expr!(1); @@ -884,7 +644,7 @@ mod test { variadic_trait! { /// Variaidic list of futures. - #[allow(dead_code)] + #[allow(clippy::allow_attributes, dead_code, reason = "compilation test code")] pub variadic FuturesList where F: std::future::Future {} } @@ -954,52 +714,28 @@ mod test { } #[test] - fn test_into_vec() { - use crate::VecVariadic; - - type Item = var_type!(i32, String); - let first: Item = var_expr!(1, "Joe".to_string()); - let second: Item = var_expr!(2, "Mingwei".to_string()); - let mut column_store = first.clone().into_singleton_vec(); - column_store.push(second.clone()); - assert_eq!(column_store.len(), 2); - assert_eq!(column_store.get(0).unwrap(), first.as_ref_var()); - assert_eq!(column_store.get(1).unwrap(), second.as_ref_var()); - } -} - -#[test] -fn test_eq_ref_vec() { - type MyVar = var_type!(i32, bool, &'static str); - let vec: Vec = vec![ - var_expr!(0, true, "hello"), - var_expr!(1, true, "world"), - var_expr!(2, false, "goodnight"), - var_expr!(3, false, "moon"), - ]; - let needle: ::AsRefVar<'_> = - var_expr!(2, false, "goodnight").as_ref_var(); - assert_eq!( - Some(2), - vec.iter() - .position(|item| ::eq_ref(needle, item.as_ref_var())) - ); - - let missing: ::AsRefVar<'_> = - var_expr!(3, false, "goodnight").as_ref_var(); - assert_eq!( - None, - vec.iter() - .position(|item| ::eq_ref(missing, item.as_ref_var())) - ); -} + fn test_eq_ref_vec() { + type MyVar = var_type!(i32, bool, &'static str); + let vec: Vec = vec![ + var_expr!(0, true, "hello"), + var_expr!(1, true, "world"), + var_expr!(2, false, "goodnight"), + var_expr!(3, false, "moon"), + ]; + let needle: ::AsRefVar<'_> = + var_expr!(2, false, "goodnight").as_ref_var(); + assert_eq!( + Some(2), + vec.iter() + .position(|item| ::eq_ref(needle, item.as_ref_var())) + ); -#[test] -fn clone_var_test() { - let ref_var = var_expr!(&1, &format!("hello {}", "world"), &vec![1, 2, 3]); - let clone_var = CloneVariadic::clone_ref_var(ref_var); - assert_eq!( - var_expr!(1, "hello world".to_owned(), vec![1, 2, 3]), - clone_var - ); + let missing: ::AsRefVar<'_> = + var_expr!(3, false, "goodnight").as_ref_var(); + assert_eq!( + None, + vec.iter() + .position(|item| ::eq_ref(missing, item.as_ref_var())) + ); + } } diff --git a/variadics/src/variadic_collections.rs b/variadics/src/variadic_collections.rs deleted file mode 100644 index f4240423464b..000000000000 --- a/variadics/src/variadic_collections.rs +++ /dev/null @@ -1,648 +0,0 @@ -use std::fmt; -use std::hash::{BuildHasher, Hash, RandomState}; - -use hashbrown::hash_table::{Entry, HashTable}; - -use crate::{PartialEqVariadic, VariadicExt, VecVariadic}; - -/// Trait for a set of Variadic Tuples -pub trait VariadicCollection { - /// The Schema (aka Variadic type) associated with tuples in this set - type Schema: PartialEqVariadic; - - /// Insert an element into the set, return true if successful - fn insert(&mut self, element: Self::Schema) -> bool; - - /// Iterate over the elements of the set - fn iter(&self) -> impl Iterator::AsRefVar<'_>>; - - /// Return number of elements in the set - fn len(&self) -> usize; - - /// Return true if empty - fn is_empty(&self) -> bool; - - /// iterate and drain items from the set without deallocating the container - fn drain(&mut self) -> impl Iterator; - - /// Check for containment - fn contains(&self, value: ::AsRefVar<'_>) -> bool; -} - -/// trait for sets or multisets of variadics -pub trait VariadicSet: VariadicCollection {} - -/// HashSet that stores Variadics of owned values but allows -/// for lookups with RefVariadics as well -#[derive(Clone)] -pub struct VariadicHashSet { - table: HashTable, - hasher: S, -} - -impl VariadicHashSet { - /// Creates a new `VariadicHashSet` with a default hasher. - pub fn new() -> Self { - Self { - table: HashTable::new(), - hasher: RandomState::default(), - } - } -} - -impl Default for VariadicHashSet { - fn default() -> Self { - Self::new() - } -} - -impl fmt::Debug for VariadicHashSet -where - T: fmt::Debug + VariadicExt + PartialEqVariadic, - for<'a> T::AsRefVar<'a>: Hash + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_set().entries(self.iter()).finish() - } -} - -impl VariadicHashSet -where - T: PartialEqVariadic, - for<'a> T::AsRefVar<'a>: Hash, - S: BuildHasher, -{ - /// given a RefVariadic lookup key, get a RefVariadic version of a tuple in the set - pub fn get<'a>(&'a self, ref_var: T::AsRefVar<'_>) -> Option<&'a T> { - let hash = self.hasher.hash_one(ref_var); - self.table.find(hash, |item| { - ::eq_ref(ref_var, item.as_ref_var()) - }) - } -} -impl VariadicCollection for VariadicHashSet -where - T: VariadicExt + PartialEqVariadic, - for<'a> T::AsRefVar<'a>: Hash, - S: BuildHasher, -{ - type Schema = T; - - fn insert(&mut self, element: T) -> bool { - // let hash = Self::get_hash(&self.hasher, element.as_ref_var()); - let hash = self.hasher.hash_one(element.as_ref_var()); - let entry = self.table.entry( - hash, - |item| ::eq(&element, item), - |item| self.hasher.hash_one(item.as_ref_var()), - ); - match entry { - Entry::Occupied(_occupied_entry) => false, - Entry::Vacant(vacant_entry) => { - vacant_entry.insert(element); - true - } - } - } - - fn len(&self) -> usize { - self.table.len() - } - - fn is_empty(&self) -> bool { - self.table.len() == 0 - } - - fn drain(&mut self) -> impl Iterator { - self.table.drain() - } - - fn contains(&self, value: ::AsRefVar<'_>) -> bool { - self.get(value).is_some() - } - - fn iter(&self) -> impl Iterator> { - self.table.iter().map(|item| item.as_ref_var()) - } -} -impl VariadicSet for VariadicHashSet -where - T: VariadicExt + PartialEqVariadic, - for<'a> T::AsRefVar<'a>: Hash, - S: BuildHasher, -{ -} - -impl IntoIterator for VariadicHashSet -where - T: VariadicExt + PartialEqVariadic, -{ - type Item = T; - type IntoIter = hashbrown::hash_table::IntoIter; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.table.into_iter() - } -} - -impl VariadicHashSet { - /// allocate a new VariadicHashSet with a specific hasher - pub fn with_hasher(hasher: S) -> Self { - Self { - table: HashTable::new(), - hasher, - } - } - /// allocate a new VariadicHashSet with a specific hasher and capacity - pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self { - Self { - table: HashTable::with_capacity(capacity), - hasher, - } - } -} - -// THIS CODE ADAPTED FROM hashbrown::HashMap -impl Extend for VariadicHashSet -where - K: Eq + Hash + PartialEqVariadic, - S: BuildHasher, - for<'a> K::AsRefVar<'a>: Hash, -{ - fn extend>(&mut self, iter: T) { - // Keys may be already present or show multiple times in the iterator. - // Reserve the entire hint lower bound if the map is empty. - // Otherwise reserve half the hint (rounded up), so the map - // will only resize twice in the worst case. - let iter = iter.into_iter(); - // let reserve = - if self.is_empty() { - iter.size_hint().0 - } else { - (iter.size_hint().0 + 1) / 2 - }; - // TODO figure out reserve! - // let hasher = self.hasher.build_hasher(); - // self.table.reserve(reserve, hasher); - iter.for_each(move |k| { - self.insert(k); - }); - } -} - -impl PartialEq for VariadicHashSet -where - T: Eq + Hash + PartialEqVariadic, - S: BuildHasher, - for<'a> T::AsRefVar<'a>: Hash, -{ - fn eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - self.iter().all(|key| other.get(key).is_some()) - } -} - -impl FromIterator for VariadicHashSet -where - T: Eq + Hash + PartialEqVariadic, - S: BuildHasher + Default, - for<'a> T::AsRefVar<'a>: Hash, - // A: Default + Allocator, -{ - fn from_iter>(iter: I) -> Self { - let mut set = Self::with_hasher(Default::default()); - set.extend(iter); - set - } -} - -/// Trait for a multiset of Tuples -pub trait VariadicMultiset: VariadicCollection {} - -/// HashMap keyed on Variadics of (owned value, count) pairs, allows -/// for lookups with RefVariadics. -#[derive(Clone)] -pub struct VariadicCountedHashSet -where - K: VariadicExt, -{ - table: HashTable<(K, usize)>, - hasher: S, - len: usize, -} - -impl VariadicCountedHashSet -where - K: VariadicExt, -{ - /// Creates a new `VariadicCountedHashSet` with a default hasher. - pub fn new() -> Self { - Self { - table: HashTable::new(), - hasher: RandomState::default(), - len: 0, - } - } -} - -impl Default for VariadicCountedHashSet -where - K: VariadicExt, -{ - fn default() -> Self { - Self::new() - } -} - -impl fmt::Debug for VariadicCountedHashSet -where - K: fmt::Debug + VariadicExt + PartialEqVariadic, - for<'a> K::AsRefVar<'a>: Hash + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_set().entries(self.table.iter()).finish() - } -} - -impl VariadicCountedHashSet -where - K: PartialEqVariadic, - for<'a> K::AsRefVar<'a>: Hash, - S: BuildHasher, -{ - /// given a RefVariadic lookup key, get a RefVariadic version of an entry in the map - pub fn get<'a>(&'a self, ref_var: K::AsRefVar<'_>) -> Option<&'a (K, usize)> { - let hash = self.hasher.hash_one(ref_var); - self.table.find(hash, |(key, _val)| { - ::eq_ref(ref_var, key.as_ref_var()) - }) - } -} - -impl VariadicCollection for VariadicCountedHashSet -where - K: VariadicExt + PartialEqVariadic + Hash + Clone, - for<'a> K::AsRefVar<'a>: Hash, - S: BuildHasher, -{ - type Schema = K; - - fn insert(&mut self, element: K) -> bool { - let hash = self.hasher.hash_one(element.as_ref_var()); - self.table - .entry( - hash, - |(item, _count)| ::eq(&element, item), - |(item, _count)| self.hasher.hash_one(item.as_ref_var()), - ) - .and_modify(|(_, count)| *count += 1) - .or_insert((element, 1)); - self.len += 1; - true - } - - fn len(&self) -> usize { - self.len - } - - fn is_empty(&self) -> bool { - self.len() == 0 - } - - fn drain(&mut self) -> impl Iterator { - // TODO: this shouldn't clone the last copy of each k! - // particularly bad when there's typically only 1 copy per item - self.len = 0; - self.table - .drain() - .flat_map(|(k, num)| (0..num).map(move |_i| k.clone())) - } - - fn contains(&self, value: ::AsRefVar<'_>) -> bool { - self.get(value).is_some() - } - - fn iter(&self) -> impl Iterator> { - self.table - .iter() - .flat_map(|(k, num)| (0..*num).map(move |_i| k.as_ref_var())) - } -} - -impl VariadicMultiset for VariadicCountedHashSet -where - K: VariadicExt + PartialEqVariadic + Hash + Clone, - for<'a> K::AsRefVar<'a>: Hash, - S: BuildHasher, -{ -} - -impl IntoIterator for VariadicCountedHashSet -where - T: VariadicExt + PartialEqVariadic + Clone, -{ - type Item = T; - type IntoIter = DuplicateCounted, T>; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - DuplicateCounted { - iter: self.table.into_iter(), - state: None, - } - } -} - -/// Iterator helper for [`VariadicCountedHashSet::into_iter`]. -pub struct DuplicateCounted { - iter: Iter, - state: Option<(Item, usize)>, -} -impl Iterator for DuplicateCounted -where - Iter: Iterator, - Item: Clone, -{ - type Item = Item; - - fn next(&mut self) -> Option { - loop { - match self.state.take() { - Some((item, 1)) => { - self.state = None; - return Some(item); - } - None | Some((_, 0)) => match self.iter.next() { - Some(state) => self.state = Some(state), - None => return None, - }, - Some((item, many)) => { - let out = Some(item.clone()); - self.state = Some((item, many - 1)); - return out; - } - } - } - } -} - -impl VariadicCountedHashSet -where - K: VariadicExt, -{ - /// allocate a new VariadicCountedHashSet with a specific hasher - pub fn with_hasher(hasher: S) -> Self { - Self { - table: HashTable::new(), - hasher, - len: 0, - } - } - /// allocate a new VariadicCountedHashSet with a specific hasher and capacity - pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self { - Self { - table: HashTable::with_capacity(capacity), - hasher, - len: 0, - } - } -} - -// THIS CODE ADAPTED FROM hashbrown::HashTable -impl Extend for VariadicCountedHashSet -where - K: Eq + Hash + PartialEqVariadic + Clone, - S: BuildHasher, - for<'a> K::AsRefVar<'a>: Hash, -{ - fn extend>(&mut self, iter: T) { - // Keys may be already present or show multiple times in the iterator. - // Reserve the entire hint lower bound if the map is empty. - // Otherwise reserve half the hint (rounded up), so the map - // will only resize twice in the worst case. - let iter = iter.into_iter(); - // let reserve = - if self.is_empty() { - iter.size_hint().0 - } else { - (iter.size_hint().0 + 1) / 2 - }; - // TODO: get reserve to work here - // let hasher = self.hasher.build_hasher(); - // self.table.reserve(reserve, hasher); - iter.for_each(move |key| { - // TODO: super inefficient. Need a insert_with_count method - self.insert(key); - }); - } -} - -impl PartialEq for VariadicCountedHashSet -where - T: Eq + Hash + PartialEqVariadic + Clone, - S: BuildHasher, - for<'a> T::AsRefVar<'a>: Hash, -{ - fn eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - - // let v: Vec<&(T, usize)> = - self.table.iter().all(|(key, count)| { - if let Some((_, match_val)) = other.get(key.as_ref_var()) { - match_val == count - } else { - false - } - }) - } -} - -impl FromIterator for VariadicCountedHashSet -where - T: Eq + Hash + PartialEqVariadic + Clone, - S: BuildHasher + Default, - for<'a> T::AsRefVar<'a>: Hash, -{ - fn from_iter>(iter: I) -> Self { - let mut set = Self::with_hasher(Default::default()); - set.extend(iter); - set - } -} - -/// Column storage for Variadic tuples of type Schema -/// An alternative to VariadicHashMultiset -pub struct VariadicColumnMultiset -where - Schema: VariadicExt, -{ - columns: Schema::IntoVec, - last_offset: usize, -} - -impl VariadicColumnMultiset -where - T: VariadicExt, -{ - /// initialize an empty columnar multiset - pub fn new() -> Self { - Self { - columns: ::default(), - last_offset: 0, - } - } -} - -impl Default for VariadicColumnMultiset -where - T: VariadicExt, -{ - fn default() -> Self { - Self::new() - } -} - -impl VariadicCollection for VariadicColumnMultiset -where - Schema: PartialEqVariadic, -{ - type Schema = Schema; - - fn insert(&mut self, element: Schema) -> bool { - if self.last_offset == 0 { - self.columns = element.into_singleton_vec() - } else { - self.columns.push(element); - } - self.last_offset += 1; - true - } - - fn iter(&self) -> impl Iterator::AsRefVar<'_>> { - self.columns.zip_vecs() - } - - fn len(&self) -> usize { - self.last_offset - } - - fn is_empty(&self) -> bool { - self.len() == 0 - } - - fn drain(&mut self) -> impl Iterator { - self.last_offset = 0; - self.columns.drain(0..) - } - - fn contains(&self, value: ::AsRefVar<'_>) -> bool { - self.iter() - .any(|t| ::eq_ref(t, value)) - } -} - -impl VariadicMultiset for VariadicColumnMultiset where Schema: PartialEqVariadic {} - -impl fmt::Debug for VariadicColumnMultiset -where - T: fmt::Debug + VariadicExt + PartialEqVariadic, - for<'a> T::AsRefVar<'a>: Hash + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_set().entries(self.iter()).finish() - } -} - -impl IntoIterator for VariadicColumnMultiset -where - Schema: PartialEqVariadic, -{ - type Item = Schema; - type IntoIter = ::IntoZip; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.columns.into_zip() - } -} - -impl Extend for VariadicColumnMultiset -where - K: Eq + Hash + PartialEqVariadic, - for<'a> K::AsRefVar<'a>: Hash, -{ - // #[cfg_attr(feature = "inline-more", inline)] - fn extend>(&mut self, iter: T) { - let iter = iter.into_iter(); - // self.table.reserve(reserve, hasher); - iter.for_each(move |k| { - self.insert(k); - }); - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::{var_expr, var_type}; - - type TestSchema = var_type!(i16, i32, i64, &'static str); - - #[test] - fn test_collections() { - let test_data: Vec = vec![ - var_expr!(1, 1, 1, "hello"), - var_expr!(1, 1, 1, "hello"), - var_expr!(1, 1, 1, "world"), - var_expr!(1, 1, 2, "world"), - ]; - - let mut hash_set: VariadicHashSet = Default::default(); - hash_set.extend(test_data.clone()); - let mut multi_set: VariadicCountedHashSet = Default::default(); - let hash = multi_set - .hasher - .hash_one(var_expr!(1, 1, 1, "world").as_ref_var()); - let hash2 = multi_set - .hasher - .hash_one(var_expr!(1, 1, 1, "world").as_ref_var()); - assert_eq!(hash, hash2); - multi_set.extend(test_data.clone()); - let mut columnar: VariadicColumnMultiset = Default::default(); - columnar.extend(test_data.clone()); - - assert_eq!(multi_set.len(), 4); - assert_eq!(columnar.len(), 4); - assert_eq!(hash_set.len(), 3); - - hash_set.insert(var_expr!(1, 1, 1, "hello")); - hash_set.insert(var_expr!(2, 1, 1, "dup")); - hash_set.insert(var_expr!(2, 1, 1, "dup")); - multi_set.insert(var_expr!(1, 1, 1, "hello")); - multi_set.insert(var_expr!(2, 1, 1, "dup")); - multi_set.insert(var_expr!(2, 1, 1, "dup")); - columnar.insert(var_expr!(1, 1, 1, "hello")); - columnar.insert(var_expr!(2, 1, 1, "dup")); - columnar.insert(var_expr!(2, 1, 1, "dup")); - - assert_eq!(multi_set.len(), 7); - assert_eq!(columnar.len(), 7); - assert_eq!(hash_set.len(), 4); - - assert!(test_data.iter().all(|t| hash_set.contains(t.as_ref_var()))); - assert!(test_data.iter().all(|t| multi_set.contains(t.as_ref_var()))); - assert!(test_data.iter().all(|t| columnar.contains(t.as_ref_var()))); - - let _hs = hash_set.drain().collect::>(); - let _ms = multi_set.drain().collect::>(); - let _c = columnar.drain().collect::>(); - assert_eq!(hash_set.len(), 0); - assert_eq!(multi_set.len(), 0); - assert_eq!(columnar.len(), 0); - } -}