risingwave_common/types/
ordered.rs

1// Copyright 2025 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! `ScalarImpl` and `Datum` wrappers that implement `PartialOrd` and `Ord` with default order type.
16
17use std::cmp::Ordering;
18use std::ops::Deref;
19
20use risingwave_common_estimate_size::EstimateSize;
21
22use crate::dispatch_scalar_ref_variants;
23use crate::types::{Datum, DatumRef, ScalarImpl, ScalarRefImpl};
24use crate::util::sort_util::{OrderType, cmp_datum, partial_cmp_datum};
25
26pub fn default_partial_cmp_scalar_ref_impl(
27    lhs: ScalarRefImpl<'_>,
28    rhs: ScalarRefImpl<'_>,
29) -> Option<Ordering> {
30    dispatch_scalar_ref_variants!(lhs, lhs, [S = ScalarRef], {
31        let rhs: S<'_> = rhs.try_into().ok()?;
32        #[allow(clippy::needless_borrow)] // false positive
33        Some(lhs.cmp(&rhs))
34    })
35}
36
37pub trait DefaultPartialOrd: PartialEq {
38    fn default_partial_cmp(&self, other: &Self) -> Option<Ordering>;
39}
40
41/// Variant of [`Ord`] that compares with default order.
42pub trait DefaultOrd: DefaultPartialOrd + Eq {
43    fn default_cmp(&self, other: &Self) -> Ordering;
44}
45
46impl DefaultPartialOrd for ScalarImpl {
47    fn default_partial_cmp(&self, other: &Self) -> Option<Ordering> {
48        self.as_scalar_ref_impl()
49            .default_partial_cmp(&other.as_scalar_ref_impl())
50    }
51}
52
53impl DefaultOrd for ScalarImpl {
54    fn default_cmp(&self, other: &Self) -> Ordering {
55        self.as_scalar_ref_impl()
56            .default_cmp(&other.as_scalar_ref_impl())
57    }
58}
59
60impl DefaultPartialOrd for ScalarRefImpl<'_> {
61    fn default_partial_cmp(&self, other: &Self) -> Option<Ordering> {
62        default_partial_cmp_scalar_ref_impl(*self, *other)
63    }
64}
65
66impl DefaultOrd for ScalarRefImpl<'_> {
67    fn default_cmp(&self, other: &Self) -> Ordering {
68        self.default_partial_cmp(other)
69            .unwrap_or_else(|| panic!("cannot compare {self:?} with {other:?}"))
70    }
71}
72
73impl DefaultPartialOrd for Datum {
74    fn default_partial_cmp(&self, other: &Self) -> Option<Ordering> {
75        partial_cmp_datum(self, other, OrderType::default())
76    }
77}
78
79impl DefaultOrd for Datum {
80    fn default_cmp(&self, other: &Self) -> Ordering {
81        cmp_datum(self, other, OrderType::default())
82    }
83}
84
85impl DefaultPartialOrd for DatumRef<'_> {
86    fn default_partial_cmp(&self, other: &Self) -> Option<Ordering> {
87        partial_cmp_datum(*self, *other, OrderType::default())
88    }
89}
90
91impl DefaultOrd for DatumRef<'_> {
92    fn default_cmp(&self, other: &Self) -> Ordering {
93        cmp_datum(*self, *other, OrderType::default())
94    }
95}
96
97/// Wrapper that delegates [`PartialOrd`] and [`Ord`] to the [`DefaultPartialOrd`] and
98/// [`DefaultOrd`] implementations of inner type.
99#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
100pub struct DefaultOrdered<T: DefaultOrd>(pub T);
101
102impl<T: DefaultOrd + EstimateSize> EstimateSize for DefaultOrdered<T> {
103    fn estimated_heap_size(&self) -> usize {
104        self.0.estimated_heap_size()
105    }
106}
107
108impl<T: DefaultOrd> DefaultOrdered<T> {
109    pub fn new(inner: T) -> Self {
110        Self(inner)
111    }
112
113    pub fn into_inner(self) -> T {
114        self.0
115    }
116
117    pub fn as_inner(&self) -> &T {
118        &self.0
119    }
120}
121
122impl<T: DefaultOrd> Deref for DefaultOrdered<T> {
123    type Target = T;
124
125    fn deref(&self) -> &Self::Target {
126        self.as_inner()
127    }
128}
129
130impl<T: DefaultOrd> From<T> for DefaultOrdered<T> {
131    fn from(inner: T) -> Self {
132        Self::new(inner)
133    }
134}
135
136#[allow(clippy::non_canonical_partial_ord_impl)]
137impl<T: DefaultOrd> PartialOrd for DefaultOrdered<T> {
138    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
139        self.0.default_partial_cmp(other.as_inner())
140    }
141}
142
143impl<T: DefaultOrd> Ord for DefaultOrdered<T> {
144    fn cmp(&self, other: &Self) -> Ordering {
145        self.0.default_cmp(other.as_inner())
146    }
147}