libgraphql_core/
readonly_map.rs

1use std::borrow::Borrow;
2use std::collections::HashMap;
3use std::hash::BuildHasher;
4use std::hash::Hash;
5use std::hash::RandomState;
6use std::ops::Index;
7
8type TFilterFn<K, V> = fn(&(&K, &V)) -> bool;
9
10#[derive(Clone, Debug)]
11pub struct ReadOnlyMap<
12    'a,
13    K,
14    V,
15    S = RandomState,
16> {
17    map: &'a HashMap<K, V, S>,
18    filter_fn: TFilterFn<K, V>,
19}
20
21impl<'a, K, V> ReadOnlyMap<'a, K, V, RandomState> {
22    #[inline]
23    pub fn new(
24        map: &'a HashMap<K, V>,
25        filter_fn: Option<TFilterFn<K, V>>,
26    ) -> ReadOnlyMap<'a, K, V, RandomState> {
27        Self {
28            map,
29            filter_fn: filter_fn.unwrap_or(|_| true),
30        }
31    }
32}
33
34impl<'a, K, V, S> ReadOnlyMap<'a, K, V, S> {
35    #[inline]
36    pub fn capacity(&self) -> usize {
37        self.map.capacity()
38    }
39
40    pub fn keys(&self) -> impl Iterator<Item = &K> {
41        self.iter().map(|(key, _val)| key)
42    }
43
44    pub fn values(&self) -> impl Iterator<Item = &V> {
45        self.iter().map(|(_key, val)| val)
46    }
47
48    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
49        self.map.iter().filter(&self.filter_fn)
50    }
51
52    #[inline]
53    pub fn len(&self) -> usize {
54        self.map.len()
55    }
56
57    #[inline]
58    pub fn is_empty(&self) -> bool {
59        self.map.is_empty()
60    }
61
62    #[inline]
63    pub fn hasher(&self) -> &S {
64        self.map.hasher()
65    }
66}
67
68impl<
69    'a,
70    K: Eq + Hash,
71    V,
72    S: BuildHasher,
73> ReadOnlyMap<'a, K, V, S> {
74    #[inline]
75    pub fn get<Q>(&self, k: &Q) -> Option<&'a V>
76    where
77        K: Borrow<Q>,
78        Q: Hash + Eq + ?Sized,
79    {
80        let filter_fn = &self.filter_fn;
81        self.map.get_key_value(k).and_then(|(k, v)| {
82            if filter_fn(&(k, v)) {
83                Some(v)
84            } else {
85                None
86            }
87        })
88    }
89
90    #[inline]
91    pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&'a K, &'a V)>
92    where
93        K: Borrow<Q>,
94        Q: Hash + Eq + ?Sized,
95    {
96        let filter_fn = &self.filter_fn;
97        self.map.get_key_value(k).filter(|(k, v)| filter_fn(&(k, v)))
98    }
99
100    #[inline]
101    pub fn contains_key<Q>(&self, k: &Q) -> bool
102    where
103        K: Borrow<Q>,
104        Q: Hash + Eq + ?Sized,
105    {
106        self.get(k).is_some()
107    }
108}
109
110impl<
111    'a,
112    K: Eq + Hash,
113    V: PartialEq,
114    S: BuildHasher,
115> PartialEq for ReadOnlyMap<'a, K, V, S> {
116    fn eq(&self, other: &ReadOnlyMap<'_, K, V, S>) -> bool {
117        self.iter().all(|(key, value)| other.get(key).is_some_and(|v| *value == *v))
118    }
119}
120
121impl<
122    'a,
123    K: Eq + Hash,
124    V: Eq,
125    S: BuildHasher,
126> Eq for ReadOnlyMap<'a, K, V, S> {}
127
128impl<
129    'a,
130    K,
131    V: Eq,
132    Q,
133    S: BuildHasher,
134> Index<&Q> for ReadOnlyMap<'a, K, V, S>
135where
136    K: Eq + Hash + Borrow<Q>,
137    Q: Hash + Eq + ?Sized,
138{
139    type Output = V;
140
141    #[inline]
142    fn index(&self, key: &Q) -> &'a V {
143        self.get(key).expect("no entry found for key")
144    }
145}