Skip to main content

jsonld_core/object/node/
multiset.rs

1use std::hash::{BuildHasher, Hash};
2
3#[derive(Debug, Default, Clone, Copy)]
4/// Hasher builder giving the same hashes across runs, so multiset
5/// iteration order is reproducible.
6pub struct DeterministicHasherBuilder;
7
8impl BuildHasher for DeterministicHasherBuilder {
9    type Hasher = foldhash::fast::FoldHasher<'static>;
10
11    fn build_hasher(&self) -> Self::Hasher {
12        foldhash::fast::FixedState::default().build_hasher()
13    }
14}
15
16use jsonld_syntax::IntoJsonWithContext;
17
18/// Multi-set of values.
19#[derive(Debug, Clone)]
20pub struct Multiset<T, S = DeterministicHasherBuilder> {
21    data: Vec<T>,
22    hasher: S,
23}
24
25impl<T, S: Default> Default for Multiset<T, S> {
26    fn default() -> Self {
27        Self {
28            data: Vec::new(),
29            hasher: S::default(),
30        }
31    }
32}
33
34impl<T, S> Multiset<T, S> {
35    /// Creates a new `Multiset`.
36    #[must_use]
37    pub fn new() -> Self
38    where
39        S: Default,
40    {
41        Self::default()
42    }
43
44    /// Creates a new `Multiset` with room for `cap` values.
45    #[must_use]
46    pub fn with_capacity(cap: usize) -> Self
47    where
48        S: Default,
49    {
50        Self {
51            data: Vec::with_capacity(cap),
52            hasher: S::default(),
53        }
54    }
55
56    /// Returns the number of values in the multiset, duplicates included.
57    pub fn len(&self) -> usize {
58        self.data.len()
59    }
60
61    /// Checks whether the multiset holds no values.
62    pub fn is_empty(&self) -> bool {
63        self.data.is_empty()
64    }
65
66    /// Checks whether the multiset holds the given value.
67    pub fn contains(&self, value: &T) -> bool
68    where
69        T: PartialEq,
70    {
71        self.data.contains(value)
72    }
73
74    /// Returns an iterator over the values of the multiset, in insertion
75    /// order.
76    pub fn iter(&self) -> core::slice::Iter<'_, T> {
77        self.data.iter()
78    }
79
80    /// Returns a mutable iterator over the values of the multiset, in
81    /// insertion order.
82    pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
83        self.data.iter_mut()
84    }
85
86    /// Returns the values of the multiset as a slice, in insertion order.
87    pub fn as_slice(&self) -> &[T] {
88        &self.data
89    }
90}
91
92impl<T: Hash, S: BuildHasher> Multiset<T, S> {
93    /// Builds a multiset holding a single value.
94    pub fn singleton(value: T) -> Self
95    where
96        S: Default,
97    {
98        let mut result = Self::new();
99        result.insert(value);
100        result
101    }
102
103    /// Inserts a value. Duplicates are kept: inserting a value already
104    /// present adds another occurrence of it.
105    pub fn insert(&mut self, value: T) {
106        self.data.push(value);
107    }
108
109    /// Inserts the value only if it is not already present. Returns `true`
110    /// if it was inserted.
111    pub fn insert_unique(&mut self, value: T) -> bool
112    where
113        T: PartialEq,
114    {
115        if self.contains(&value) {
116            false
117        } else {
118            self.insert(value);
119            true
120        }
121    }
122}
123
124impl<'a, T, S> IntoIterator for &'a Multiset<T, S> {
125    type Item = &'a T;
126    type IntoIter = core::slice::Iter<'a, T>;
127
128    fn into_iter(self) -> Self::IntoIter {
129        self.iter()
130    }
131}
132
133impl<'a, T, S> IntoIterator for &'a mut Multiset<T, S> {
134    type Item = &'a mut T;
135    type IntoIter = core::slice::IterMut<'a, T>;
136
137    fn into_iter(self) -> Self::IntoIter {
138        self.iter_mut()
139    }
140}
141
142impl<T, S> IntoIterator for Multiset<T, S> {
143    type Item = T;
144    type IntoIter = std::vec::IntoIter<T>;
145
146    fn into_iter(self) -> Self::IntoIter {
147        self.data.into_iter()
148    }
149}
150
151impl<T: Hash, S: Default + BuildHasher> FromIterator<T> for Multiset<T, S> {
152    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
153        let mut result = Self::new();
154
155        for item in iter {
156            result.insert(item);
157        }
158
159        result
160    }
161}
162
163impl<T: Hash, S: BuildHasher> Extend<T> for Multiset<T, S> {
164    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
165        for item in iter {
166            self.insert(item);
167        }
168    }
169}
170
171impl<T: PartialEq<U>, U, S, P> PartialEq<Multiset<U, P>> for Multiset<T, S> {
172    fn eq(&self, other: &Multiset<U, P>) -> bool {
173        compare_unordered(&self.data, &other.data)
174    }
175}
176
177pub(crate) fn compare_unordered<T: PartialEq<U>, U>(a: &[T], b: &[U]) -> bool {
178    if a.len() == b.len() {
179        let mut free_indexes = Vec::new();
180        free_indexes.resize(a.len(), true);
181
182        for item in a {
183            match free_indexes.iter_mut().enumerate().find(|(i, free)| **free && item == &b[*i]) {
184                Some((_, free)) => *free = false,
185                None => return false,
186            }
187        }
188
189        true
190    } else {
191        false
192    }
193}
194
195pub(crate) fn compare_unordered_opt<T: PartialEq<U>, U>(a: Option<&[T]>, b: Option<&[U]>) -> bool {
196    match (a, b) {
197        (Some(a), Some(b)) => compare_unordered(a, b),
198        (None, None) => true,
199        _ => false,
200    }
201}
202
203impl<T: Eq, S> Eq for Multiset<T, S> {}
204
205impl<T: Hash, S: BuildHasher> Hash for Multiset<T, S> {
206    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
207        let mut hash = 0u64;
208
209        for item in self {
210            hash = hash.wrapping_add(self.hasher.hash_one(item));
211        }
212
213        state.write_u64(hash);
214    }
215}
216
217impl<T: IntoJsonWithContext<N>, S, N> IntoJsonWithContext<N> for Multiset<T, S> {
218    fn into_json_with(self, vocabulary: &N) -> jstrict::Value {
219        jstrict::Value::Array(self.into_iter().map(|item| item.into_json_with(vocabulary)).collect())
220    }
221}