1use std::num::NonZeroU32;
2
3use futures::future;
4use idx_binary::{AvltrieeIter, AvltrieeSearch};
5
6use crate::{Condition, CustomSort, Data, FieldName, Order, RowSet, Search};
7
8use super::{Field, Number, Term};
9
10impl<'a> Search<'a> {
11 pub async fn result(&self) -> RowSet {
12 if !self.conditions.is_empty() {
13 self.data.result(&self.conditions).await
14 } else {
15 self.data.all()
16 }
17 }
18
19 pub async fn result_with_sort<C: CustomSort>(&self, orders: Vec<Order<C>>) -> Vec<NonZeroU32> {
20 self.data.sort(&self.result().await, &orders)
21 }
22}
23
24impl Data {
25 pub async fn result_condition(&self, condition: &Condition<'_>) -> RowSet {
27 match condition {
28 Condition::Activity(condition) => {
29 if let Some(ref index) = self.activity {
30 let activity = *condition as u8;
31 index.iter_by(&activity).collect()
32 } else {
33 RowSet::default()
34 }
35 }
36 Condition::Term(condition) => self.result_term(condition),
37 Condition::Field(field_name, condition) => self.result_field(field_name, condition),
38 Condition::Row(condition) => self.result_row(condition),
39 Condition::LastUpdated(condition) => self.result_last_updated(condition),
40 Condition::Uuid(uuid) => self.result_uuid(uuid),
41 Condition::Narrow(conditions) => Box::pin(self.result(conditions)).await,
42 Condition::Wide(conditions) => future::join_all(
43 conditions
44 .iter()
45 .map(|c| Box::pin(self.result_condition(c))),
46 )
47 .await
48 .into_iter()
49 .flatten()
50 .collect(),
51 }
52 }
53
54 async fn result(&self, conditions: &[Condition<'_>]) -> RowSet {
55 if conditions.is_empty() {
56 return self.all();
57 }
58 let (mut rows, _index, fs) = future::select_all(
59 conditions
60 .iter()
61 .map(|c| Box::pin(self.result_condition(c))),
62 )
63 .await;
64 for r in future::join_all(fs).await.into_iter() {
65 rows.retain(|v| r.contains(v));
66 }
67 rows
68 }
69
70 fn result_last_updated(&self, condition: &Number) -> RowSet {
71 if let Some(ref f) = self.last_updated {
72 match condition {
73 Number::Min(min) => {
74 let min = *min as u64;
75 f.iter_from(&min).collect()
76 }
77 Number::Max(max) => {
78 let max = *max as u64;
79 f.iter_to(&max).collect()
80 }
81 Number::Range(range) => f
82 .iter_range(&(*range.start() as u64), &(*range.end() as u64))
83 .collect(),
84 Number::In(rows) => rows.iter().flat_map(|i| f.iter_by(&(*i as u64))).collect(),
85 }
86 } else {
87 RowSet::default()
88 }
89 }
90
91 fn result_uuid(&self, uuids: &[u128]) -> RowSet {
92 if let Some(ref index) = self.uuid {
93 uuids.iter().flat_map(|uuid| index.iter_by(uuid)).collect()
94 } else {
95 RowSet::default()
96 }
97 }
98 fn result_term(&self, condition: &Term) -> RowSet {
99 match condition {
100 Term::In(base) => {
101 if let Some(ref term_begin) = self.term_begin {
102 if let Some(ref term_end) = self.term_end {
103 term_begin
104 .iter_to(base)
105 .filter(|row| {
106 let end = term_end.value(*row).unwrap_or(&0);
107 *end == 0 || end > base
108 })
109 .collect()
110 } else {
111 RowSet::default()
112 }
113 } else {
114 RowSet::default()
115 }
116 }
117 Term::Future(base) => {
118 if let Some(ref index) = self.term_begin {
119 index.iter_from(base).collect()
120 } else {
121 RowSet::default()
122 }
123 }
124 Term::Past(base) => {
125 if let Some(ref index) = self.term_end {
126 index.iter_range(&1, base).collect()
127 } else {
128 RowSet::default()
129 }
130 }
131 }
132 }
133
134 fn result_row(&self, condition: &Number) -> RowSet {
135 let to_row = |i: isize| u32::try_from(i).ok().and_then(NonZeroU32::new);
136 let exists = |row: &NonZeroU32| self.serial.node(*row).is_some();
137 match condition {
138 Number::Min(min) => self
139 .serial
140 .iter()
141 .filter(|i| i.get() as isize >= *min)
142 .collect(),
143 Number::Max(max) => self
144 .serial
145 .iter()
146 .filter(|i| i.get() as isize <= *max)
147 .collect(),
148 Number::Range(range) => {
149 let start = (*range.start()).max(1);
150 let end = (*range.end()).min(self.serial.rows_count() as isize);
151 (start..=end).filter_map(to_row).filter(exists).collect()
152 }
153 Number::In(rows) => rows
154 .iter()
155 .filter_map(|i| to_row(*i))
156 .filter(exists)
157 .collect(),
158 }
159 }
160
161 pub fn result_field(&self, name: &FieldName, condition: &Field) -> RowSet {
162 if let Some(field) = self.fields.get(name) {
163 match condition {
164 Field::Match(v) => AvltrieeIter::by(field, v).collect(),
165 Field::Min(min) => AvltrieeIter::from_asc(field, min).collect(),
166 Field::Max(max) => AvltrieeIter::to_asc(field, max).collect(),
167 Field::Range(min, max) => AvltrieeIter::range_asc(field, min, max).collect(),
168 Field::Forward(cont) => Self::result_field_sub(field, cont, Self::forward),
169 Field::Partial(cont) => Self::result_field_sub(field, cont, Self::partial),
170 Field::Backward(cont) => Self::result_field_sub(field, cont, Self::backward),
171 Field::ValueForward(cont) => {
172 Self::result_field_sub(field, cont, Self::value_forward)
173 }
174 Field::ValuePartial(cont) => {
175 Self::result_field_sub(field, cont, Self::value_partial)
176 }
177 Field::ValueBackward(cont) => {
178 Self::result_field_sub(field, cont, Self::value_backward)
179 }
180 }
181 } else {
182 RowSet::default()
183 }
184 }
185
186 fn result_field_sub(
187 field: &crate::Field,
188 cont: &str,
189 func: fn(row: NonZeroU32, field: &crate::Field, cont: &str) -> (NonZeroU32, bool),
190 ) -> RowSet {
191 field
192 .as_ref()
193 .iter()
194 .map(|row| func(row, field, cont))
195 .filter_map(|(v, b)| b.then_some(v))
196 .collect()
197 }
198
199 fn forward(row: NonZeroU32, field: &crate::Field, cont: &str) -> (NonZeroU32, bool) {
200 (
201 row,
202 field
203 .value(row)
204 .is_some_and(|bytes| bytes.starts_with(cont.as_bytes())),
205 )
206 }
207
208 fn partial(row: NonZeroU32, field: &crate::Field, cont: &str) -> (NonZeroU32, bool) {
209 (
210 row,
211 field.value(row).is_some_and(|bytes| {
212 let len = cont.len();
213 len <= bytes.len() && {
214 let cont_bytes = cont.as_bytes();
215 bytes
216 .windows(len)
217 .position(|window| window == cont_bytes)
218 .is_some()
219 }
220 }),
221 )
222 }
223
224 fn backward(row: NonZeroU32, field: &crate::Field, cont: &str) -> (NonZeroU32, bool) {
225 (
226 row,
227 field
228 .value(row)
229 .is_some_and(|bytes| bytes.ends_with(cont.as_bytes())),
230 )
231 }
232
233 fn value_forward(row: NonZeroU32, field: &crate::Field, cont: &str) -> (NonZeroU32, bool) {
234 (
235 row,
236 field
237 .value(row)
238 .is_some_and(|bytes| cont.as_bytes().starts_with(bytes)),
239 )
240 }
241
242 fn value_partial(row: NonZeroU32, field: &crate::Field, cont: &str) -> (NonZeroU32, bool) {
243 (
244 row,
245 field.value(row).is_some_and(|bytes| {
246 cont.as_bytes()
247 .windows(bytes.len())
248 .position(|window| window == bytes)
249 .is_some()
250 }),
251 )
252 }
253
254 fn value_backward(row: NonZeroU32, field: &crate::Field, cont: &str) -> (NonZeroU32, bool) {
255 (
256 row,
257 field
258 .value(row)
259 .is_some_and(|bytes| cont.as_bytes().ends_with(bytes)),
260 )
261 }
262}