qubit_function/comparator.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # Comparator Abstraction
10//!
11//! Provides a Rust implementation similar to Java's `Comparator` interface
12//! for comparison operations and chaining.
13//!
14//! ## Design Overview
15//!
16//! This module adopts the **Trait + Multiple Implementations** design
17//! pattern, which is the most flexible and elegant approach for
18//! implementing comparators in Rust. It achieves a perfect balance
19//! between semantic clarity, type safety, and API flexibility.
20//!
21//! ### Core Components
22//!
23//! 1. **`Comparator<T>` trait**: A minimalist unified interface that only
24//! defines the core `compare` method and type conversion methods
25//! (`into_*`). It does NOT include chaining methods like
26//! `then_comparing`, etc.
27//!
28//! 2. **Three Concrete Struct Implementations**:
29//! - [`BoxComparator<T>`]: Box-based single ownership implementation
30//! for one-time use scenarios
31//! - [`ArcComparator<T>`]: Arc-based thread-safe shared ownership
32//! implementation for multi-threaded scenarios
33//! - [`RcComparator<T>`]: Rc-based single-threaded shared ownership
34//! implementation for single-threaded reuse
35//!
36//! 3. **Specialized Composition Methods**: Each struct implements its own
37//! inherent methods (`reversed`, `then_comparing`, etc.) that return
38//! the same concrete type, preserving their specific characteristics
39//! (e.g., `ArcComparator` compositions remain `ArcComparator` and stay
40//! cloneable and thread-safe).
41//!
42//! 4. **Extension Trait for Closures**: The `FnComparatorOps<T>`
43//! extension trait provides composition methods for all closures and
44//! function pointers, returning `BoxComparator<T>` to initiate method
45//! chaining.
46//!
47//! 5. **Unified Trait Implementation**: All closures and the three
48//! structs implement the `Comparator<T>` trait, enabling them to be
49//! handled uniformly by generic functions.
50//!
51//! ## Ownership Model Coverage
52//!
53//! The three implementations correspond to three typical ownership
54//! scenarios:
55//!
56//! | Type | Ownership | Clonable | Thread-Safe | API | Use Case |
57//! |:-----|:----------|:---------|:------------|:----|:---------|
58//! | [`BoxComparator`] | Single | ❌ | ❌ | consumes `self` | One-time |
59//! | [`ArcComparator`] | Shared | ✅ | ✅ | borrows `&self` | Multi-thread |
60//! | [`RcComparator`] | Shared | ✅ | ❌ | borrows `&self` | Single-thread |
61//!
62//! ## Key Design Advantages
63//!
64//! ### 1. Type Preservation through Specialization
65//!
66//! By implementing composition methods on concrete structs rather than in
67//! the trait, each type maintains its specific characteristics through
68//! composition:
69//!
70//! ```rust
71//! use qubit_function::comparator::{Comparator, ArcComparator};
72//! use std::cmp::Ordering;
73//!
74//! let arc_cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
75//! let another = ArcComparator::new(|a: &i32, b: &i32| b.cmp(a));
76//!
77//! // Composition returns ArcComparator, preserving clonability and
78//! // thread-safety
79//! let combined = arc_cmp.then_comparing(&another);
80//! let cloned = combined.clone(); // ✅ Still cloneable
81//!
82//! // Original comparators remain usable
83//! assert_eq!(arc_cmp.compare(&5, &3), Ordering::Greater);
84//! ```
85//!
86//! ### 2. Elegant API without Explicit Cloning
87//!
88//! `ArcComparator` and `RcComparator` use `&self` in their composition
89//! methods, providing a natural experience without requiring explicit
90//! `.clone()` calls:
91//!
92//! ```rust
93//! use qubit_function::comparator::{Comparator, ArcComparator};
94//!
95//! let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
96//!
97//! // No need for explicit clone()
98//! let reversed = cmp.reversed();
99//! let chained = cmp.then_comparing(&ArcComparator::new(|a, b| b.cmp(a)));
100//!
101//! // cmp is still available
102//! cmp.compare(&1, &2);
103//! ```
104//!
105//! ### 3. Efficient Closure Composition
106//!
107//! The `FnComparatorOps` extension trait allows direct composition on
108//! closures:
109//!
110//! ```rust
111//! use qubit_function::comparator::{Comparator, FnComparatorOps};
112//! use std::cmp::Ordering;
113//!
114//! let cmp = (|a: &i32, b: &i32| a.cmp(b))
115//! .reversed()
116//! .then_comparing(|a: &i32, b: &i32| b.cmp(a));
117//!
118//! assert_eq!(cmp.compare(&5, &3), Ordering::Less);
119//! ```
120//!
121//! ## Usage Examples
122//!
123//! ### Basic Comparison
124//!
125//! ```rust
126//! use qubit_function::comparator::{Comparator, BoxComparator};
127//! use std::cmp::Ordering;
128//!
129//! let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
130//! assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
131//! ```
132//!
133//! ### Reversed Comparison
134//!
135//! ```rust
136//! use qubit_function::comparator::{Comparator, BoxComparator};
137//! use std::cmp::Ordering;
138//!
139//! let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
140//! let rev = cmp.reversed();
141//! assert_eq!(rev.compare(&5, &3), Ordering::Less);
142//! ```
143//!
144//! ### Chained Comparison
145//!
146//! ```rust
147//! use qubit_function::comparator::{Comparator, BoxComparator};
148//! use std::cmp::Ordering;
149//!
150//! #[derive(Debug)]
151//! struct Person {
152//! name: String,
153//! age: i32,
154//! }
155//!
156//! let by_name = BoxComparator::new(|a: &Person, b: &Person| {
157//! a.name.cmp(&b.name)
158//! });
159//! let by_age = BoxComparator::new(|a: &Person, b: &Person| {
160//! a.age.cmp(&b.age)
161//! });
162//! let cmp = by_name.then_comparing(by_age);
163//!
164//! let p1 = Person { name: "Alice".to_string(), age: 30 };
165//! let p2 = Person { name: "Alice".to_string(), age: 25 };
166//! assert_eq!(cmp.compare(&p1, &p2), Ordering::Greater);
167//! ```
168//!
169//! ## Author
170//!
171//! Haixing Hu
172use std::cmp::Ordering;
173use std::rc::Rc;
174use std::sync::Arc;
175
176// ==========================================================================
177// Type Aliases
178// ==========================================================================
179
180/// A trait for comparison operations.
181///
182/// This trait defines the core comparison operation and conversion methods.
183/// It does NOT include composition methods like `reversed` or
184/// `then_comparing` to maintain a clean separation between the trait
185/// interface and specialized implementations.
186///
187/// # Type Parameters
188///
189/// * `T` - The type of values being compared
190///
191/// # Examples
192///
193/// ```rust
194/// use qubit_function::comparator::{Comparator, BoxComparator};
195/// use std::cmp::Ordering;
196///
197/// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
198/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
199/// ```
200///
201/// # Author
202///
203/// Haixing Hu
204pub trait Comparator<T> {
205 /// Compares two values and returns an ordering.
206 ///
207 /// # Parameters
208 ///
209 /// * `a` - The first value to compare
210 /// * `b` - The second value to compare
211 ///
212 /// # Returns
213 ///
214 /// An `Ordering` indicating whether `a` is less than, equal to, or
215 /// greater than `b`.
216 ///
217 /// # Examples
218 ///
219 /// ```rust
220 /// use qubit_function::comparator::{Comparator, BoxComparator};
221 /// use std::cmp::Ordering;
222 ///
223 /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
224 /// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
225 /// assert_eq!(cmp.compare(&3, &5), Ordering::Less);
226 /// assert_eq!(cmp.compare(&5, &5), Ordering::Equal);
227 /// ```
228 fn compare(&self, a: &T, b: &T) -> Ordering;
229
230 /// Converts this comparator into a `BoxComparator`.
231 ///
232 /// # Returns
233 ///
234 /// A new `BoxComparator` wrapping this comparator.
235 ///
236 /// # Examples
237 ///
238 /// ```rust
239 /// use qubit_function::comparator::{Comparator, BoxComparator};
240 ///
241 /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
242 /// let boxed = cmp.into_box();
243 /// ```
244 #[inline]
245 fn into_box(self) -> BoxComparator<T>
246 where
247 Self: Sized + 'static,
248 T: 'static,
249 {
250 BoxComparator::new(move |a, b| self.compare(a, b))
251 }
252
253 /// Converts this comparator into an `ArcComparator`.
254 ///
255 /// # Returns
256 ///
257 /// A new `ArcComparator` wrapping this comparator.
258 ///
259 /// # Examples
260 ///
261 /// ```rust
262 /// use qubit_function::comparator::{Comparator, ArcComparator};
263 ///
264 /// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
265 /// let arc = cmp.into_arc();
266 /// ```
267 #[inline]
268 fn into_arc(self) -> ArcComparator<T>
269 where
270 Self: Sized + Send + Sync + 'static,
271 T: 'static,
272 {
273 ArcComparator::new(move |a, b| self.compare(a, b))
274 }
275
276 /// Converts this comparator into an `RcComparator`.
277 ///
278 /// # Returns
279 ///
280 /// A new `RcComparator` wrapping this comparator.
281 ///
282 /// # Examples
283 ///
284 /// ```rust
285 /// use qubit_function::comparator::{Comparator, RcComparator};
286 ///
287 /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
288 /// let rc = cmp.into_rc();
289 /// ```
290 #[inline]
291 fn into_rc(self) -> RcComparator<T>
292 where
293 Self: Sized + 'static,
294 T: 'static,
295 {
296 RcComparator::new(move |a, b| self.compare(a, b))
297 }
298
299 /// Converts this comparator into a closure that implements
300 /// `Fn(&T, &T) -> Ordering`.
301 ///
302 /// This method consumes the comparator and returns a closure that
303 /// can be used anywhere a function or closure is expected.
304 ///
305 /// # Returns
306 ///
307 /// An implementation that can be called as `Fn(&T, &T) -> Ordering`.
308 ///
309 /// # Examples
310 ///
311 /// ```rust
312 /// use qubit_function::comparator::{Comparator, BoxComparator};
313 /// use std::cmp::Ordering;
314 ///
315 /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
316 /// let func = cmp.into_fn();
317 /// assert_eq!(func(&5, &3), Ordering::Greater);
318 /// ```
319 #[inline]
320 fn into_fn(self) -> impl Fn(&T, &T) -> Ordering
321 where
322 Self: Sized + 'static,
323 {
324 move |a: &T, b: &T| self.compare(a, b)
325 }
326}
327
328/// Blanket implementation of `Comparator` for all closures and function
329/// pointers.
330///
331/// This allows any closure or function with the signature
332/// `Fn(&T, &T) -> Ordering` to be used as a comparator.
333///
334/// # Examples
335///
336/// ```rust
337/// use qubit_function::comparator::Comparator;
338/// use std::cmp::Ordering;
339///
340/// let cmp = |a: &i32, b: &i32| a.cmp(b);
341/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
342/// ```
343impl<T, F> Comparator<T> for F
344where
345 F: Fn(&T, &T) -> Ordering,
346{
347 #[inline]
348 fn compare(&self, a: &T, b: &T) -> Ordering {
349 self(a, b)
350 }
351}
352
353/// A boxed comparator with single ownership.
354///
355/// `BoxComparator` wraps a comparator function in a `Box`, providing single
356/// ownership semantics. It is not cloneable and consumes `self` in
357/// composition operations.
358///
359/// # Type Parameters
360///
361/// * `T` - The type of values being compared
362///
363/// # Examples
364///
365/// ```rust
366/// use qubit_function::comparator::{Comparator, BoxComparator};
367/// use std::cmp::Ordering;
368///
369/// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
370/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
371/// ```
372///
373/// # Author
374///
375/// Haixing Hu
376pub struct BoxComparator<T> {
377 function: Box<dyn Fn(&T, &T) -> Ordering>,
378}
379
380impl<T> BoxComparator<T> {
381 /// Creates a new `BoxComparator` from a closure.
382 ///
383 /// # Parameters
384 ///
385 /// * `f` - The closure to wrap
386 ///
387 /// # Returns
388 ///
389 /// A new `BoxComparator` instance.
390 ///
391 /// # Examples
392 ///
393 /// ```rust
394 /// use qubit_function::comparator::BoxComparator;
395 ///
396 /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
397 /// ```
398 #[inline]
399 pub fn new<F>(f: F) -> Self
400 where
401 F: Fn(&T, &T) -> Ordering + 'static,
402 {
403 Self {
404 function: Box::new(f),
405 }
406 }
407
408 /// Returns a comparator that imposes the reverse ordering.
409 ///
410 /// # Returns
411 ///
412 /// A new `BoxComparator` that reverses the comparison order.
413 ///
414 /// # Examples
415 ///
416 /// ```rust
417 /// use qubit_function::comparator::{Comparator, BoxComparator};
418 /// use std::cmp::Ordering;
419 ///
420 /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
421 /// let rev = cmp.reversed();
422 /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
423 /// ```
424 #[inline]
425 pub fn reversed(self) -> Self
426 where
427 T: 'static,
428 {
429 BoxComparator::new(move |a, b| (self.function)(b, a))
430 }
431
432 /// Returns a comparator that uses this comparator first, then another
433 /// comparator if this one considers the values equal.
434 ///
435 /// # Parameters
436 ///
437 /// * `other` - The comparator to use for tie-breaking. **Note: This
438 /// parameter is passed by value and will transfer ownership.** If you
439 /// need to preserve the original comparator, clone it first (if it
440 /// implements `Clone`). Can be:
441 /// - A `BoxComparator<T>`
442 /// - An `RcComparator<T>`
443 /// - An `ArcComparator<T>`
444 /// - Any type implementing `Comparator<T>`
445 ///
446 /// # Returns
447 ///
448 /// A new `BoxComparator` that chains this comparator with another.
449 ///
450 /// # Examples
451 ///
452 /// ```rust
453 /// use qubit_function::comparator::{Comparator, BoxComparator};
454 /// use std::cmp::Ordering;
455 ///
456 /// #[derive(Debug)]
457 /// struct Person {
458 /// name: String,
459 /// age: i32,
460 /// }
461 ///
462 /// let by_name = BoxComparator::new(|a: &Person, b: &Person| {
463 /// a.name.cmp(&b.name)
464 /// });
465 /// let by_age = BoxComparator::new(|a: &Person, b: &Person| {
466 /// a.age.cmp(&b.age)
467 /// });
468 ///
469 /// // by_age is moved here
470 /// let cmp = by_name.then_comparing(by_age);
471 ///
472 /// let p1 = Person { name: "Alice".to_string(), age: 30 };
473 /// let p2 = Person { name: "Alice".to_string(), age: 25 };
474 /// assert_eq!(cmp.compare(&p1, &p2), Ordering::Greater);
475 /// // by_age.compare(&p1, &p2); // Would not compile - moved
476 /// ```
477 #[inline]
478 pub fn then_comparing(self, other: Self) -> Self
479 where
480 T: 'static,
481 {
482 BoxComparator::new(move |a, b| match (self.function)(a, b) {
483 Ordering::Equal => (other.function)(a, b),
484 ord => ord,
485 })
486 }
487
488 /// Returns a comparator that compares values by a key extracted by the
489 /// given function.
490 ///
491 /// # Parameters
492 ///
493 /// * `key_fn` - A function that extracts a comparable key from values
494 ///
495 /// # Returns
496 ///
497 /// A new `BoxComparator` that compares by the extracted key.
498 ///
499 /// # Examples
500 ///
501 /// ```rust
502 /// use qubit_function::comparator::{Comparator, BoxComparator};
503 /// use std::cmp::Ordering;
504 ///
505 /// #[derive(Debug)]
506 /// struct Person {
507 /// name: String,
508 /// age: i32,
509 /// }
510 ///
511 /// let by_age = BoxComparator::comparing(|p: &Person| &p.age);
512 /// let p1 = Person { name: "Alice".to_string(), age: 30 };
513 /// let p2 = Person { name: "Bob".to_string(), age: 25 };
514 /// assert_eq!(by_age.compare(&p1, &p2), Ordering::Greater);
515 /// ```
516 #[inline]
517 pub fn comparing<K, F>(key_fn: F) -> Self
518 where
519 K: Ord,
520 F: Fn(&T) -> &K + 'static,
521 {
522 BoxComparator::new(move |a: &T, b: &T| key_fn(a).cmp(key_fn(b)))
523 }
524
525 /// Converts this comparator into a closure.
526 ///
527 /// # Returns
528 ///
529 /// A closure that implements `Fn(&T, &T) -> Ordering`.
530 ///
531 /// # Examples
532 ///
533 /// ```rust
534 /// use qubit_function::comparator::{Comparator, BoxComparator};
535 /// use std::cmp::Ordering;
536 ///
537 /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
538 /// let func = cmp.into_fn();
539 /// assert_eq!(func(&5, &3), Ordering::Greater);
540 /// ```
541 #[inline]
542 pub fn into_fn(self) -> impl Fn(&T, &T) -> Ordering {
543 move |a: &T, b: &T| (self.function)(a, b)
544 }
545}
546
547impl<T> Comparator<T> for BoxComparator<T> {
548 #[inline]
549 fn compare(&self, a: &T, b: &T) -> Ordering {
550 (self.function)(a, b)
551 }
552}
553
554/// An Arc-based thread-safe comparator with shared ownership.
555///
556/// `ArcComparator` wraps a comparator function in an `Arc`, providing
557/// thread-safe shared ownership semantics. It is cloneable and uses `&self`
558/// in composition operations.
559///
560/// # Type Parameters
561///
562/// * `T` - The type of values being compared
563///
564/// # Examples
565///
566/// ```rust
567/// use qubit_function::comparator::{Comparator, ArcComparator};
568/// use std::cmp::Ordering;
569///
570/// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
571/// let cloned = cmp.clone();
572/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
573/// assert_eq!(cloned.compare(&5, &3), Ordering::Greater);
574/// ```
575///
576/// # Author
577///
578/// Haixing Hu
579#[derive(Clone)]
580pub struct ArcComparator<T> {
581 function: Arc<dyn Fn(&T, &T) -> Ordering + Send + Sync>,
582}
583
584impl<T> ArcComparator<T> {
585 /// Creates a new `ArcComparator` from a closure.
586 ///
587 /// # Parameters
588 ///
589 /// * `f` - The closure to wrap
590 ///
591 /// # Returns
592 ///
593 /// A new `ArcComparator` instance.
594 ///
595 /// # Examples
596 ///
597 /// ```rust
598 /// use qubit_function::comparator::ArcComparator;
599 ///
600 /// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
601 /// ```
602 #[inline]
603 pub fn new<F>(f: F) -> Self
604 where
605 F: Fn(&T, &T) -> Ordering + Send + Sync + 'static,
606 {
607 Self {
608 function: Arc::new(f),
609 }
610 }
611
612 /// Returns a comparator that imposes the reverse ordering.
613 ///
614 /// # Returns
615 ///
616 /// A new `ArcComparator` that reverses the comparison order.
617 ///
618 /// # Examples
619 ///
620 /// ```rust
621 /// use qubit_function::comparator::{Comparator, ArcComparator};
622 /// use std::cmp::Ordering;
623 ///
624 /// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
625 /// let rev = cmp.reversed();
626 /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
627 /// assert_eq!(cmp.compare(&5, &3), Ordering::Greater); // cmp still works
628 /// ```
629 #[inline]
630 pub fn reversed(&self) -> Self
631 where
632 T: 'static,
633 {
634 let self_fn = self.function.clone();
635 ArcComparator::new(move |a, b| self_fn(b, a))
636 }
637
638 /// Returns a comparator that uses this comparator first, then another
639 /// comparator if this one considers the values equal.
640 ///
641 /// # Parameters
642 ///
643 /// * `other` - The comparator to use for tie-breaking
644 ///
645 /// # Returns
646 ///
647 /// A new `ArcComparator` that chains this comparator with another.
648 ///
649 /// # Examples
650 ///
651 /// ```rust
652 /// use qubit_function::comparator::{Comparator, ArcComparator};
653 /// use std::cmp::Ordering;
654 ///
655 /// let cmp1 = ArcComparator::new(|a: &i32, b: &i32| {
656 /// (a % 2).cmp(&(b % 2))
657 /// });
658 /// let cmp2 = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
659 /// let chained = cmp1.then_comparing(&cmp2);
660 /// assert_eq!(chained.compare(&4, &2), Ordering::Greater);
661 /// ```
662 #[inline]
663 pub fn then_comparing(&self, other: &Self) -> Self
664 where
665 T: 'static,
666 {
667 let first = self.function.clone();
668 let second = other.function.clone();
669 ArcComparator::new(move |a, b| match first(a, b) {
670 Ordering::Equal => second(a, b),
671 ord => ord,
672 })
673 }
674
675 /// Returns a comparator that compares values by a key extracted by the
676 /// given function.
677 ///
678 /// # Parameters
679 ///
680 /// * `key_fn` - A function that extracts a comparable key from values
681 ///
682 /// # Returns
683 ///
684 /// A new `ArcComparator` that compares by the extracted key.
685 ///
686 /// # Examples
687 ///
688 /// ```rust
689 /// use qubit_function::comparator::{Comparator, ArcComparator};
690 /// use std::cmp::Ordering;
691 ///
692 /// #[derive(Debug)]
693 /// struct Person {
694 /// name: String,
695 /// age: i32,
696 /// }
697 ///
698 /// let by_age = ArcComparator::comparing(|p: &Person| &p.age);
699 /// let p1 = Person { name: "Alice".to_string(), age: 30 };
700 /// let p2 = Person { name: "Bob".to_string(), age: 25 };
701 /// assert_eq!(by_age.compare(&p1, &p2), Ordering::Greater);
702 /// ```
703 #[inline]
704 pub fn comparing<K, F>(key_fn: F) -> Self
705 where
706 K: Ord,
707 F: Fn(&T) -> &K + Send + Sync + 'static,
708 {
709 ArcComparator::new(move |a, b| key_fn(a).cmp(key_fn(b)))
710 }
711
712 /// Converts this comparator into a closure.
713 ///
714 /// # Returns
715 ///
716 /// A closure that implements `Fn(&T, &T) -> Ordering`.
717 ///
718 /// # Examples
719 ///
720 /// ```rust
721 /// use qubit_function::comparator::{Comparator, ArcComparator};
722 /// use std::cmp::Ordering;
723 ///
724 /// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
725 /// let func = cmp.into_fn();
726 /// assert_eq!(func(&5, &3), Ordering::Greater);
727 /// ```
728 #[inline]
729 pub fn into_fn(self) -> impl Fn(&T, &T) -> Ordering {
730 move |a: &T, b: &T| (self.function)(a, b)
731 }
732}
733
734impl<T> Comparator<T> for ArcComparator<T> {
735 #[inline]
736 fn compare(&self, a: &T, b: &T) -> Ordering {
737 (self.function)(a, b)
738 }
739}
740
741/// An Rc-based single-threaded comparator with shared ownership.
742///
743/// `RcComparator` wraps a comparator function in an `Rc`, providing
744/// single-threaded shared ownership semantics. It is cloneable and uses
745/// `&self` in composition operations.
746///
747/// # Type Parameters
748///
749/// * `T` - The type of values being compared
750///
751/// # Examples
752///
753/// ```rust
754/// use qubit_function::comparator::{Comparator, RcComparator};
755/// use std::cmp::Ordering;
756///
757/// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
758/// let cloned = cmp.clone();
759/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
760/// assert_eq!(cloned.compare(&5, &3), Ordering::Greater);
761/// ```
762///
763/// # Author
764///
765/// Haixing Hu
766#[derive(Clone)]
767pub struct RcComparator<T> {
768 function: Rc<dyn Fn(&T, &T) -> Ordering>,
769}
770
771impl<T> RcComparator<T> {
772 /// Creates a new `RcComparator` from a closure.
773 ///
774 /// # Parameters
775 ///
776 /// * `f` - The closure to wrap
777 ///
778 /// # Returns
779 ///
780 /// A new `RcComparator` instance.
781 ///
782 /// # Examples
783 ///
784 /// ```rust
785 /// use qubit_function::comparator::RcComparator;
786 ///
787 /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
788 /// ```
789 #[inline]
790 pub fn new<F>(f: F) -> Self
791 where
792 F: Fn(&T, &T) -> Ordering + 'static,
793 {
794 Self {
795 function: Rc::new(f),
796 }
797 }
798
799 /// Returns a comparator that imposes the reverse ordering.
800 ///
801 /// # Returns
802 ///
803 /// A new `RcComparator` that reverses the comparison order.
804 ///
805 /// # Examples
806 ///
807 /// ```rust
808 /// use qubit_function::comparator::{Comparator, RcComparator};
809 /// use std::cmp::Ordering;
810 ///
811 /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
812 /// let rev = cmp.reversed();
813 /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
814 /// assert_eq!(cmp.compare(&5, &3), Ordering::Greater); // cmp still works
815 /// ```
816 #[inline]
817 pub fn reversed(&self) -> Self
818 where
819 T: 'static,
820 {
821 let self_fn = self.function.clone();
822 RcComparator::new(move |a, b| self_fn(b, a))
823 }
824
825 /// Returns a comparator that uses this comparator first, then another
826 /// comparator if this one considers the values equal.
827 ///
828 /// # Parameters
829 ///
830 /// * `other` - The comparator to use for tie-breaking
831 ///
832 /// # Returns
833 ///
834 /// A new `RcComparator` that chains this comparator with another.
835 ///
836 /// # Examples
837 ///
838 /// ```rust
839 /// use qubit_function::comparator::{Comparator, RcComparator};
840 /// use std::cmp::Ordering;
841 ///
842 /// let cmp1 = RcComparator::new(|a: &i32, b: &i32| {
843 /// (a % 2).cmp(&(b % 2))
844 /// });
845 /// let cmp2 = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
846 /// let chained = cmp1.then_comparing(&cmp2);
847 /// assert_eq!(chained.compare(&4, &2), Ordering::Greater);
848 /// ```
849 #[inline]
850 pub fn then_comparing(&self, other: &Self) -> Self
851 where
852 T: 'static,
853 {
854 let first = self.function.clone();
855 let second = other.function.clone();
856 RcComparator::new(move |a, b| match first(a, b) {
857 Ordering::Equal => second(a, b),
858 ord => ord,
859 })
860 }
861
862 /// Returns a comparator that compares values by a key extracted by the
863 /// given function.
864 ///
865 /// # Parameters
866 ///
867 /// * `key_fn` - A function that extracts a comparable key from values
868 ///
869 /// # Returns
870 ///
871 /// A new `RcComparator` that compares by the extracted key.
872 ///
873 /// # Examples
874 ///
875 /// ```rust
876 /// use qubit_function::comparator::{Comparator, RcComparator};
877 /// use std::cmp::Ordering;
878 ///
879 /// #[derive(Debug)]
880 /// struct Person {
881 /// name: String,
882 /// age: i32,
883 /// }
884 ///
885 /// let by_age = RcComparator::comparing(|p: &Person| &p.age);
886 /// let p1 = Person { name: "Alice".to_string(), age: 30 };
887 /// let p2 = Person { name: "Bob".to_string(), age: 25 };
888 /// assert_eq!(by_age.compare(&p1, &p2), Ordering::Greater);
889 /// ```
890 #[inline]
891 pub fn comparing<K, F>(key_fn: F) -> Self
892 where
893 K: Ord,
894 F: Fn(&T) -> &K + 'static,
895 {
896 RcComparator::new(move |a, b| key_fn(a).cmp(key_fn(b)))
897 }
898
899 /// Converts this comparator into a closure.
900 ///
901 /// # Returns
902 ///
903 /// A closure that implements `Fn(&T, &T) -> Ordering`.
904 ///
905 /// # Examples
906 ///
907 /// ```rust
908 /// use qubit_function::comparator::{Comparator, RcComparator};
909 /// use std::cmp::Ordering;
910 ///
911 /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
912 /// let func = cmp.into_fn();
913 /// assert_eq!(func(&5, &3), Ordering::Greater);
914 /// ```
915 #[inline]
916 pub fn into_fn(self) -> impl Fn(&T, &T) -> Ordering {
917 move |a: &T, b: &T| (self.function)(a, b)
918 }
919}
920
921impl<T> Comparator<T> for RcComparator<T> {
922 #[inline]
923 fn compare(&self, a: &T, b: &T) -> Ordering {
924 (self.function)(a, b)
925 }
926}
927
928/// Extension trait providing composition methods for closures and function
929/// pointers.
930///
931/// This trait is automatically implemented for all closures and function
932/// pointers with the signature `Fn(&T, &T) -> Ordering`, allowing them to
933/// be composed directly without explicit wrapping.
934///
935/// # Examples
936///
937/// ```rust
938/// use qubit_function::comparator::{Comparator, FnComparatorOps};
939/// use std::cmp::Ordering;
940///
941/// let cmp = (|a: &i32, b: &i32| a.cmp(b))
942/// .reversed()
943/// .then_comparing(BoxComparator::new(|a, b| b.cmp(a)));
944///
945/// assert_eq!(cmp.compare(&5, &3), Ordering::Less);
946/// ```
947///
948/// # Author
949///
950/// Haixing Hu
951pub trait FnComparatorOps<T>: Fn(&T, &T) -> Ordering + Sized {
952 /// Returns a comparator that imposes the reverse ordering.
953 ///
954 /// # Returns
955 ///
956 /// A new `BoxComparator` that reverses the comparison order.
957 ///
958 /// # Examples
959 ///
960 /// ```rust
961 /// use qubit_function::comparator::{Comparator, FnComparatorOps};
962 /// use std::cmp::Ordering;
963 ///
964 /// let rev = (|a: &i32, b: &i32| a.cmp(b)).reversed();
965 /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
966 /// ```
967 #[inline]
968 fn reversed(self) -> BoxComparator<T>
969 where
970 Self: 'static,
971 T: 'static,
972 {
973 BoxComparator::new(self).reversed()
974 }
975
976 /// Returns a comparator that uses this comparator first, then another
977 /// comparator if this one considers the values equal.
978 ///
979 /// # Parameters
980 ///
981 /// * `other` - The comparator to use for tie-breaking
982 ///
983 /// # Returns
984 ///
985 /// A new `BoxComparator` that chains this comparator with another.
986 ///
987 /// # Examples
988 ///
989 /// ```rust
990 /// use qubit_function::comparator::{Comparator, FnComparatorOps,
991 /// BoxComparator};
992 /// use std::cmp::Ordering;
993 ///
994 /// let cmp = (|a: &i32, b: &i32| (a % 2).cmp(&(b % 2)))
995 /// .then_comparing(BoxComparator::new(|a, b| a.cmp(b)));
996 /// assert_eq!(cmp.compare(&4, &2), Ordering::Greater);
997 /// ```
998 #[inline]
999 fn then_comparing(self, other: BoxComparator<T>) -> BoxComparator<T>
1000 where
1001 Self: 'static,
1002 T: 'static,
1003 {
1004 BoxComparator::new(self).then_comparing(other)
1005 }
1006}
1007
1008impl<T, F> FnComparatorOps<T> for F where F: Fn(&T, &T) -> Ordering {}