1use crate::datum::DatumLower;
2use crate::{Bag, List, Tuple, Value, Variant};
3use std::cmp::Ordering;
4
5#[derive(Eq, PartialEq)]
8pub struct NullSortedValue<'a, const NULLS_FIRST: bool, T>(pub &'a T);
9
10impl<'a, const NULLS_FIRST: bool, T> PartialOrd for NullSortedValue<'a, NULLS_FIRST, T>
11where
12 T: PartialOrd,
13 NullSortedValue<'a, NULLS_FIRST, T>: Ord,
14{
15 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
16 Some(self.cmp(other))
17 }
18}
19
20impl<const NULLS_FIRST: bool> Ord for NullSortedValue<'_, NULLS_FIRST, Value> {
21 fn cmp(&self, other: &Self) -> Ordering {
22 let wrap_list = NullSortedValue::<'_, { NULLS_FIRST }, List>;
23 let wrap_tuple = NullSortedValue::<'_, { NULLS_FIRST }, Tuple>;
24 let wrap_bag = NullSortedValue::<'_, { NULLS_FIRST }, Bag>;
25 let wrap_var = NullSortedValue::<'_, { NULLS_FIRST }, Variant>;
26 let wrap_value = NullSortedValue::<'_, { NULLS_FIRST }, Value>;
27 let null_cond = |order: Ordering| {
28 if NULLS_FIRST {
29 order
30 } else {
31 order.reverse()
32 }
33 };
34
35 match (self.0, other.0) {
36 (Value::Null, Value::Null) => Ordering::Equal,
37 (Value::Missing, Value::Null) => Ordering::Equal,
38
39 (Value::Null, Value::Missing) => Ordering::Equal,
40 (Value::Null, _) => null_cond(Ordering::Less),
41 (_, Value::Null) => null_cond(Ordering::Greater),
42
43 (Value::Missing, Value::Missing) => Ordering::Equal,
44 (Value::Missing, _) => null_cond(Ordering::Less),
45 (_, Value::Missing) => null_cond(Ordering::Greater),
46
47 (Value::List(l), Value::List(r)) => wrap_list(l.as_ref()).cmp(&wrap_list(r.as_ref())),
48
49 (Value::Tuple(l), Value::Tuple(r)) => {
50 wrap_tuple(l.as_ref()).cmp(&wrap_tuple(r.as_ref()))
51 }
52
53 (Value::Bag(l), Value::Bag(r)) => wrap_bag(l.as_ref()).cmp(&wrap_bag(r.as_ref())),
54
55 (Value::Variant(l), Value::Variant(r)) => wrap_var(l).cmp(&wrap_var(r)),
56 (Value::Variant(var), _) => {
57 let l_val = var.lower().expect("variant lower");
58 wrap_value(l_val.as_ref()).cmp(other)
59 }
60 (_, Value::Variant(var)) => {
61 let r_val = var.lower().expect("variant lower");
62 self.cmp(&wrap_value(r_val.as_ref()))
63 }
64
65 (l, r) => l.cmp(r),
66 }
67 }
68}