qubit_function/comparator/rc_comparator.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! Defines the `RcComparator` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15/// An Rc-based single-threaded comparator with shared ownership.
16///
17/// `RcComparator` wraps a comparator function in an `Rc`, providing
18/// single-threaded shared ownership semantics. It is cloneable and uses
19/// `&self` in composition operations.
20///
21/// # Type Parameters
22///
23/// * `T` - The type of values being compared
24///
25/// # Examples
26///
27/// ```rust
28/// use qubit_function::comparator::{Comparator, RcComparator};
29/// use std::cmp::Ordering;
30///
31/// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
32/// let cloned = cmp.clone();
33/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
34/// assert_eq!(cloned.compare(&5, &3), Ordering::Greater);
35/// ```
36///
37/// # Author
38///
39/// Haixing Hu
40#[derive(Clone)]
41pub struct RcComparator<T> {
42 pub(super) function: Rc<dyn Fn(&T, &T) -> Ordering>,
43}
44
45impl<T> RcComparator<T> {
46 /// Creates a new `RcComparator` from a closure.
47 ///
48 /// # Parameters
49 ///
50 /// * `f` - The closure to wrap
51 ///
52 /// # Returns
53 ///
54 /// A new `RcComparator` instance.
55 ///
56 /// # Examples
57 ///
58 /// ```rust
59 /// use qubit_function::comparator::RcComparator;
60 ///
61 /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
62 /// ```
63 #[inline]
64 pub fn new<F>(f: F) -> Self
65 where
66 F: Fn(&T, &T) -> Ordering + 'static,
67 {
68 Self {
69 function: Rc::new(f),
70 }
71 }
72
73 /// Returns a comparator that imposes the reverse ordering.
74 ///
75 /// # Returns
76 ///
77 /// A new `RcComparator` that reverses the comparison order.
78 ///
79 /// # Examples
80 ///
81 /// ```rust
82 /// use qubit_function::comparator::{Comparator, RcComparator};
83 /// use std::cmp::Ordering;
84 ///
85 /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
86 /// let rev = cmp.reversed();
87 /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
88 /// assert_eq!(cmp.compare(&5, &3), Ordering::Greater); // cmp still works
89 /// ```
90 #[inline]
91 pub fn reversed(&self) -> Self
92 where
93 T: 'static,
94 {
95 let self_fn = self.function.clone();
96 RcComparator::new(move |a, b| self_fn(b, a))
97 }
98
99 /// Returns a comparator that uses this comparator first, then another
100 /// comparator if this one considers the values equal.
101 ///
102 /// # Parameters
103 ///
104 /// * `other` - The comparator to use for tie-breaking
105 ///
106 /// # Returns
107 ///
108 /// A new `RcComparator` that chains this comparator with another.
109 ///
110 /// # Examples
111 ///
112 /// ```rust
113 /// use qubit_function::comparator::{Comparator, RcComparator};
114 /// use std::cmp::Ordering;
115 ///
116 /// let cmp1 = RcComparator::new(|a: &i32, b: &i32| {
117 /// (a % 2).cmp(&(b % 2))
118 /// });
119 /// let cmp2 = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
120 /// let chained = cmp1.then_comparing(&cmp2);
121 /// assert_eq!(chained.compare(&4, &2), Ordering::Greater);
122 /// ```
123 #[inline]
124 pub fn then_comparing(&self, other: &Self) -> Self
125 where
126 T: 'static,
127 {
128 let first = self.function.clone();
129 let second = other.function.clone();
130 RcComparator::new(move |a, b| match first(a, b) {
131 Ordering::Equal => second(a, b),
132 ord => ord,
133 })
134 }
135
136 /// Returns a comparator that compares values by a key extracted by the
137 /// given function.
138 ///
139 /// # Parameters
140 ///
141 /// * `key_fn` - A function that extracts a comparable key from values
142 ///
143 /// # Returns
144 ///
145 /// A new `RcComparator` that compares by the extracted key.
146 ///
147 /// # Examples
148 ///
149 /// ```rust
150 /// use qubit_function::comparator::{Comparator, RcComparator};
151 /// use std::cmp::Ordering;
152 ///
153 /// #[derive(Debug)]
154 /// struct Person {
155 /// name: String,
156 /// age: i32,
157 /// }
158 ///
159 /// let by_age = RcComparator::comparing(|p: &Person| &p.age);
160 /// let p1 = Person { name: "Alice".to_string(), age: 30 };
161 /// let p2 = Person { name: "Bob".to_string(), age: 25 };
162 /// assert_eq!(by_age.compare(&p1, &p2), Ordering::Greater);
163 /// ```
164 #[inline]
165 pub fn comparing<K, F>(key_fn: F) -> Self
166 where
167 K: Ord,
168 F: Fn(&T) -> &K + 'static,
169 {
170 RcComparator::new(move |a, b| key_fn(a).cmp(key_fn(b)))
171 }
172
173 /// Converts this comparator into a closure.
174 ///
175 /// # Returns
176 ///
177 /// A closure that implements `Fn(&T, &T) -> Ordering`.
178 ///
179 /// # Examples
180 ///
181 /// ```rust
182 /// use qubit_function::comparator::{Comparator, RcComparator};
183 /// use std::cmp::Ordering;
184 ///
185 /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
186 /// let func = cmp.into_fn();
187 /// assert_eq!(func(&5, &3), Ordering::Greater);
188 /// ```
189 #[inline]
190 pub fn into_fn(self) -> impl Fn(&T, &T) -> Ordering {
191 move |a: &T, b: &T| (self.function)(a, b)
192 }
193}
194
195impl<T> Comparator<T> for RcComparator<T> {
196 #[inline]
197 fn compare(&self, a: &T, b: &T) -> Ordering {
198 (self.function)(a, b)
199 }
200}