1use crate::dynamic::{BSet, DowncastTrait, DynData, LeanVec};
4use crate::time::UnitTimestamp;
5use std::collections::BTreeMap;
6use std::rc::Rc;
7use std::sync::Arc;
8use uuid::Uuid;
9
10pub trait SupportsRoaring {
18 #[inline]
21 fn supports_roaring32(&self) -> bool {
22 false
23 }
24
25 #[inline]
30 fn roaring_u32_offset(&self, _min: &Self) -> Option<u32>
31 where
32 Self: Sized,
33 {
34 None
35 }
36
37 #[inline]
40 fn roaring_u32_offset_dyn(&self, _min: &DynData) -> Option<u32> {
41 None
42 }
43
44 #[inline]
47 fn roaring_u32_offset_dyn_checked(&self, min: &DynData) -> u32 {
48 self.roaring_u32_offset_dyn(min)
49 .expect("roaring-u32 filter was selected for a key outside the planned batch range")
50 }
51}
52
53#[macro_export]
54macro_rules! never_roaring_filter {
55 ($($ty:ty),* $(,)?) => {
56 $(
57 impl $crate::utils::SupportsRoaring for $ty {}
58 )*
59 };
60}
61
62never_roaring_filter!(
65 (),
66 bool,
67 char,
68 f32,
69 f64,
70 usize,
71 isize,
72 String,
73 UnitTimestamp,
74 Uuid
75);
76
77impl SupportsRoaring for u8 {
78 #[inline]
79 fn supports_roaring32(&self) -> bool {
80 true
81 }
82
83 #[inline]
84 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
85 self.checked_sub(*min).map(u32::from)
86 }
87
88 #[inline]
89 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
90 self.roaring_u32_offset(unsafe { min.downcast::<u8>() })
92 }
93}
94
95impl SupportsRoaring for i8 {
96 #[inline]
97 fn supports_roaring32(&self) -> bool {
98 true
99 }
100
101 #[inline]
102 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
103 (*self >= *min).then_some(u32::from(self.abs_diff(*min)))
104 }
105
106 #[inline]
107 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
108 self.roaring_u32_offset(unsafe { min.downcast::<i8>() })
110 }
111}
112
113impl SupportsRoaring for u16 {
114 #[inline]
115 fn supports_roaring32(&self) -> bool {
116 true
117 }
118
119 #[inline]
120 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
121 self.checked_sub(*min).map(u32::from)
122 }
123
124 #[inline]
125 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
126 self.roaring_u32_offset(unsafe { min.downcast::<u16>() })
128 }
129}
130
131impl SupportsRoaring for i16 {
132 #[inline]
133 fn supports_roaring32(&self) -> bool {
134 true
135 }
136
137 #[inline]
138 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
139 (*self >= *min).then_some(u32::from(self.abs_diff(*min)))
140 }
141
142 #[inline]
143 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
144 self.roaring_u32_offset(unsafe { min.downcast::<i16>() })
146 }
147}
148
149impl SupportsRoaring for u32 {
150 #[inline]
151 fn supports_roaring32(&self) -> bool {
152 true
153 }
154
155 #[inline]
156 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
157 self.checked_sub(*min)
158 }
159
160 #[inline]
161 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
162 self.roaring_u32_offset(unsafe { min.downcast::<u32>() })
164 }
165}
166
167impl SupportsRoaring for i32 {
168 #[inline]
169 fn supports_roaring32(&self) -> bool {
170 true
171 }
172
173 #[inline]
174 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
175 (*self >= *min).then_some(self.abs_diff(*min))
176 }
177
178 #[inline]
179 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
180 self.roaring_u32_offset(unsafe { min.downcast::<i32>() })
182 }
183}
184
185impl SupportsRoaring for u64 {
186 #[inline]
187 fn supports_roaring32(&self) -> bool {
188 true
189 }
190
191 #[inline]
192 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
193 self.checked_sub(*min)
194 .and_then(|diff| u32::try_from(diff).ok())
195 }
196
197 #[inline]
198 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
199 self.roaring_u32_offset(unsafe { min.downcast::<u64>() })
201 }
202}
203
204impl SupportsRoaring for i64 {
205 #[inline]
206 fn supports_roaring32(&self) -> bool {
207 true
208 }
209
210 #[inline]
211 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
212 (*self >= *min)
213 .then_some(self.abs_diff(*min))
214 .and_then(|diff| diff.try_into().ok())
215 }
216
217 #[inline]
218 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
219 self.roaring_u32_offset(unsafe { min.downcast::<i64>() })
221 }
222}
223
224impl SupportsRoaring for u128 {
225 #[inline]
226 fn supports_roaring32(&self) -> bool {
227 true
228 }
229
230 #[inline]
231 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
232 self.checked_sub(*min)
233 .and_then(|diff| u32::try_from(diff).ok())
234 }
235
236 #[inline]
237 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
238 self.roaring_u32_offset(unsafe { min.downcast::<u128>() })
240 }
241}
242
243impl SupportsRoaring for i128 {
244 #[inline]
245 fn supports_roaring32(&self) -> bool {
246 true
247 }
248
249 #[inline]
250 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
251 (*self >= *min)
252 .then_some(self.abs_diff(*min))
253 .and_then(|diff| diff.try_into().ok())
254 }
255
256 #[inline]
257 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
258 self.roaring_u32_offset(unsafe { min.downcast::<i128>() })
260 }
261}
262
263impl<T> SupportsRoaring for Option<T> {}
264
265#[macro_export]
266macro_rules! never_roaring_filter_1 {
267 ($($wrapper:ident),* $(,)?) => {
268 $(
269 impl<T> $crate::utils::SupportsRoaring for $wrapper<T> {}
270 )*
271 };
272}
273
274never_roaring_filter_1!(Vec, LeanVec, BSet);
275
276#[macro_export]
277macro_rules! delegate_supports_roaring {
278 ($($wrapper:ident),* $(,)?) => {
279 $(
280 impl<T: $crate::utils::SupportsRoaring> $crate::utils::SupportsRoaring for $wrapper<T> {
281 #[inline]
282 fn supports_roaring32(&self) -> bool {
283 self.as_ref().supports_roaring32()
284 }
285
286 #[inline]
287 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
288 self.as_ref().roaring_u32_offset(min.as_ref())
289 }
290
291 #[inline]
292 fn roaring_u32_offset_dyn(&self, min: &$crate::dynamic::DynData) -> Option<u32> {
293 self.as_ref().roaring_u32_offset_dyn(min)
294 }
295
296 #[inline]
297 fn roaring_u32_offset_dyn_checked(&self, min: &$crate::dynamic::DynData) -> u32 {
298 self.as_ref().roaring_u32_offset_dyn_checked(min)
299 }
300 }
301 )*
302 };
303}
304
305delegate_supports_roaring!(Box, Rc, Arc);
306
307#[macro_export]
308macro_rules! never_roaring_filter_tuples {
309 ($($name:ident),+) => {
310 impl<$($name),+> SupportsRoaring for ($($name,)+) {}
311 };
312}
313
314never_roaring_filter_tuples!(A);
315never_roaring_filter_tuples!(A, B);
316never_roaring_filter_tuples!(A, B, C);
317never_roaring_filter_tuples!(A, B, C, D);
318never_roaring_filter_tuples!(A, B, C, D, E);
319never_roaring_filter_tuples!(A, B, C, D, E, F);
320
321impl<K, V> SupportsRoaring for BTreeMap<K, V> {}
322
323impl<T: SupportsRoaring + 'static> SupportsRoaring for crate::utils::Tup1<T> {
324 #[inline]
325 fn supports_roaring32(&self) -> bool {
326 self.0.supports_roaring32()
327 }
328
329 #[inline]
330 fn roaring_u32_offset(&self, min: &Self) -> Option<u32> {
331 self.0.roaring_u32_offset(&min.0)
332 }
333
334 #[inline]
335 fn roaring_u32_offset_dyn(&self, min: &DynData) -> Option<u32> {
336 self.roaring_u32_offset(unsafe { min.downcast::<Self>() })
338 }
339
340 #[inline]
341 fn roaring_u32_offset_dyn_checked(&self, min: &DynData) -> u32 {
342 self.roaring_u32_offset(unsafe { min.downcast::<Self>() })
344 .expect("roaring-u32 filter was selected for a key outside the planned batch range")
345 }
346}
347
348#[cfg(test)]
349mod test {
350 use super::SupportsRoaring;
351 use crate::{dynamic::DynData, utils::Tup1};
352
353 #[test]
354 fn u32_roaring_offset_boundaries() {
355 assert!(0u32.supports_roaring32());
356 assert_eq!(0u32.roaring_u32_offset(&0), Some(0));
357 assert_eq!(u32::MAX.roaring_u32_offset(&0), Some(u32::MAX));
358 assert_eq!(5u32.roaring_u32_offset(&7), None);
359
360 assert_eq!(7u32.roaring_u32_offset_dyn((&0u32) as &DynData), Some(7));
361 }
362
363 #[test]
364 fn i32_roaring_offset_boundaries() {
365 assert!(0i32.supports_roaring32());
366 assert_eq!(i32::MIN.roaring_u32_offset(&i32::MIN), Some(0));
367 assert_eq!(i32::MAX.roaring_u32_offset(&i32::MIN), Some(u32::MAX));
368 assert_eq!((-7i32).roaring_u32_offset(&-10), Some(3));
369 assert_eq!((-11i32).roaring_u32_offset(&-10), None);
370
371 assert_eq!(
372 (-7i32).roaring_u32_offset_dyn((&-10i32) as &DynData),
373 Some(3)
374 );
375 }
376
377 #[test]
378 fn u64_roaring_offset_boundaries() {
379 let min = (u64::from(u32::MAX) << 8) + 11;
380
381 assert!(min.supports_roaring32());
382 assert_eq!(min.roaring_u32_offset(&min), Some(0));
383 assert_eq!(
384 min.wrapping_add(u64::from(u32::MAX))
385 .roaring_u32_offset(&min),
386 Some(u32::MAX)
387 );
388 assert_eq!(
389 min.wrapping_add(u64::from(u32::MAX) + 1)
390 .roaring_u32_offset(&min),
391 None
392 );
393 assert_eq!(11u64.roaring_u32_offset(&(u64::MAX - 1)), None);
394
395 assert_eq!(11u64.roaring_u32_offset_dyn((&9u64) as &DynData), Some(2));
396 }
397
398 #[test]
399 fn i64_roaring_offset_boundaries() {
400 let min = -5i64;
401 let max_fitting = min + i64::from(u32::MAX);
402
403 assert!(min.supports_roaring32());
404 assert_eq!(min.roaring_u32_offset(&min), Some(0));
405 assert_eq!(max_fitting.roaring_u32_offset(&min), Some(u32::MAX));
406 assert_eq!((max_fitting + 1).roaring_u32_offset(&min), None);
407 assert_eq!((min - 1).roaring_u32_offset(&min), None);
408
409 assert_eq!(
410 (-2i64).roaring_u32_offset_dyn((&-5i64) as &DynData),
411 Some(3)
412 );
413 }
414
415 #[test]
416 fn tup1_delegates_roaring_support() {
417 assert!(Tup1(-7i32).supports_roaring32());
418 assert_eq!(
419 Tup1(-7i32).roaring_u32_offset_dyn((&Tup1(-10i32)) as &DynData),
420 Some(3)
421 );
422 }
423
424 #[test]
425 fn u8_roaring_offset_boundaries() {
426 assert!(0u8.supports_roaring32());
427 assert_eq!(0u8.roaring_u32_offset(&0), Some(0));
428 assert_eq!(u8::MAX.roaring_u32_offset(&0), Some(255));
429 assert_eq!(5u8.roaring_u32_offset(&7), None);
430
431 assert_eq!(7u8.roaring_u32_offset_dyn((&0u8) as &DynData), Some(7));
432 }
433
434 #[test]
435 fn i8_roaring_offset_boundaries() {
436 assert!(0i8.supports_roaring32());
437 assert_eq!(i8::MIN.roaring_u32_offset(&i8::MIN), Some(0));
438 assert_eq!(i8::MAX.roaring_u32_offset(&i8::MIN), Some(255));
439 assert_eq!((-7i8).roaring_u32_offset(&-10), Some(3));
440 assert_eq!((-11i8).roaring_u32_offset(&-10), None);
441
442 assert_eq!((-7i8).roaring_u32_offset_dyn((&-10i8) as &DynData), Some(3));
443 }
444
445 #[test]
446 fn u16_roaring_offset_boundaries() {
447 assert!(0u16.supports_roaring32());
448 assert_eq!(0u16.roaring_u32_offset(&0), Some(0));
449 assert_eq!(u16::MAX.roaring_u32_offset(&0), Some(65535));
450 assert_eq!(5u16.roaring_u32_offset(&7), None);
451
452 assert_eq!(7u16.roaring_u32_offset_dyn((&0u16) as &DynData), Some(7));
453 }
454
455 #[test]
456 fn i16_roaring_offset_boundaries() {
457 assert!(0i16.supports_roaring32());
458 assert_eq!(i16::MIN.roaring_u32_offset(&i16::MIN), Some(0));
459 assert_eq!(i16::MAX.roaring_u32_offset(&i16::MIN), Some(65535));
460 assert_eq!((-7i16).roaring_u32_offset(&-10), Some(3));
461 assert_eq!((-11i16).roaring_u32_offset(&-10), None);
462
463 assert_eq!(
464 (-7i16).roaring_u32_offset_dyn((&-10i16) as &DynData),
465 Some(3)
466 );
467 }
468
469 #[test]
470 fn u128_roaring_offset_boundaries() {
471 let min = u128::from(u32::MAX) << 64;
472
473 assert!(min.supports_roaring32());
474 assert_eq!(min.roaring_u32_offset(&min), Some(0));
475 assert_eq!(
476 (min + u128::from(u32::MAX)).roaring_u32_offset(&min),
477 Some(u32::MAX)
478 );
479 assert_eq!(
480 (min + u128::from(u32::MAX) + 1).roaring_u32_offset(&min),
481 None
482 );
483 assert_eq!(11u128.roaring_u32_offset(&(u128::MAX - 1)), None);
484
485 assert_eq!(11u128.roaring_u32_offset_dyn((&9u128) as &DynData), Some(2));
486 }
487
488 #[test]
489 fn i128_roaring_offset_boundaries() {
490 let min = -5i128;
491 let max_fitting = min + i128::from(u32::MAX);
492
493 assert!(min.supports_roaring32());
494 assert_eq!(min.roaring_u32_offset(&min), Some(0));
495 assert_eq!(max_fitting.roaring_u32_offset(&min), Some(u32::MAX));
496 assert_eq!((max_fitting + 1).roaring_u32_offset(&min), None);
497 assert_eq!((min - 1).roaring_u32_offset(&min), None);
498
499 assert_eq!(
500 (-2i128).roaring_u32_offset_dyn((&-5i128) as &DynData),
501 Some(3)
502 );
503 }
504
505 #[test]
506 fn unsupported_roaring_keys() {
507 assert!(!"feldera".to_string().supports_roaring32());
508 assert_eq!(
509 "feldera"
510 .to_string()
511 .roaring_u32_offset_dyn((&String::new()) as &DynData),
512 None
513 );
514 }
515}