use std::collections::HashSet;
use std::hash::Hash;
#[cfg(feature = "persistent-artrie")]
use serde::{de::DeserializeOwned, Serialize};
#[cfg(feature = "persistent-artrie")]
pub trait DictionaryValue:
Clone + Default + Send + Sync + Unpin + 'static + Serialize + DeserializeOwned
{
fn is_value(&self) -> bool {
true
}
}
#[cfg(feature = "persistent-artrie")]
mod counter_sealed {
pub trait Sealed {}
impl Sealed for i64 {}
impl Sealed for u64 {}
}
#[cfg(feature = "persistent-artrie")]
pub trait Counter: counter_sealed::Sealed {}
#[cfg(feature = "persistent-artrie")]
impl Counter for i64 {}
#[cfg(feature = "persistent-artrie")]
impl Counter for u64 {}
#[cfg(not(feature = "persistent-artrie"))]
pub trait DictionaryValue: Clone + Default + Send + Sync + Unpin + 'static {
fn is_value(&self) -> bool {
true
}
}
pub trait FilterableValue: DictionaryValue {
type Atom: ?Sized;
fn matches_any<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool;
fn matches_all<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool;
}
impl DictionaryValue for () {
fn is_value(&self) -> bool {
false }
}
impl FilterableValue for () {
type Atom = ();
fn matches_any<F>(&self, _predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
true }
fn matches_all<F>(&self, _predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
true }
}
macro_rules! impl_primitive_value {
($($t:ty),*) => {
$(
impl DictionaryValue for $t {}
impl FilterableValue for $t {
type Atom = Self;
fn matches_any<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
predicate(self)
}
fn matches_all<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
predicate(self)
}
}
)*
};
}
impl_primitive_value!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, bool, char);
impl DictionaryValue for String {}
impl FilterableValue for String {
type Atom = Self;
fn matches_any<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
predicate(self)
}
fn matches_all<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
predicate(self)
}
}
#[cfg(not(feature = "persistent-artrie"))]
impl DictionaryValue for &'static str {}
#[cfg(not(feature = "persistent-artrie"))]
impl FilterableValue for &'static str {
type Atom = Self;
fn matches_any<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
predicate(self)
}
fn matches_all<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
predicate(self)
}
}
impl<T: DictionaryValue> DictionaryValue for Vec<T> {}
impl<T: FilterableValue> FilterableValue for Vec<T> {
type Atom = T;
fn matches_any<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
self.iter().any(predicate)
}
fn matches_all<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
self.iter().all(predicate)
}
}
impl<T: DictionaryValue + Eq + Hash> DictionaryValue for HashSet<T> {}
impl<T: FilterableValue + Eq + Hash> FilterableValue for HashSet<T> {
type Atom = T;
fn matches_any<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
self.iter().any(predicate)
}
fn matches_all<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
self.iter().all(predicate)
}
}
impl<A: smallvec::Array + Send + Sync + Unpin + 'static> DictionaryValue for smallvec::SmallVec<A> where
A::Item: DictionaryValue
{
}
impl<A: smallvec::Array + Send + Sync + Unpin + 'static> FilterableValue for smallvec::SmallVec<A>
where
A::Item: FilterableValue,
{
type Atom = A::Item;
fn matches_any<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
self.iter().any(predicate)
}
fn matches_all<F>(&self, predicate: &F) -> bool
where
F: Fn(&Self::Atom) -> bool,
{
self.iter().all(predicate)
}
}
pub fn contains<T: PartialEq>(collection: &[T], value: &T) -> bool {
collection.contains(value)
}
pub fn any<T, F>(collection: &[T], predicate: F) -> bool
where
F: Fn(&T) -> bool,
{
collection.iter().any(predicate)
}
pub fn all<T, F>(collection: &[T], predicate: F) -> bool
where
F: Fn(&T) -> bool,
{
collection.iter().all(predicate)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_unit_type() {
let unit = ();
assert!(!unit.is_value());
assert!(unit.matches_any(&|_| false)); assert!(unit.matches_all(&|_| false)); }
#[test]
fn test_primitives() {
let num: u32 = 42;
assert!(num.is_value());
assert!(num.matches_any(&|&x| x == 42));
assert!(!num.matches_any(&|&x| x == 99));
assert!(num.matches_all(&|&x| x > 0));
}
#[test]
fn test_strings() {
let s = String::from("hello");
assert!(s.is_value());
assert!(s.matches_any(&|x| x == "hello"));
assert!(!s.matches_any(&|x| x == "world"));
}
#[test]
fn test_vec_per_element() {
let v: Vec<u32> = vec![1, 2, 3];
assert!(v.is_value());
assert!(v.matches_any(&|&x| x == 2));
assert!(!v.matches_any(&|&x| x == 99));
assert!(v.matches_all(&|&x| x > 0));
assert!(!v.matches_all(&|&x| x > 1));
}
#[test]
fn test_hashset_per_element() {
let mut set: HashSet<u32> = HashSet::new();
set.insert(10);
set.insert(20);
set.insert(30);
assert!(set.is_value());
assert!(set.matches_any(&|&x| x == 20));
assert!(!set.matches_any(&|&x| x == 99));
assert!(set.matches_all(&|&x| x >= 10));
assert!(!set.matches_all(&|&x| x > 15));
}
#[test]
fn test_smallvec_per_element() {
let sv: smallvec::SmallVec<[u32; 4]> = smallvec::smallvec![5, 10, 15];
assert!(sv.matches_any(&|&x| x == 10));
assert!(!sv.matches_any(&|&x| x == 999));
assert!(sv.matches_all(&|&x| x >= 5));
assert!(!sv.matches_all(&|&x| x > 10));
}
#[test]
fn test_helper_functions() {
let nums = vec![1, 2, 3, 4, 5];
assert!(contains(&nums, &3));
assert!(!contains(&nums, &10));
assert!(any(&nums, |&x| x > 3));
assert!(!any(&nums, |&x| x > 10));
assert!(all(&nums, |&x| x > 0));
assert!(!all(&nums, |&x| x > 2));
}
}