1use crate::TagVec;
2use crate::BitField;
3use std::hash::Hash;
4
5pub mod expressions {
11 use crate::query::Expression;
12 use std::hash::Hash;
13
14 pub fn tag<'a, Q>(tag: &'a Q) -> Expression<'a, Q>
16 where Q: ?Sized + Eq + Hash {
17 Expression::Tag(tag)
18 }
19
20 pub fn and<'a, Q>(a: Expression<'a, Q>, b: Expression<'a, Q>) -> Expression<'a, Q>
22 where Q: ?Sized + Eq + Hash {
23 Expression::And(Box::new(a), Box::new(b))
24 }
25
26 pub fn or<'a, Q>(a: Expression<'a, Q>, b: Expression<'a, Q>) -> Expression<'a, Q>
28 where Q: ?Sized + Eq + Hash {
29 Expression::Or(Box::new(a), Box::new(b))
30 }
31
32 pub fn not<'a, Q>(a: Expression<'a, Q>) -> Expression<'a, Q>
34 where Q: ?Sized + Eq + Hash {
35 Expression::Not(Box::new(a))
36 }
37}
38
39pub enum Expression<'a, Q> where Q: ?Sized + Hash + Eq + 'a {
41 And(Box<Expression<'a, Q>>, Box<Expression<'a, Q>>),
42 Or(Box<Expression<'a, Q>>, Box<Expression<'a, Q>>),
43 Not(Box<Expression<'a, Q>>),
44 Tag(&'a Q),
45}
46
47impl<'a, Q: ?Sized + Hash + Eq + 'a> Expression<'a, Q> {
48 fn command_size(&self) -> usize {
51 use Expression::*;
52
53 match self {
54 And(a, b) => 1 + a.command_size() + b.command_size(),
55 Or(a, b) => 1 + a.command_size() + b.command_size(),
56 Not(a) => 1 + a.command_size(),
57 Tag(_) => 1,
58 }
59 }
60
61 fn to_commands(self, tag_requests: &mut Vec<&'a Q>, commands: &mut Vec<u16>) {
63 use Expression::*;
64
65 match self {
66 And(a, b) => {
67 a.to_commands(tag_requests, commands);
68 b.to_commands(tag_requests, commands);
69 commands.push(QUERY_CMD_AND);
70 },
71 Or(a, b) => {
72 a.to_commands(tag_requests, commands);
73 b.to_commands(tag_requests, commands);
74 commands.push(QUERY_CMD_OR);
75 },
76 Not(a) => {
77 a.to_commands(tag_requests, commands);
78 commands.push(QUERY_CMD_NOT);
79 },
80 Tag(tag) => {
81 let id = tag_requests.len() as u16;
82 assert!(id < QUERY_CMD_TAG);
83 tag_requests.push(tag);
84 commands.push(id);
87 },
88 }
89 }
90}
91
92const QUERY_CMD_AND: u16 = 0xFFFF;
95const QUERY_CMD_OR: u16 = 0xFFFD;
96const QUERY_CMD_NOT: u16 = 0xFFFC;
97const QUERY_CMD_TAG: u16 = 0xFFFC; pub struct Query<'a, F>
102 where
103 F: BitField {
104 tag_data: Vec<Option<&'a [F]>>,
105 commands: Vec<u16>,
106 bit_ctr: usize,
107 total_bits: usize,
108 data: F,
109 stack: Vec<F>,
110}
111
112impl<'a, F> Query<'a, F>
113 where
114 F: BitField
115{
116 pub(crate) fn create_from<T, Q>(vec: &'a TagVec<T, F>, expr: Expression<'a, Q>)
126 -> Query<'a, F>
127 where T: Eq + Hash + Clone + std::borrow::Borrow<Q>,
128 Q: ?Sized + Eq + Hash + 'a {
129 let mut tag_requests = Vec::new();
130 let mut commands = Vec::with_capacity(expr.command_size());
131
132 expr.to_commands(&mut tag_requests, &mut commands);
133
134 let tag_data: Vec<_> = tag_requests.into_iter()
137 .map(|request| vec.tag_fields.get(request).map(|v| v.data())).collect();
138
139 Query {
140 tag_data,
141 commands,
142 bit_ctr: 0,
143 total_bits: vec.len(),
144 data: F::empty(),
145 stack: Vec::new(),
146 }
147 }
148
149 fn sloppy_next(&mut self) -> bool {
153 let local_index = self.bit_ctr % F::n_bits();
154
155 if local_index == 0 {
156 let data_index = self.bit_ctr / F::n_bits();
158
159 self.stack.clear();
162 let stack = &mut self.stack;
163 let commands = &self.commands;
164 let tag_data = &self.tag_data;
165 for cmd in commands.iter() {
166 match *cmd {
167 QUERY_CMD_AND => {
168 let a = stack.pop().unwrap();
169 let b = stack.pop().unwrap();
170 stack.push(a & b);
171 },
172 QUERY_CMD_OR => {
173 let a = stack.pop().unwrap();
174 let b = stack.pop().unwrap();
175 stack.push(a | b);
176 },
177 QUERY_CMD_NOT => {
178 let a = stack.pop().unwrap();
179 stack.push(!a);
180 },
181 tag => {
182 stack.push(tag_data[tag as usize].map_or(F::empty(), |v| v[data_index]));
184 },
185 }
186 }
187
188 self.data = stack[0];
189 }
190
191 self.bit_ctr += 1;
192 self.data.get_bit(local_index)
193 }
194}
195
196impl<'a, F> Iterator for Query<'a, F> where F: BitField {
197 type Item = usize;
198
199 fn next(&mut self) -> Option<usize> {
200 while self.bit_ctr < self.total_bits {
201 if self.sloppy_next() {
202 return Some(self.bit_ctr - 1);
205 }
206 }
207
208 None
209 }
210}