Skip to main content

sdset/
collection.rs

1use std::hash::Hash;
2use std::collections::{HashSet, BTreeSet};
3
4/// This trait is meant to abstract any kind of collection
5/// (i.e. [`Vec`], [`HashSet`]).
6///
7/// This is particularly helpful when you want particular behavior
8/// when inserting elements, the [`Counter`] struct is a good example
9/// of a custom implementation of the [`Collection`] trait, it is used to only
10/// count the number of elements of a set operation.
11pub trait Collection<T> {
12
13    /// Insert one element into the collection.
14    fn push(&mut self, elem: T);
15
16    /// Extend the collection by cloning the elements.
17    fn extend_from_slice(&mut self, elems: &[T]) where T: Clone;
18
19    /// Extend the collection by inserting the elements from the given [`Iterator`].
20    fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T>;
21
22    /// Reserve enough space in the collection for `size` elements.
23    fn reserve(&mut self, _size: usize) { }
24}
25
26impl<T> Collection<T> for Vec<T> {
27    fn push(&mut self, elem: T) {
28        Vec::push(self, elem);
29    }
30
31    fn extend_from_slice(&mut self, elems: &[T]) where T: Clone {
32        Vec::extend_from_slice(self, elems);
33    }
34
35    fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T> {
36        Extend::extend(self, elems);
37    }
38
39    fn reserve(&mut self, size: usize) {
40        Vec::reserve(self, size);
41    }
42}
43
44impl<T: Hash + Eq> Collection<T> for HashSet<T> {
45    fn push(&mut self, elem: T) {
46        HashSet::insert(self, elem);
47    }
48
49    fn extend_from_slice(&mut self, elems: &[T]) where T: Clone {
50        Collection::extend(self, elems.iter().cloned());
51    }
52
53    fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T> {
54        Extend::extend(self, elems);
55    }
56
57    fn reserve(&mut self, size: usize) {
58        HashSet::reserve(self, size);
59    }
60}
61
62impl<T: Ord> Collection<T> for BTreeSet<T> {
63    fn push(&mut self, elem: T) {
64        BTreeSet::insert(self, elem);
65    }
66
67    fn extend_from_slice(&mut self, elems: &[T]) where T: Clone {
68        Collection::extend(self, elems.iter().cloned());
69    }
70
71    fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T> {
72        Extend::extend(self, elems);
73    }
74}
75
76/// A [`Collection`] that only counts the final size of a set operation.
77///
78/// It is meant to be used to avoid unecessary allocations.
79///
80/// ```
81/// # use sdset::Error;
82/// # fn try_main() -> Result<(), Error> {
83/// use sdset::duo::OpBuilder;
84/// use sdset::{SetOperation, Set, SetBuf, Counter};
85///
86/// let a = Set::new(&[1, 2, 4, 6, 7])?;
87/// let b = Set::new(&[2, 3, 4, 5, 6, 7])?;
88///
89/// let op = OpBuilder::new(a, b).union();
90///
91/// let mut counter = Counter::default();
92/// SetOperation::<i32>::extend_collection(op, &mut counter);
93///
94/// assert_eq!(counter.0, 7);
95/// # Ok(()) }
96/// # try_main().unwrap();
97/// ```
98#[derive(Default)]
99pub struct Counter(pub usize);
100
101impl Counter {
102    /// Create a new [`Counter`] initialized with 0;
103    pub fn new() -> Counter {
104        Counter::default()
105    }
106}
107
108impl<T> Collection<T> for Counter {
109    fn push(&mut self, _elem: T) {
110        self.0 = self.0.saturating_add(1);
111    }
112
113    fn extend_from_slice(&mut self, elems: &[T]) where T: Clone {
114        self.0 = self.0.saturating_add(elems.len());
115    }
116
117    fn extend<I>(&mut self, elems: I) where I: IntoIterator<Item=T> {
118        self.0 = self.0.saturating_add(elems.into_iter().count());
119    }
120}