1use std::{cmp::Ordering, fmt::Debug, num::NonZeroU32};
2
3use idx_binary::{AvltrieeSearch, IdxBinary, IdxFileAvlTriee};
4
5use crate::{Data, FieldName, RowSet};
6
7pub trait CustomSort {
8 fn compare(&self, a: NonZeroU32, b: NonZeroU32) -> Ordering;
9 fn asc(&self) -> Vec<NonZeroU32>;
10 fn desc(&self) -> Vec<NonZeroU32>;
11}
12impl Debug for dyn CustomSort {
13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14 writeln!(f, "CustomSort")?;
15 Ok(())
16 }
17}
18
19pub struct NoCustomSort {}
20
21impl CustomSort for NoCustomSort {
22 fn compare(&self, _: NonZeroU32, _: NonZeroU32) -> Ordering {
23 unreachable!()
24 }
25
26 fn asc(&self) -> Vec<NonZeroU32> {
27 unreachable!()
28 }
29
30 fn desc(&self) -> Vec<NonZeroU32> {
31 unreachable!()
32 }
33}
34
35pub enum CustomOrderKey<C: CustomSort> {
36 Serial,
37 Row,
38 TermBegin,
39 TermEnd,
40 LastUpdated,
41 Field(FieldName),
42 Custom(C),
43}
44
45pub type OrderKey = CustomOrderKey<NoCustomSort>;
46
47pub enum Order<C: CustomSort> {
48 Asc(CustomOrderKey<C>),
49 Desc(CustomOrderKey<C>),
50}
51
52impl Data {
53 pub fn sort<C: CustomSort>(&self, rows: &RowSet, orders: &[Order<C>]) -> Vec<NonZeroU32> {
55 let sub_orders = &orders[1..];
56 match &orders[0] {
57 Order::Asc(key) => self.sort_with_key(rows, key, sub_orders),
58 Order::Desc(key) => self.sort_with_key_desc(rows, key, sub_orders),
59 }
60 }
61
62 fn compare_by_key<C: CustomSort>(
65 &self,
66 key: &CustomOrderKey<C>,
67 a: NonZeroU32,
68 b: NonZeroU32,
69 desc: bool,
70 ) -> Ordering {
71 fn missing_last<T>(
72 a: Option<T>,
73 b: Option<T>,
74 desc: bool,
75 cmp: impl Fn(T, T) -> Ordering,
76 ) -> Ordering {
77 match (a, b) {
78 (Some(a), Some(b)) => {
79 if desc {
80 cmp(b, a)
81 } else {
82 cmp(a, b)
83 }
84 }
85 (Some(_), None) => Ordering::Less,
86 (None, Some(_)) => Ordering::Greater,
87 (None, None) => Ordering::Equal,
88 }
89 }
90 let index = |f: &Option<idx_binary::IdxFile<u64>>| {
91 f.as_ref().map_or(Ordering::Equal, |f| {
92 missing_last(f.value(a), f.value(b), desc, Ord::cmp)
93 })
94 };
95 match key {
96 CustomOrderKey::Serial => {
97 missing_last(self.serial.value(a), self.serial.value(b), desc, Ord::cmp)
98 }
99 CustomOrderKey::Row => missing_last(Some(a), Some(b), desc, |a, b| a.cmp(&b)),
100 CustomOrderKey::TermBegin => index(&self.term_begin),
101 CustomOrderKey::TermEnd => index(&self.term_end),
102 CustomOrderKey::LastUpdated => index(&self.last_updated),
103 CustomOrderKey::Field(name) => self.fields.get(name).map_or(Ordering::Equal, |f| {
104 missing_last(f.value(a), f.value(b), desc, IdxBinary::cmp)
105 }),
106 CustomOrderKey::Custom(custom_order) => {
107 if desc {
108 custom_order.compare(b, a)
109 } else {
110 custom_order.compare(a, b)
111 }
112 }
113 }
114 }
115
116 fn subsort<C: CustomSort>(
117 &self,
118 mut tmp: Vec<NonZeroU32>,
119 sub_orders: &[Order<C>],
120 ) -> Vec<NonZeroU32> {
121 tmp.sort_by(|a, b| {
122 for order in sub_orders {
123 let ord = match order {
124 Order::Asc(key) => self.compare_by_key(key, *a, *b, false),
125 Order::Desc(key) => self.compare_by_key(key, *a, *b, true),
126 };
127 if ord != Ordering::Equal {
128 return ord;
129 }
130 }
131 Ordering::Equal
132 });
133 tmp
134 }
135
136 fn sort_with_triee_inner<T: PartialEq, I: ?Sized, C: CustomSort>(
139 &self,
140 rows: &RowSet,
141 triee: &IdxFileAvlTriee<T, I>,
142 iter: impl Iterator<Item = NonZeroU32>,
143 sub_orders: &[Order<C>],
144 ) -> Vec<NonZeroU32> {
145 let sorted_group = |tmp: Vec<NonZeroU32>| {
146 if tmp.len() <= 1 || sub_orders.is_empty() {
147 tmp
148 } else {
149 self.subsort(tmp, sub_orders)
150 }
151 };
152
153 let mut ret = Vec::with_capacity(rows.len());
154 let mut before: Option<&T> = None;
155 let mut tmp: Vec<NonZeroU32> = Vec::new();
156 for r in iter {
157 if rows.contains(&r) {
158 let value: &T = triee.node(r).unwrap();
159 if before.is_some_and(|before| before.ne(value)) {
160 ret.extend(sorted_group(std::mem::take(&mut tmp)));
161 }
162 tmp.push(r);
163 before = Some(value);
164 }
165 }
166 ret.extend(sorted_group(tmp));
167
168 if ret.len() < rows.len() {
169 let in_index: RowSet = ret.iter().copied().collect();
170 let missing = rows
171 .iter()
172 .copied()
173 .filter(|r| !in_index.contains(r))
174 .collect();
175 ret.extend(sorted_group(missing));
176 }
177 ret
178 }
179
180 fn sort_with_triee<T: PartialEq, I: ?Sized, C: CustomSort>(
181 &self,
182 rows: &RowSet,
183 triee: &IdxFileAvlTriee<T, I>,
184 sub_orders: &[Order<C>],
185 ) -> Vec<NonZeroU32> {
186 self.sort_with_triee_inner(rows, triee, triee.iter(), sub_orders)
187 }
188
189 fn sort_with_triee_desc<T: PartialEq, I: ?Sized, C: CustomSort>(
190 &self,
191 rows: &RowSet,
192 index: &IdxFileAvlTriee<T, I>,
193 sub_orders: &[Order<C>],
194 ) -> Vec<NonZeroU32> {
195 self.sort_with_triee_inner(rows, index, index.desc_iter(), sub_orders)
196 }
197
198 fn sort_with_key<C: CustomSort>(
199 &self,
200 rows: &RowSet,
201 key: &CustomOrderKey<C>,
202 sub_orders: &[Order<C>],
203 ) -> Vec<NonZeroU32> {
204 match key {
205 CustomOrderKey::Serial => self.sort_with_triee::<u32, u32, C>(rows, &self.serial, &[]),
206 CustomOrderKey::Row => rows.iter().cloned().collect(),
207 CustomOrderKey::TermBegin => self.term_begin.as_ref().map_or_else(
208 || rows.iter().cloned().collect(),
209 |f| self.sort_with_triee(rows, f, sub_orders),
210 ),
211 CustomOrderKey::TermEnd => self.term_end.as_ref().map_or_else(
212 || rows.iter().cloned().collect(),
213 |f| self.sort_with_triee(rows, f, sub_orders),
214 ),
215 CustomOrderKey::LastUpdated => self.last_updated.as_ref().map_or_else(
216 || rows.iter().cloned().collect(),
217 |f| self.sort_with_triee(rows, f, sub_orders),
218 ),
219 CustomOrderKey::Field(name) => self.fields.get(name).map_or_else(
220 || rows.iter().cloned().collect(),
221 |f| self.sort_with_triee(rows, f.as_ref(), sub_orders),
222 ),
223 CustomOrderKey::Custom(custom_order) => custom_order.asc(),
224 }
225 }
226
227 fn sort_with_key_desc<C: CustomSort>(
228 &self,
229 rows: &RowSet,
230 key: &CustomOrderKey<C>,
231 sub_orders: &[Order<C>],
232 ) -> Vec<NonZeroU32> {
233 match key {
234 CustomOrderKey::Serial => {
235 self.sort_with_triee_desc::<u32, u32, C>(rows, &self.serial, &[])
236 }
237 CustomOrderKey::Row => rows.iter().rev().cloned().collect(),
238 CustomOrderKey::TermBegin => self.term_begin.as_ref().map_or_else(
239 || rows.iter().rev().cloned().collect(),
240 |f| self.sort_with_triee_desc(rows, f, sub_orders),
241 ),
242 CustomOrderKey::TermEnd => self.term_end.as_ref().map_or_else(
243 || rows.iter().rev().cloned().collect(),
244 |f| self.sort_with_triee_desc(rows, f, sub_orders),
245 ),
246 CustomOrderKey::LastUpdated => self.last_updated.as_ref().map_or_else(
247 || rows.iter().rev().cloned().collect(),
248 |f| self.sort_with_triee_desc(rows, f, sub_orders),
249 ),
250 CustomOrderKey::Field(name) => self.fields.get(name).map_or_else(
251 || rows.iter().rev().cloned().collect(),
252 |f| self.sort_with_triee_desc(rows, f.as_ref(), sub_orders),
253 ),
254 CustomOrderKey::Custom(custom_order) => custom_order.desc(),
255 }
256 }
257}