prism3_function/
comparator.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism 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 prism3_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 prism3_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 prism3_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 prism3_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 prism3_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 prism3_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
172
173use std::cmp::Ordering;
174use std::rc::Rc;
175use std::sync::Arc;
176
177// ==========================================================================
178// Type Aliases
179// ==========================================================================
180
181/// Type alias for comparator function signature.
182type ComparatorFn<T> = dyn Fn(&T, &T) -> Ordering;
183
184/// Type alias for thread-safe comparator function signature.
185type ThreadSafeComparatorFn<T> = dyn Fn(&T, &T) -> Ordering + Send + Sync;
186
187/// A trait for comparison operations.
188///
189/// This trait defines the core comparison operation and conversion methods.
190/// It does NOT include composition methods like `reversed` or
191/// `then_comparing` to maintain a clean separation between the trait
192/// interface and specialized implementations.
193///
194/// # Type Parameters
195///
196/// * `T` - The type of values being compared
197///
198/// # Examples
199///
200/// ```rust
201/// use prism3_function::comparator::{Comparator, BoxComparator};
202/// use std::cmp::Ordering;
203///
204/// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
205/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
206/// ```
207///
208/// # Author
209///
210/// Haixing Hu
211pub trait Comparator<T> {
212    /// Compares two values and returns an ordering.
213    ///
214    /// # Parameters
215    ///
216    /// * `a` - The first value to compare
217    /// * `b` - The second value to compare
218    ///
219    /// # Returns
220    ///
221    /// An `Ordering` indicating whether `a` is less than, equal to, or
222    /// greater than `b`.
223    ///
224    /// # Examples
225    ///
226    /// ```rust
227    /// use prism3_function::comparator::{Comparator, BoxComparator};
228    /// use std::cmp::Ordering;
229    ///
230    /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
231    /// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
232    /// assert_eq!(cmp.compare(&3, &5), Ordering::Less);
233    /// assert_eq!(cmp.compare(&5, &5), Ordering::Equal);
234    /// ```
235    fn compare(&self, a: &T, b: &T) -> Ordering;
236
237    /// Converts this comparator into a `BoxComparator`.
238    ///
239    /// # Returns
240    ///
241    /// A new `BoxComparator` wrapping this comparator.
242    ///
243    /// # Examples
244    ///
245    /// ```rust
246    /// use prism3_function::comparator::{Comparator, BoxComparator};
247    ///
248    /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
249    /// let boxed = cmp.into_box();
250    /// ```
251    fn into_box(self) -> BoxComparator<T>
252    where
253        Self: Sized + 'static,
254        T: 'static,
255    {
256        BoxComparator::new(move |a, b| self.compare(a, b))
257    }
258
259    /// Converts this comparator into an `ArcComparator`.
260    ///
261    /// # Returns
262    ///
263    /// A new `ArcComparator` wrapping this comparator.
264    ///
265    /// # Examples
266    ///
267    /// ```rust
268    /// use prism3_function::comparator::{Comparator, ArcComparator};
269    ///
270    /// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
271    /// let arc = cmp.into_arc();
272    /// ```
273    fn into_arc(self) -> ArcComparator<T>
274    where
275        Self: Sized + Send + Sync + 'static,
276        T: 'static,
277    {
278        ArcComparator::new(move |a, b| self.compare(a, b))
279    }
280
281    /// Converts this comparator into an `RcComparator`.
282    ///
283    /// # Returns
284    ///
285    /// A new `RcComparator` wrapping this comparator.
286    ///
287    /// # Examples
288    ///
289    /// ```rust
290    /// use prism3_function::comparator::{Comparator, RcComparator};
291    ///
292    /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
293    /// let rc = cmp.into_rc();
294    /// ```
295    fn into_rc(self) -> RcComparator<T>
296    where
297        Self: Sized + 'static,
298        T: 'static,
299    {
300        RcComparator::new(move |a, b| self.compare(a, b))
301    }
302
303    /// Converts this comparator into a closure that implements
304    /// `Fn(&T, &T) -> Ordering`.
305    ///
306    /// This method consumes the comparator and returns a closure that
307    /// can be used anywhere a function or closure is expected.
308    ///
309    /// # Returns
310    ///
311    /// An implementation that can be called as `Fn(&T, &T) -> Ordering`.
312    ///
313    /// # Examples
314    ///
315    /// ```rust
316    /// use prism3_function::comparator::{Comparator, BoxComparator};
317    /// use std::cmp::Ordering;
318    ///
319    /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
320    /// let func = cmp.into_fn();
321    /// assert_eq!(func(&5, &3), Ordering::Greater);
322    /// ```
323    fn into_fn(self) -> impl Fn(&T, &T) -> Ordering
324    where
325        Self: Sized + 'static,
326        T: 'static,
327    {
328        move |a: &T, b: &T| self.compare(a, b)
329    }
330}
331
332/// Blanket implementation of `Comparator` for all closures and function
333/// pointers.
334///
335/// This allows any closure or function with the signature
336/// `Fn(&T, &T) -> Ordering` to be used as a comparator.
337///
338/// # Examples
339///
340/// ```rust
341/// use prism3_function::comparator::Comparator;
342/// use std::cmp::Ordering;
343///
344/// let cmp = |a: &i32, b: &i32| a.cmp(b);
345/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
346/// ```
347impl<T, F> Comparator<T> for F
348where
349    F: Fn(&T, &T) -> Ordering,
350{
351    fn compare(&self, a: &T, b: &T) -> Ordering {
352        self(a, b)
353    }
354}
355
356/// A boxed comparator with single ownership.
357///
358/// `BoxComparator` wraps a comparator function in a `Box`, providing single
359/// ownership semantics. It is not cloneable and consumes `self` in
360/// composition operations.
361///
362/// # Type Parameters
363///
364/// * `T` - The type of values being compared
365///
366/// # Examples
367///
368/// ```rust
369/// use prism3_function::comparator::{Comparator, BoxComparator};
370/// use std::cmp::Ordering;
371///
372/// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
373/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
374/// ```
375///
376/// # Author
377///
378/// Haixing Hu
379pub struct BoxComparator<T> {
380    function: Box<ComparatorFn<T>>,
381}
382
383impl<T: 'static> BoxComparator<T> {
384    /// Creates a new `BoxComparator` from a closure.
385    ///
386    /// # Parameters
387    ///
388    /// * `f` - The closure to wrap
389    ///
390    /// # Returns
391    ///
392    /// A new `BoxComparator` instance.
393    ///
394    /// # Examples
395    ///
396    /// ```rust
397    /// use prism3_function::comparator::BoxComparator;
398    ///
399    /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
400    /// ```
401    pub fn new<F>(f: F) -> Self
402    where
403        F: Fn(&T, &T) -> Ordering + 'static,
404    {
405        Self {
406            function: Box::new(f),
407        }
408    }
409
410    /// Returns a comparator that imposes the reverse ordering.
411    ///
412    /// # Returns
413    ///
414    /// A new `BoxComparator` that reverses the comparison order.
415    ///
416    /// # Examples
417    ///
418    /// ```rust
419    /// use prism3_function::comparator::{Comparator, BoxComparator};
420    /// use std::cmp::Ordering;
421    ///
422    /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
423    /// let rev = cmp.reversed();
424    /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
425    /// ```
426    pub fn reversed(self) -> Self {
427        Self {
428            function: Box::new(move |a: &T, b: &T| (self.function)(b, a)),
429        }
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 prism3_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    pub fn then_comparing(self, other: Self) -> Self {
478        Self {
479            function: Box::new(move |a: &T, b: &T| match (self.function)(a, b) {
480                Ordering::Equal => (other.function)(a, b),
481                ord => ord,
482            }),
483        }
484    }
485
486    /// Returns a comparator that compares values by a key extracted by the
487    /// given function.
488    ///
489    /// # Parameters
490    ///
491    /// * `key_fn` - A function that extracts a comparable key from values
492    ///
493    /// # Returns
494    ///
495    /// A new `BoxComparator` that compares by the extracted key.
496    ///
497    /// # Examples
498    ///
499    /// ```rust
500    /// use prism3_function::comparator::{Comparator, BoxComparator};
501    /// use std::cmp::Ordering;
502    ///
503    /// #[derive(Debug)]
504    /// struct Person {
505    ///     name: String,
506    ///     age: i32,
507    /// }
508    ///
509    /// let by_age = BoxComparator::comparing(|p: &Person| &p.age);
510    /// let p1 = Person { name: "Alice".to_string(), age: 30 };
511    /// let p2 = Person { name: "Bob".to_string(), age: 25 };
512    /// assert_eq!(by_age.compare(&p1, &p2), Ordering::Greater);
513    /// ```
514    pub fn comparing<K, F>(key_fn: F) -> Self
515    where
516        K: Ord,
517        F: Fn(&T) -> &K + 'static,
518    {
519        Self::new(move |a: &T, b: &T| key_fn(a).cmp(key_fn(b)))
520    }
521
522    /// Converts this comparator into a closure.
523    ///
524    /// # Returns
525    ///
526    /// A closure that implements `Fn(&T, &T) -> Ordering`.
527    ///
528    /// # Examples
529    ///
530    /// ```rust
531    /// use prism3_function::comparator::{Comparator, BoxComparator};
532    /// use std::cmp::Ordering;
533    ///
534    /// let cmp = BoxComparator::new(|a: &i32, b: &i32| a.cmp(b));
535    /// let func = cmp.into_fn();
536    /// assert_eq!(func(&5, &3), Ordering::Greater);
537    /// ```
538    pub fn into_fn(self) -> impl Fn(&T, &T) -> Ordering {
539        move |a: &T, b: &T| (self.function)(a, b)
540    }
541}
542
543impl<T> Comparator<T> for BoxComparator<T> {
544    fn compare(&self, a: &T, b: &T) -> Ordering {
545        (self.function)(a, b)
546    }
547}
548
549/// An Arc-based thread-safe comparator with shared ownership.
550///
551/// `ArcComparator` wraps a comparator function in an `Arc`, providing
552/// thread-safe shared ownership semantics. It is cloneable and uses `&self`
553/// in composition operations.
554///
555/// # Type Parameters
556///
557/// * `T` - The type of values being compared
558///
559/// # Examples
560///
561/// ```rust
562/// use prism3_function::comparator::{Comparator, ArcComparator};
563/// use std::cmp::Ordering;
564///
565/// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
566/// let cloned = cmp.clone();
567/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
568/// assert_eq!(cloned.compare(&5, &3), Ordering::Greater);
569/// ```
570///
571/// # Author
572///
573/// Haixing Hu
574#[derive(Clone)]
575pub struct ArcComparator<T> {
576    function: Arc<ThreadSafeComparatorFn<T>>,
577}
578
579impl<T: 'static> ArcComparator<T> {
580    /// Creates a new `ArcComparator` from a closure.
581    ///
582    /// # Parameters
583    ///
584    /// * `f` - The closure to wrap
585    ///
586    /// # Returns
587    ///
588    /// A new `ArcComparator` instance.
589    ///
590    /// # Examples
591    ///
592    /// ```rust
593    /// use prism3_function::comparator::ArcComparator;
594    ///
595    /// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
596    /// ```
597    pub fn new<F>(f: F) -> Self
598    where
599        F: Fn(&T, &T) -> Ordering + Send + Sync + 'static,
600    {
601        Self {
602            function: Arc::new(f),
603        }
604    }
605
606    /// Returns a comparator that imposes the reverse ordering.
607    ///
608    /// # Returns
609    ///
610    /// A new `ArcComparator` that reverses the comparison order.
611    ///
612    /// # Examples
613    ///
614    /// ```rust
615    /// use prism3_function::comparator::{Comparator, ArcComparator};
616    /// use std::cmp::Ordering;
617    ///
618    /// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
619    /// let rev = cmp.reversed();
620    /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
621    /// assert_eq!(cmp.compare(&5, &3), Ordering::Greater); // cmp still works
622    /// ```
623    pub fn reversed(&self) -> Self {
624        let function = self.function.clone();
625        Self {
626            function: Arc::new(move |a: &T, b: &T| function(b, a)),
627        }
628    }
629
630    /// Returns a comparator that uses this comparator first, then another
631    /// comparator if this one considers the values equal.
632    ///
633    /// # Parameters
634    ///
635    /// * `other` - The comparator to use for tie-breaking
636    ///
637    /// # Returns
638    ///
639    /// A new `ArcComparator` that chains this comparator with another.
640    ///
641    /// # Examples
642    ///
643    /// ```rust
644    /// use prism3_function::comparator::{Comparator, ArcComparator};
645    /// use std::cmp::Ordering;
646    ///
647    /// let cmp1 = ArcComparator::new(|a: &i32, b: &i32| {
648    ///     (a % 2).cmp(&(b % 2))
649    /// });
650    /// let cmp2 = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
651    /// let chained = cmp1.then_comparing(&cmp2);
652    /// assert_eq!(chained.compare(&4, &2), Ordering::Greater);
653    /// ```
654    pub fn then_comparing(&self, other: &Self) -> Self {
655        let first = self.function.clone();
656        let second = other.function.clone();
657        Self {
658            function: Arc::new(move |a: &T, b: &T| match first(a, b) {
659                Ordering::Equal => second(a, b),
660                ord => ord,
661            }),
662        }
663    }
664
665    /// Returns a comparator that compares values by a key extracted by the
666    /// given function.
667    ///
668    /// # Parameters
669    ///
670    /// * `key_fn` - A function that extracts a comparable key from values
671    ///
672    /// # Returns
673    ///
674    /// A new `ArcComparator` that compares by the extracted key.
675    ///
676    /// # Examples
677    ///
678    /// ```rust
679    /// use prism3_function::comparator::{Comparator, ArcComparator};
680    /// use std::cmp::Ordering;
681    ///
682    /// #[derive(Debug)]
683    /// struct Person {
684    ///     name: String,
685    ///     age: i32,
686    /// }
687    ///
688    /// let by_age = ArcComparator::comparing(|p: &Person| &p.age);
689    /// let p1 = Person { name: "Alice".to_string(), age: 30 };
690    /// let p2 = Person { name: "Bob".to_string(), age: 25 };
691    /// assert_eq!(by_age.compare(&p1, &p2), Ordering::Greater);
692    /// ```
693    pub fn comparing<K, F>(key_fn: F) -> Self
694    where
695        K: Ord,
696        F: Fn(&T) -> &K + Send + Sync + 'static,
697    {
698        Self::new(move |a: &T, b: &T| key_fn(a).cmp(key_fn(b)))
699    }
700
701    /// Converts this comparator into a closure.
702    ///
703    /// # Returns
704    ///
705    /// A closure that implements `Fn(&T, &T) -> Ordering`.
706    ///
707    /// # Examples
708    ///
709    /// ```rust
710    /// use prism3_function::comparator::{Comparator, ArcComparator};
711    /// use std::cmp::Ordering;
712    ///
713    /// let cmp = ArcComparator::new(|a: &i32, b: &i32| a.cmp(b));
714    /// let func = cmp.into_fn();
715    /// assert_eq!(func(&5, &3), Ordering::Greater);
716    /// ```
717    pub fn into_fn(self) -> impl Fn(&T, &T) -> Ordering {
718        move |a: &T, b: &T| (self.function)(a, b)
719    }
720}
721
722impl<T> Comparator<T> for ArcComparator<T> {
723    fn compare(&self, a: &T, b: &T) -> Ordering {
724        (self.function)(a, b)
725    }
726}
727
728/// An Rc-based single-threaded comparator with shared ownership.
729///
730/// `RcComparator` wraps a comparator function in an `Rc`, providing
731/// single-threaded shared ownership semantics. It is cloneable and uses
732/// `&self` in composition operations.
733///
734/// # Type Parameters
735///
736/// * `T` - The type of values being compared
737///
738/// # Examples
739///
740/// ```rust
741/// use prism3_function::comparator::{Comparator, RcComparator};
742/// use std::cmp::Ordering;
743///
744/// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
745/// let cloned = cmp.clone();
746/// assert_eq!(cmp.compare(&5, &3), Ordering::Greater);
747/// assert_eq!(cloned.compare(&5, &3), Ordering::Greater);
748/// ```
749///
750/// # Author
751///
752/// Haixing Hu
753#[derive(Clone)]
754pub struct RcComparator<T> {
755    function: Rc<ComparatorFn<T>>,
756}
757
758impl<T: 'static> RcComparator<T> {
759    /// Creates a new `RcComparator` from a closure.
760    ///
761    /// # Parameters
762    ///
763    /// * `f` - The closure to wrap
764    ///
765    /// # Returns
766    ///
767    /// A new `RcComparator` instance.
768    ///
769    /// # Examples
770    ///
771    /// ```rust
772    /// use prism3_function::comparator::RcComparator;
773    ///
774    /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
775    /// ```
776    pub fn new<F>(f: F) -> Self
777    where
778        F: Fn(&T, &T) -> Ordering + 'static,
779    {
780        Self {
781            function: Rc::new(f),
782        }
783    }
784
785    /// Returns a comparator that imposes the reverse ordering.
786    ///
787    /// # Returns
788    ///
789    /// A new `RcComparator` that reverses the comparison order.
790    ///
791    /// # Examples
792    ///
793    /// ```rust
794    /// use prism3_function::comparator::{Comparator, RcComparator};
795    /// use std::cmp::Ordering;
796    ///
797    /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
798    /// let rev = cmp.reversed();
799    /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
800    /// assert_eq!(cmp.compare(&5, &3), Ordering::Greater); // cmp still works
801    /// ```
802    pub fn reversed(&self) -> Self {
803        let function = self.function.clone();
804        Self {
805            function: Rc::new(move |a: &T, b: &T| function(b, a)),
806        }
807    }
808
809    /// Returns a comparator that uses this comparator first, then another
810    /// comparator if this one considers the values equal.
811    ///
812    /// # Parameters
813    ///
814    /// * `other` - The comparator to use for tie-breaking
815    ///
816    /// # Returns
817    ///
818    /// A new `RcComparator` that chains this comparator with another.
819    ///
820    /// # Examples
821    ///
822    /// ```rust
823    /// use prism3_function::comparator::{Comparator, RcComparator};
824    /// use std::cmp::Ordering;
825    ///
826    /// let cmp1 = RcComparator::new(|a: &i32, b: &i32| {
827    ///     (a % 2).cmp(&(b % 2))
828    /// });
829    /// let cmp2 = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
830    /// let chained = cmp1.then_comparing(&cmp2);
831    /// assert_eq!(chained.compare(&4, &2), Ordering::Greater);
832    /// ```
833    pub fn then_comparing(&self, other: &Self) -> Self {
834        let first = self.function.clone();
835        let second = other.function.clone();
836        Self {
837            function: Rc::new(move |a: &T, b: &T| match first(a, b) {
838                Ordering::Equal => second(a, b),
839                ord => ord,
840            }),
841        }
842    }
843
844    /// Returns a comparator that compares values by a key extracted by the
845    /// given function.
846    ///
847    /// # Parameters
848    ///
849    /// * `key_fn` - A function that extracts a comparable key from values
850    ///
851    /// # Returns
852    ///
853    /// A new `RcComparator` that compares by the extracted key.
854    ///
855    /// # Examples
856    ///
857    /// ```rust
858    /// use prism3_function::comparator::{Comparator, RcComparator};
859    /// use std::cmp::Ordering;
860    ///
861    /// #[derive(Debug)]
862    /// struct Person {
863    ///     name: String,
864    ///     age: i32,
865    /// }
866    ///
867    /// let by_age = RcComparator::comparing(|p: &Person| &p.age);
868    /// let p1 = Person { name: "Alice".to_string(), age: 30 };
869    /// let p2 = Person { name: "Bob".to_string(), age: 25 };
870    /// assert_eq!(by_age.compare(&p1, &p2), Ordering::Greater);
871    /// ```
872    pub fn comparing<K, F>(key_fn: F) -> Self
873    where
874        K: Ord,
875        F: Fn(&T) -> &K + 'static,
876    {
877        Self::new(move |a: &T, b: &T| key_fn(a).cmp(key_fn(b)))
878    }
879
880    /// Converts this comparator into a closure.
881    ///
882    /// # Returns
883    ///
884    /// A closure that implements `Fn(&T, &T) -> Ordering`.
885    ///
886    /// # Examples
887    ///
888    /// ```rust
889    /// use prism3_function::comparator::{Comparator, RcComparator};
890    /// use std::cmp::Ordering;
891    ///
892    /// let cmp = RcComparator::new(|a: &i32, b: &i32| a.cmp(b));
893    /// let func = cmp.into_fn();
894    /// assert_eq!(func(&5, &3), Ordering::Greater);
895    /// ```
896    pub fn into_fn(self) -> impl Fn(&T, &T) -> Ordering {
897        move |a: &T, b: &T| (self.function)(a, b)
898    }
899}
900
901impl<T> Comparator<T> for RcComparator<T> {
902    fn compare(&self, a: &T, b: &T) -> Ordering {
903        (self.function)(a, b)
904    }
905}
906
907/// Extension trait providing composition methods for closures and function
908/// pointers.
909///
910/// This trait is automatically implemented for all closures and function
911/// pointers with the signature `Fn(&T, &T) -> Ordering`, allowing them to
912/// be composed directly without explicit wrapping.
913///
914/// # Examples
915///
916/// ```rust
917/// use prism3_function::comparator::{Comparator, FnComparatorOps};
918/// use std::cmp::Ordering;
919///
920/// let cmp = (|a: &i32, b: &i32| a.cmp(b))
921///     .reversed()
922///     .then_comparing(BoxComparator::new(|a, b| b.cmp(a)));
923///
924/// assert_eq!(cmp.compare(&5, &3), Ordering::Less);
925/// ```
926///
927/// # Author
928///
929/// Haixing Hu
930pub trait FnComparatorOps<T>: Fn(&T, &T) -> Ordering + Sized {
931    /// Returns a comparator that imposes the reverse ordering.
932    ///
933    /// # Returns
934    ///
935    /// A new `BoxComparator` that reverses the comparison order.
936    ///
937    /// # Examples
938    ///
939    /// ```rust
940    /// use prism3_function::comparator::{Comparator, FnComparatorOps};
941    /// use std::cmp::Ordering;
942    ///
943    /// let rev = (|a: &i32, b: &i32| a.cmp(b)).reversed();
944    /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
945    /// ```
946    fn reversed(self) -> BoxComparator<T>
947    where
948        Self: 'static,
949        T: 'static,
950    {
951        BoxComparator::new(self).reversed()
952    }
953
954    /// Returns a comparator that uses this comparator first, then another
955    /// comparator if this one considers the values equal.
956    ///
957    /// # Parameters
958    ///
959    /// * `other` - The comparator to use for tie-breaking
960    ///
961    /// # Returns
962    ///
963    /// A new `BoxComparator` that chains this comparator with another.
964    ///
965    /// # Examples
966    ///
967    /// ```rust
968    /// use prism3_function::comparator::{Comparator, FnComparatorOps,
969    ///                                   BoxComparator};
970    /// use std::cmp::Ordering;
971    ///
972    /// let cmp = (|a: &i32, b: &i32| (a % 2).cmp(&(b % 2)))
973    ///     .then_comparing(BoxComparator::new(|a, b| a.cmp(b)));
974    /// assert_eq!(cmp.compare(&4, &2), Ordering::Greater);
975    /// ```
976    fn then_comparing(self, other: BoxComparator<T>) -> BoxComparator<T>
977    where
978        Self: 'static,
979        T: 'static,
980    {
981        BoxComparator::new(self).then_comparing(other)
982    }
983}
984
985impl<T, F> FnComparatorOps<T> for F where F: Fn(&T, &T) -> Ordering {}