libgraphql-core 0.0.8

Core libraries provided by the `libgraphql` crate.
Documentation
use std::borrow::Borrow;
use std::collections::HashMap;
use std::hash::BuildHasher;
use std::hash::Hash;
use std::hash::RandomState;
use std::ops::Index;

type TFilterFn<K, V> = fn(&(&K, &V)) -> bool;

#[derive(Clone, Debug)]
pub struct ReadOnlyMap<
    'a,
    K,
    V,
    S = RandomState,
> {
    map: &'a HashMap<K, V, S>,
    filter_fn: TFilterFn<K, V>,
}

impl<'a, K, V> ReadOnlyMap<'a, K, V, RandomState> {
    #[inline]
    pub fn new(
        map: &'a HashMap<K, V>,
        filter_fn: Option<TFilterFn<K, V>>,
    ) -> ReadOnlyMap<'a, K, V, RandomState> {
        Self {
            map,
            filter_fn: filter_fn.unwrap_or(|_| true),
        }
    }
}

impl<'a, K, V, S> ReadOnlyMap<'a, K, V, S> {
    #[inline]
    pub fn capacity(&self) -> usize {
        self.map.capacity()
    }

    pub fn keys(&self) -> impl Iterator<Item = &K> {
        self.iter().map(|(key, _val)| key)
    }

    pub fn values(&self) -> impl Iterator<Item = &V> {
        self.iter().map(|(_key, val)| val)
    }

    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
        self.map.iter().filter(&self.filter_fn)
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.map.len()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.map.is_empty()
    }

    #[inline]
    pub fn hasher(&self) -> &S {
        self.map.hasher()
    }
}

impl<
    'a,
    K: Eq + Hash,
    V,
    S: BuildHasher,
> ReadOnlyMap<'a, K, V, S> {
    #[inline]
    pub fn get<Q>(&self, k: &Q) -> Option<&'a V>
    where
        K: Borrow<Q>,
        Q: Hash + Eq + ?Sized,
    {
        let filter_fn = &self.filter_fn;
        self.map.get_key_value(k).and_then(|(k, v)| {
            if filter_fn(&(k, v)) {
                Some(v)
            } else {
                None
            }
        })
    }

    #[inline]
    pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&'a K, &'a V)>
    where
        K: Borrow<Q>,
        Q: Hash + Eq + ?Sized,
    {
        let filter_fn = &self.filter_fn;
        self.map.get_key_value(k).filter(|(k, v)| filter_fn(&(k, v)))
    }

    #[inline]
    pub fn contains_key<Q>(&self, k: &Q) -> bool
    where
        K: Borrow<Q>,
        Q: Hash + Eq + ?Sized,
    {
        self.get(k).is_some()
    }
}

impl<
    'a,
    K: Eq + Hash,
    V: PartialEq,
    S: BuildHasher,
> PartialEq for ReadOnlyMap<'a, K, V, S> {
    fn eq(&self, other: &ReadOnlyMap<'_, K, V, S>) -> bool {
        self.iter().all(|(key, value)| other.get(key).is_some_and(|v| *value == *v))
    }
}

impl<
    'a,
    K: Eq + Hash,
    V: Eq,
    S: BuildHasher,
> Eq for ReadOnlyMap<'a, K, V, S> {}

impl<
    'a,
    K,
    V: Eq,
    Q,
    S: BuildHasher,
> Index<&Q> for ReadOnlyMap<'a, K, V, S>
where
    K: Eq + Hash + Borrow<Q>,
    Q: Hash + Eq + ?Sized,
{
    type Output = V;

    #[inline]
    fn index(&self, key: &Q) -> &'a V {
        self.get(key).expect("no entry found for key")
    }
}