indexical/
set.rs

1use std::fmt;
2
3use index_vec::Idx;
4
5use crate::{
6    FromIndexicalIterator, IndexedDomain, IndexedValue, ToIndex, bitset::BitSet,
7    pointer::PointerFamily,
8};
9
10/// An unordered collections of `T`s, implemented with a bit-set.
11pub struct IndexSet<'a, T: IndexedValue + 'a, S, P: PointerFamily<'a>> {
12    set: S,
13    domain: P::Pointer<IndexedDomain<T>>,
14}
15
16impl<'a, T, S, P> IndexSet<'a, T, S, P>
17where
18    T: IndexedValue + 'a,
19    S: BitSet,
20    P: PointerFamily<'a>,
21{
22    /// Creates an empty index set.
23    pub fn new(domain: &P::Pointer<IndexedDomain<T>>) -> Self {
24        IndexSet {
25            set: S::empty(domain.len()),
26            domain: domain.clone(),
27        }
28    }
29
30    /// Returns an iterator over all the indices contained in `self`.
31    pub fn indices(&self) -> impl Iterator<Item = T::Index> {
32        self.set.iter().map(T::Index::from_usize)
33    }
34
35    /// Returns an iterator over all the objects contained in `self`.
36    pub fn iter(&self) -> impl Iterator<Item = &T> {
37        self.indices().map(move |idx| self.domain.value(idx))
38    }
39
40    /// Returns an iterator over the pairs of indices and objects contained in `self`.
41    pub fn iter_enumerated(&self) -> impl Iterator<Item = (T::Index, &T)> {
42        self.indices().map(move |idx| (idx, self.domain.value(idx)))
43    }
44
45    /// Returns true if `index` is contained in `self`.
46    pub fn contains<M>(&self, index: impl ToIndex<T, M>) -> bool {
47        let elem = index.to_index(&self.domain);
48        self.set.contains(elem.index())
49    }
50
51    /// Returns the number of elements in `self`.
52    pub fn len(&self) -> usize {
53        self.set.len()
54    }
55
56    /// Return true if `self` has no elements.
57    pub fn is_empty(&self) -> bool {
58        self.len() == 0
59    }
60
61    /// Returns true if every element in `other` is also in `self`.
62    pub fn is_superset(&self, other: &IndexSet<'a, T, S, P>) -> bool {
63        self.set.superset(&other.set)
64    }
65
66    /// Adds the element `elt` to `self`, returning true if `self` changed.
67    pub fn insert<M>(&mut self, elt: impl ToIndex<T, M>) -> bool {
68        let elt = elt.to_index(&self.domain);
69        self.set.insert(elt.index())
70    }
71
72    /// Removes the element `elt` from `self`, returning true if `self` changed.
73    pub fn remove<M>(&mut self, elt: impl ToIndex<T, M>) -> bool {
74        let elt = elt.to_index(&self.domain);
75        self.set.remove(elt.index())
76    }
77
78    /// Adds each element of `other` to `self`.
79    pub fn union(&mut self, other: &IndexSet<'a, T, S, P>) {
80        self.set.union(&other.set);
81    }
82
83    /// Adds each element of `other` to `self`, returning true if `self` changed.
84    pub fn union_changed(&mut self, other: &IndexSet<'a, T, S, P>) -> bool {
85        self.set.union_changed(&other.set)
86    }
87
88    /// Removes every element of `other` from `self`.
89    pub fn subtract(&mut self, other: &IndexSet<'a, T, S, P>) {
90        self.set.subtract(&other.set)
91    }
92
93    /// Removes every element of `other` from `self`, returning true if `self` changed.
94    pub fn subtract_changed(&mut self, other: &IndexSet<'a, T, S, P>) -> bool {
95        self.set.subtract_changed(&other.set)
96    }
97
98    /// Removes every element of `self` not in `other`.
99    pub fn intersect(&mut self, other: &IndexSet<'a, T, S, P>) {
100        self.set.intersect(&other.set)
101    }
102
103    /// Removes every element of `self` not in `other`, returning true if `self` changed.
104    pub fn intersect_changed(&mut self, other: &IndexSet<'a, T, S, P>) -> bool {
105        self.set.intersect_changed(&other.set)
106    }
107
108    /// Adds every element of the domain to `self`.
109    pub fn insert_all(&mut self) {
110        self.set.insert_all()
111    }
112
113    /// Removes every element from `self`.
114    pub fn clear(&mut self) {
115        self.set.clear();
116    }
117
118    /// Returns a reference to the inner set.
119    pub fn inner(&self) -> &S {
120        &self.set
121    }
122}
123
124impl<'a, T, S, P> fmt::Debug for IndexSet<'a, T, S, P>
125where
126    T: IndexedValue + fmt::Debug + 'a,
127    S: BitSet,
128    P: PointerFamily<'a>,
129{
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        f.debug_set().entries(self.iter()).finish()
132    }
133}
134
135impl<'a, T, S, P> PartialEq for IndexSet<'a, T, S, P>
136where
137    T: IndexedValue + 'a,
138    S: BitSet,
139    P: PointerFamily<'a>,
140{
141    fn eq(&self, other: &Self) -> bool {
142        self.set == other.set
143    }
144}
145
146impl<'a, T, S, P> Eq for IndexSet<'a, T, S, P>
147where
148    T: IndexedValue + 'a,
149    S: BitSet,
150    P: PointerFamily<'a>,
151{
152}
153
154impl<'a, T, S, P> Clone for IndexSet<'a, T, S, P>
155where
156    T: IndexedValue + 'a,
157    S: BitSet,
158    P: PointerFamily<'a>,
159{
160    fn clone(&self) -> Self {
161        IndexSet {
162            set: self.set.clone(),
163            domain: self.domain.clone(),
164        }
165    }
166
167    fn clone_from(&mut self, source: &Self) {
168        self.set.copy_from(&source.set);
169        self.domain = source.domain.clone();
170    }
171}
172
173impl<'a, T, U, S, M, P> FromIndexicalIterator<'a, T, P, M, U> for IndexSet<'a, T, S, P>
174where
175    T: IndexedValue + 'a,
176    S: BitSet,
177    P: PointerFamily<'a>,
178    U: ToIndex<T, M>,
179{
180    fn from_indexical_iter(
181        iter: impl Iterator<Item = U>,
182        domain: &P::Pointer<IndexedDomain<T>>,
183    ) -> Self {
184        let mut set = IndexSet::new(domain);
185        for s in iter {
186            set.insert(s);
187        }
188        set
189    }
190}
191
192#[cfg(test)]
193mod test {
194    use crate::{IndexedDomain, IndexicalIteratorExt, test_utils::TestIndexSet};
195    use std::rc::Rc;
196
197    fn mk(s: &str) -> String {
198        s.to_string()
199    }
200
201    #[test]
202    fn test_indexset() {
203        let d = Rc::new(IndexedDomain::from_iter([mk("a"), mk("b"), mk("c")]));
204        let mut s = TestIndexSet::new(&d);
205        s.insert(mk("a"));
206        let b = d.index(&mk("b"));
207        s.insert(b);
208        assert!(s.contains(mk("a")));
209        assert!(s.contains(mk("b")));
210        assert_eq!(s.len(), 2);
211
212        assert_eq!(
213            [mk("a"), mk("b")]
214                .into_iter()
215                .collect_indexical::<TestIndexSet<_>>(&d),
216            s
217        );
218        assert_eq!(format!("{s:?}"), r#"{"a", "b"}"#)
219    }
220
221    #[cfg(feature = "bitvec")]
222    #[test]
223    fn test_indexset_reffamily() {
224        let d = &IndexedDomain::from_iter([mk("a"), mk("b"), mk("c")]);
225        let mut s = crate::bitset::bitvec::RefIndexSet::new(&d);
226        s.insert(mk("a"));
227        assert!(s.contains(mk("a")));
228
229        let s2 = s.clone();
230        assert!(std::ptr::eq(s.domain, s2.domain));
231    }
232}