logic_eval_util/
unique.rs

1use crate::Map;
2use smallvec::{SmallVec, smallvec};
3use std::{
4    cell::Cell,
5    hash::{DefaultHasher, Hash, Hasher},
6    iter, mem, ops,
7};
8
9/// - Each value is unique in this container. if multiple indices have to refer
10///   to the same value, then only one index points to the real value and the
11///   others point to indirect values, which are just jump indices to the real
12///   value.
13/// - You can get a value via its index.
14/// - This container doesn't support remove methods except clear method, so that
15///   index cannot be broken until you call the clear method.
16#[derive(Debug, Clone)]
17pub struct UniqueContainer<T> {
18    values: Values<T>,
19
20    /// Hash of a `T` -> Indices to `values`, but only for [`Value::Data`].
21    map: Map<u64, SmallVec<[usize; 1]>>,
22}
23
24impl<T> UniqueContainer<T> {
25    pub fn new() -> Self {
26        Self {
27            values: Values::new(),
28            map: Map::default(),
29        }
30    }
31
32    pub const fn len(&self) -> usize {
33        self.values.len()
34    }
35
36    pub const fn is_empty(&self) -> bool {
37        self.len() == 0
38    }
39
40    pub fn get(&self, index: usize) -> Option<&T> {
41        self.values.get(index)
42    }
43
44    pub fn iter(&self) -> PairIter<T> {
45        self.values.iter()
46    }
47
48    pub fn values(&self) -> ValueIter<T> {
49        self.values.values()
50    }
51
52    pub fn clear(&mut self) {
53        self.values.clear();
54        self.map.clear();
55    }
56}
57
58impl<T> UniqueContainer<T>
59where
60    T: Hash + Eq + std::fmt::Debug, // TODO: remove debug
61{
62    /// Inserts the given value in the container.
63    ///
64    /// If the same value was found by [`PartialEq`], then the old value is
65    /// replaced with the given new value.
66    pub fn insert(&mut self, value: T) -> usize {
67        let hash = Self::hash(&value);
68        if let Some(index) = self._find(hash, &value) {
69            self.values.replace(index, Value::Data(value));
70            return index;
71        }
72
73        let index = self.values.len();
74
75        Self::append_mapping(&mut self.map, hash, index);
76        self.values.push(Value::Data(value));
77
78        index
79    }
80
81    pub fn next_index<Q>(&mut self, value: &Q) -> usize
82    where
83        Q: Hash + PartialEq<T> + ?Sized,
84    {
85        self.find(value).unwrap_or(self.values.len())
86    }
87
88    pub fn replace<Q>(&mut self, old: &Q, new: T) -> bool
89    where
90        Q: Hash + PartialEq<T> + ?Sized,
91    {
92        if let Some(index) = self.find(old) {
93            self.replace_at(index, new);
94            true
95        } else {
96            false
97        }
98    }
99
100    /// Replaces a value at the given index with the given value.
101    ///
102    /// Note that some other indices that point to the old value will point to
103    /// the given new value after replacement.
104    ///
105    /// You may keep in mind that you should get an index using [`Self::find`].
106    /// Because what you want would be to replace [`Value::Data`] which can
107    /// be obtained by the find function. Otherwise, you may pick up an index
108    /// to a [`Value::Indirect`] which ends up a wrong result.
109    fn replace_at(&mut self, index: usize, value: T) {
110        let hash = Self::hash(&value);
111
112        if let Some(exist_idx) = self._find(hash, &value) {
113            self.values
114                .replace(index, Value::Indirect(Cell::new(exist_idx)));
115            self.values.replace(exist_idx, Value::Data(value));
116        } else {
117            Self::append_mapping(&mut self.map, hash, index);
118            let old = self.values.replace(index, Value::Data(value));
119            if let Value::Data(old) = old {
120                Self::remove_mapping(&mut self.map, Self::hash(&old), index);
121            }
122        }
123    }
124
125    pub fn find<Q>(&self, value: &Q) -> Option<usize>
126    where
127        Q: Hash + PartialEq<T> + ?Sized,
128    {
129        let hash = Self::hash(value);
130        self._find(hash, value)
131    }
132
133    /// Returns an index to the given value in the container.
134    ///
135    /// The returned index points to a real data, which is [`Value::Data`] in
136    /// other words.
137    fn _find<Q>(&self, hash: u64, value: &Q) -> Option<usize>
138    where
139        Q: PartialEq<T> + ?Sized,
140    {
141        if let Some(idxs) = self.map.get(&hash) {
142            for idx in idxs.iter() {
143                if value == &self.values[*idx] {
144                    return Some(*idx);
145                }
146            }
147        }
148        None
149    }
150
151    fn hash<Q>(value: &Q) -> u64
152    where
153        Q: Hash + PartialEq<T> + ?Sized,
154    {
155        let mut hasher = DefaultHasher::new();
156        value.hash(&mut hasher);
157        hasher.finish()
158    }
159
160    fn append_mapping(map: &mut Map<u64, SmallVec<[usize; 1]>>, hash: u64, index: usize) {
161        map.entry(hash)
162            .and_modify(|indices| indices.push(index))
163            .or_insert(smallvec![index]);
164    }
165
166    fn remove_mapping(map: &mut Map<u64, SmallVec<[usize; 1]>>, hash: u64, index: usize) {
167        let Some(indices) = map.get_mut(&hash) else {
168            return;
169        };
170
171        let Some((i, _)) = indices.iter().enumerate().find(|(_, ii)| **ii == index) else {
172            return;
173        };
174
175        indices.swap_remove(i);
176
177        if indices.is_empty() {
178            map.remove(&hash);
179        }
180    }
181}
182
183impl<T> ops::Index<usize> for UniqueContainer<T> {
184    type Output = T;
185
186    fn index(&self, index: usize) -> &Self::Output {
187        &self.values[index]
188    }
189}
190
191impl<T> Default for UniqueContainer<T> {
192    fn default() -> Self {
193        Self::new()
194    }
195}
196
197#[derive(Debug, Clone)]
198struct Values<T>(Vec<Value<T>>);
199
200impl<T> Values<T> {
201    const fn new() -> Self {
202        Self(Vec::new())
203    }
204
205    const fn len(&self) -> usize {
206        self.0.len()
207    }
208
209    fn iter(&self) -> PairIter<T> {
210        PairIter::new(self)
211    }
212
213    fn values(&self) -> ValueIter<T> {
214        ValueIter::new(self)
215    }
216
217    fn get(&self, index: usize) -> Option<&T> {
218        self.get_with_opt(index).map(|(_idx, ty)| ty)
219    }
220
221    fn get_with_opt(&self, index: usize) -> Option<(usize, &T)> {
222        match self.0.get(index)? {
223            Value::Indirect(v) => {
224                let (w, ty) = self.get_with_opt(v.get())?;
225                v.set(w);
226                Some((w, ty))
227            }
228            Value::Data(ty) => Some((index, ty)),
229        }
230    }
231
232    fn replace(&mut self, index: usize, value: Value<T>) -> Value<T> {
233        mem::replace(&mut self.0[index], value)
234    }
235
236    fn push(&mut self, value: Value<T>) {
237        self.0.push(value);
238    }
239
240    fn clear(&mut self) {
241        self.0.clear();
242    }
243}
244
245impl<T> ops::Index<usize> for Values<T> {
246    type Output = T;
247
248    fn index(&self, index: usize) -> &Self::Output {
249        self.get(index).expect("index is out of bounds")
250    }
251}
252
253#[derive(Debug, Clone)]
254enum Value<T> {
255    Indirect(Cell<usize>),
256    Data(T),
257}
258
259/// The iterator skips indirect values.
260#[derive(Clone)]
261pub struct PairIter<'a, T> {
262    values: &'a [Value<T>],
263    cur: usize,
264    remain: usize,
265}
266
267impl<'a, T> PairIter<'a, T> {
268    fn new(values: &'a Values<T>) -> Self {
269        Self {
270            values: values.0.as_slice(),
271            cur: 0,
272            remain: values
273                .0
274                .iter()
275                .filter(|value| matches!(value, Value::Data(_)))
276                .count(),
277        }
278    }
279
280    const fn len(&self) -> usize {
281        self.remain
282    }
283}
284
285impl<'a, T> Iterator for PairIter<'a, T> {
286    type Item = (usize, &'a T);
287
288    fn next(&mut self) -> Option<Self::Item> {
289        if self.remain == 0 {
290            return None;
291        }
292
293        let value = loop {
294            let value = &self.values[self.cur];
295            self.cur += 1;
296            match value {
297                Value::Indirect(_) => continue,
298                Value::Data(value) => break value,
299            }
300        };
301        self.remain -= 1;
302        Some((self.cur - 1, value))
303    }
304
305    fn size_hint(&self) -> (usize, Option<usize>) {
306        let len = <Self>::len(self);
307        (len, Some(len))
308    }
309}
310
311impl<T> ExactSizeIterator for PairIter<'_, T> {
312    fn len(&self) -> usize {
313        <Self>::len(self)
314    }
315}
316
317impl<T> iter::FusedIterator for PairIter<'_, T> {}
318
319/// The iterator skips indirect values.
320#[derive(Clone)]
321pub struct ValueIter<'a, T> {
322    rest: &'a [Value<T>],
323    remain: usize,
324}
325
326impl<'a, T> ValueIter<'a, T> {
327    fn new(values: &'a Values<T>) -> Self {
328        Self {
329            rest: values.0.as_slice(),
330            remain: values
331                .0
332                .iter()
333                .filter(|value| matches!(value, Value::Data(_)))
334                .count(),
335        }
336    }
337
338    const fn len(&self) -> usize {
339        self.remain
340    }
341}
342
343impl<'a, T> Iterator for ValueIter<'a, T> {
344    type Item = &'a T;
345
346    fn next(&mut self) -> Option<Self::Item> {
347        let value = loop {
348            let (head, rest) = self.rest.split_first()?;
349            self.rest = rest;
350            match head {
351                Value::Indirect(_) => continue,
352                Value::Data(value) => break value,
353            }
354        };
355        self.remain -= 1;
356        Some(value)
357    }
358
359    fn size_hint(&self) -> (usize, Option<usize>) {
360        let len = <Self>::len(self);
361        (len, Some(len))
362    }
363}
364
365impl<T> ExactSizeIterator for ValueIter<'_, T> {
366    fn len(&self) -> usize {
367        <Self>::len(self)
368    }
369}
370
371impl<T> iter::FusedIterator for ValueIter<'_, T> {}