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}