tag_vec/lib.rs
1use std::collections::HashMap;
2use std::hash::Hash;
3
4mod dyn_bit_field;
5use dyn_bit_field::DynamicBitField;
6mod bit_field;
7mod query;
8
9// Reexport a bunch of stuff
10// (i.e. flatten the hierarchy to make the api easier to use)
11pub use bit_field::BitField;
12pub use query::Query;
13pub use query::Expression;
14pub use query::expressions;
15
16/// This is the main star of this crate.
17/// It is an efficient model of a vector of elements,
18/// where each element is just a set of tags.
19///
20/// This datatype is intended to handle requests for a huge set
21/// of elements whose tags fulfill a requirement, i.e. "all elements
22/// with the tag 'fruit' but not with the tag 'apple'.
23///
24/// It is expected that the elements share a lot of tags, i.e.
25/// there are a lot fewer tags than elements.
26///
27/// It is not optimized for simply iterating over the tags
28/// of each element, hence it is not recommended to do such
29/// a thing with this datatype too much.
30pub struct TagVec<T, F = u32>
31 where T: Eq + Hash + Clone, F: BitField {
32 tag_fields: HashMap<T, DynamicBitField<F>>,
33 len: usize,
34}
35
36impl<T: Eq + Hash + Clone, F: BitField> TagVec<T, F> {
37 // I don't think this needs an example?
38 /// Creates an empty, new bit vector.
39 pub fn new() -> TagVec<T, F> {
40 TagVec {
41 tag_fields: HashMap::new(),
42 len: 0,
43 }
44 }
45
46 /// The number of elements in the TagVec
47 pub fn len(&self) -> usize { self.len }
48
49 /// Pushes a new element onto the bitvec,
50 /// where the new element is defined
51 /// as an iterator of tags(borrows of tags specifically)
52 ///
53 /// And OMG the generics on this function are
54 /// crazy
55 pub fn push<'a, I, Q>(&mut self, tags: I)
56 where I: IntoIterator<Item = &'a Q>,
57 Q: ?Sized + Hash + Eq + 'a,
58 T: From<&'a Q> + std::borrow::Borrow<Q> {
59 // Vec doesn't allocate when created, and
60 // we will rarely see unknown tags come forth,
61 // so this won't be a performance hog
62 let mut skipped_tags: Vec<T> = Vec::new();
63
64 // Add tags to existing tag fields
65 for tag in tags {
66 match self.tag_fields.get_mut(tag) {
67 Some(field) => field.push(true),
68 None => skipped_tags.push(tag.into()),
69 }
70 }
71
72 // Push false to any tag fields that this element didn't contain
73 for tag_field in self.tag_fields.values_mut() {
74 if tag_field.len() < self.len + 1 {
75 tag_field.push(false);
76 }
77 }
78
79 // Create new tag fields for tags that appeared just now
80 // This shouldn't run too often since there are fewer tags than values hopefully
81 for skipped_tag in skipped_tags {
82 let mut new_field = DynamicBitField::with_false(self.len());
83 new_field.push(true); // This is the first element to have the tag
84 self.tag_fields.insert(skipped_tag, new_field);
85 }
86
87 self.len += 1;
88 }
89
90 /// Iterates over all elements who fulfill the given expression.
91 /// The behind the scenes of this function are complete and utter
92 /// black magic code, and that code is indeed very strange.
93 /// Nonetheless, the use of this function is not strange, and in
94 /// fact quite intuitive
95 ///
96 /// ```
97 /// use tag_vec::TagVec;
98 ///
99 /// // Make it easier to construct an expression
100 /// use tag_vec::expressions::*;
101 ///
102 /// // Construct a tag_vec
103 /// let mut tag_vec: TagVec<String> = TagVec::new();
104 /// tag_vec.push(vec!["hello", "world"]);
105 /// tag_vec.push(vec!["rust", "is", "good"]);
106 /// tag_vec.push(vec!["hello", "is", "good"]);
107 /// tag_vec.push(vec!["hello", "rust"]);
108 ///
109 /// // Query something
110 /// let mut query = tag_vec.query(tag("hello"));
111 /// // The first element to contain the tag "hello" is number 0
112 /// assert_eq!(query.next(), Some(0));
113 /// // ... and so on
114 /// assert_eq!(query.next(), Some(2));
115 /// assert_eq!(query.next(), Some(3));
116 /// assert_eq!(query.next(), None); // Oops, we ran out!
117 ///
118 /// // Query something more complicated
119 /// let mut query = tag_vec.query(and(tag("rust"), tag("good")));
120 /// // Element "1" is the only element with both the "rust" and "good" tags
121 /// assert_eq!(query.next(), Some(1));
122 /// assert_eq!(query.next(), None);
123 /// ```
124 pub fn query<'a, Q>(&'a self, expr: query::Expression<'a, Q>) -> query::Query<'a, F>
125 where Q: ?Sized + Hash + Eq + 'a,
126 T: std::borrow::Borrow<Q> {
127 query::Query::create_from(self, expr)
128 }
129
130 /// Iterates over each tag of an element(an element is considered
131 /// to _be_ its tags). The iterator is unordered, so be careful.
132 /// Will panic if the index is out of bounds.
133 ///
134 /// Examples:
135 /// ```
136 /// use tag_vec::TagVec;
137 /// // It is good to give the type of the key to
138 /// // the type, as it may be difficult for the compiler
139 /// // to infer it
140 /// let mut tag_vec: TagVec<String> = TagVec::new();
141 /// tag_vec.push(vec!["hello", "world"]);
142 ///
143 /// // We should find a "hello" tag but not a "hi" tag
144 /// // in the iterator
145 /// let tags = tag_vec.iter_element(0);
146 /// assert!(tags.clone().any(|v| *v == "hello"));
147 /// assert!(!tags.clone().any(|v| *v == "hi"));
148 /// ```
149 pub fn iter_element<'a>(&'a self, index: usize) -> IterElement<'a, T, F>
150 {
151 assert!(index < self.len(), "Cannot iter over an element out of bounds");
152
153 IterElement {
154 fields: self.tag_fields.iter(),
155 element_id: index
156 }
157 }
158}
159
160/// Iterates over every tag over an element.
161/// See ``TagVec::iter_element`` for more
162/// information.
163#[derive(Clone)]
164pub struct IterElement<'a, T, F>
165 where T: Eq + Hash + Clone, F: BitField {
166 fields: std::collections::hash_map::Iter<'a, T, DynamicBitField<F>>,
167 element_id: usize,
168}
169
170impl<T: Eq + Hash + Clone, F: BitField> std::iter::FusedIterator for IterElement<'_, T, F> {}
171
172impl<'a, T: Eq + Hash + Clone, F: BitField> Iterator for IterElement<'a, T, F> {
173 type Item = &'a T;
174
175 fn next(&mut self) -> Option<&'a T> {
176 // Try to find the next field that contains this element.
177 // Once you find one, return it.
178 while let Some((key, field)) = self.fields.next() {
179 if field.get_unchecked(self.element_id) {
180 return Some(key);
181 }
182 }
183
184 None
185 }
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191
192 #[test]
193 fn pushing() {
194 let mut tags = TagVec::<String>::new();
195 assert_eq!(tags.tag_fields.len(), 0);
196 tags.push(vec!["hello", "sir"]);
197 tags.push(vec!["other", "sir"]);
198
199 // Testing implementation detail thing, not part of
200 // the API
201 assert_eq!(tags.tag_fields.len(), 3);
202
203 let tag_vec: Vec<_> = tags.iter_element(0).collect();
204 assert_eq!(tag_vec.len(), 2);
205 assert!(tag_vec.iter().any(|v| *v == "hello"));
206 assert!(tag_vec.iter().any(|v| *v == "sir"));
207 }
208
209 #[test]
210 fn extreme_queries() {
211 let mut tags = TagVec::<String, u8>::new();
212 tags.push(vec!["hi", "yuh"]);
213 tags.push(vec!["hi2", "yuh"]);
214 tags.push(vec!["hi", "yuh"]);
215 tags.push(vec!["hi", "yuh"]);
216 tags.push(vec!["hi", "yuh"]);
217 tags.push(vec!["hi", "yuh"]);
218 tags.push(vec!["hi", "yuh"]);
219 tags.push(vec!["hi", "yuh"]);
220 tags.push(vec!["hi", "yuh"]);
221 tags.push(vec!["hi", "yuh"]);
222 tags.push(vec!["hi", "yuh"]);
223 tags.push(vec!["hi", "yuh"]);
224 tags.push(vec!["hi2", "yuh"]);
225 tags.push(vec!["hi", "yuh"]);
226 tags.push(vec!["hi", "yuh"]);
227 tags.push(vec!["hi", "yuh"]);
228 tags.push(vec!["hi", "yuh"]);
229 tags.push(vec!["hi", "yuh"]);
230 tags.push(vec!["hi", "yuh"]);
231 tags.push(vec!["hi2", "yuh"]);
232 tags.push(vec!["hi", "yuh"]);
233
234 use super::expressions::*;
235 let contains: Vec<_> = tags.query(tag("hi2")).collect();
236 assert_eq!(contains.len(), 3);
237 assert_eq!(contains[0], 1);
238 assert_eq!(contains[1], 12);
239 assert_eq!(contains[2], 19);
240 }
241}