versatile_data/search/
result.rs

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