Skip to main content

icydb_core/value/ops/
ordering.rs

1//! Module: value::ops::ordering
2//!
3//! Responsibility: ordering helpers that are behavioral rather than identity data.
4//! Does not own: canonical variant rank/tag definitions.
5//! Boundary: map-entry and strict-order helpers shared by runtime consumers.
6
7use crate::value::{Value, compare, ops::numeric, semantics};
8use std::cmp::Ordering;
9
10/// Total canonical comparator for one map entry `(key, value)`.
11#[must_use]
12pub fn canonical_cmp_map_entry(
13    left_key: &Value,
14    left_value: &Value,
15    right_key: &Value,
16    right_value: &Value,
17) -> Ordering {
18    Value::canonical_cmp_key(left_key, right_key)
19        .then_with(|| Value::canonical_cmp(left_value, right_value))
20}
21
22/// Build one borrowed canonical map-entry order for hashing and
23/// fingerprint-adjacent encoding surfaces.
24#[must_use]
25pub fn ordered_map_entries(entries: &[(Value, Value)]) -> Vec<&(Value, Value)> {
26    let mut ordered = entries.iter().collect::<Vec<_>>();
27    ordered.sort_by(|left, right| canonical_cmp_map_entry(&left.0, &left.1, &right.0, &right.1));
28
29    ordered
30}
31
32/// Strict comparator for identical orderable variants.
33#[must_use]
34pub(crate) fn strict_order_cmp(left: &Value, right: &Value) -> Option<Ordering> {
35    compare::strict_order_cmp(left, right)
36}
37
38/// Compare two values for projection-style equality.
39#[must_use]
40pub(crate) fn eq(left: &Value, right: &Value) -> Option<bool> {
41    let numeric_widen_enabled =
42        semantics::supports_numeric_coercion(left) || semantics::supports_numeric_coercion(right);
43    if numeric_widen_enabled {
44        return numeric::compare_decimal_order(left, right)
45            .map(|ordering| ordering == Ordering::Equal);
46    }
47
48    Some(left == right)
49}
50
51/// Compare two values for projection-style inequality.
52#[must_use]
53pub(crate) fn ne(left: &Value, right: &Value) -> Option<bool> {
54    eq(left, right).map(|equal| !equal)
55}
56
57/// Compare two values under projection-style ordering semantics.
58#[must_use]
59pub(crate) fn order(left: &Value, right: &Value) -> Option<Ordering> {
60    let numeric_widen_enabled =
61        semantics::supports_numeric_coercion(left) || semantics::supports_numeric_coercion(right);
62    if numeric_widen_enabled {
63        return numeric::compare_decimal_order(left, right);
64    }
65
66    strict_order_cmp(left, right)
67}
68
69/// Return whether `left < right` under projection-style ordering semantics.
70#[must_use]
71pub(crate) fn lt(left: &Value, right: &Value) -> Option<bool> {
72    order(left, right).map(Ordering::is_lt)
73}
74
75/// Return whether `left <= right` under projection-style ordering semantics.
76#[must_use]
77pub(crate) fn lte(left: &Value, right: &Value) -> Option<bool> {
78    order(left, right).map(Ordering::is_le)
79}
80
81/// Return whether `left > right` under projection-style ordering semantics.
82#[must_use]
83pub(crate) fn gt(left: &Value, right: &Value) -> Option<bool> {
84    order(left, right).map(Ordering::is_gt)
85}
86
87/// Return whether `left >= right` under projection-style ordering semantics.
88#[must_use]
89pub(crate) fn gte(left: &Value, right: &Value) -> Option<bool> {
90    order(left, right).map(Ordering::is_ge)
91}
92
93impl Value {
94    /// Total canonical comparator for one map entry `(key, value)`.
95    ///
96    /// This keeps map-entry ordering aligned across normalization, hashing,
97    /// and fingerprint-adjacent surfaces.
98    #[must_use]
99    pub(crate) fn canonical_cmp_map_entry(
100        left_key: &Self,
101        left_value: &Self,
102        right_key: &Self,
103        right_value: &Self,
104    ) -> Ordering {
105        canonical_cmp_map_entry(left_key, left_value, right_key, right_value)
106    }
107
108    /// Build one borrowed canonical map-entry order for hashing and
109    /// fingerprint-adjacent encoding surfaces.
110    #[must_use]
111    pub(crate) fn ordered_map_entries(entries: &[(Self, Self)]) -> Vec<&(Self, Self)> {
112        ordered_map_entries(entries)
113    }
114
115    /// Strict comparator for identical orderable variants.
116    ///
117    /// Returns `None` for mismatched or non-orderable variants.
118    #[must_use]
119    pub(crate) fn strict_order_cmp(left: &Self, right: &Self) -> Option<Ordering> {
120        strict_order_cmp(left, right)
121    }
122}