Skip to main content

qubit_function/comparator/
fn_comparator_ops.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10// qubit-style: allow explicit-imports
11//! Defines the `FnComparatorOps` public type.
12
13use super::{
14    BoxComparator,
15    Ordering,
16};
17
18/// Extension trait providing composition methods for closures and function
19/// pointers.
20///
21/// This trait is automatically implemented for all closures and function
22/// pointers with the signature `Fn(&T, &T) -> Ordering`, allowing them to
23/// be composed directly without explicit wrapping.
24///
25/// # Examples
26///
27/// ```rust
28/// use qubit_function::comparator::{Comparator, FnComparatorOps, BoxComparator};
29/// use std::cmp::Ordering;
30///
31/// let cmp = (|a: &i32, b: &i32| a.cmp(b))
32///     .reversed()
33///     .then_comparing(BoxComparator::new(|a: &i32, b: &i32| b.cmp(a)));
34///
35/// assert_eq!(cmp.compare(&5, &3), Ordering::Less);
36/// ```
37///
38pub trait FnComparatorOps<T>: Fn(&T, &T) -> Ordering + Sized {
39    /// Returns a comparator that imposes the reverse ordering.
40    ///
41    /// # Returns
42    ///
43    /// A new `BoxComparator` that reverses the comparison order.
44    ///
45    /// # Examples
46    ///
47    /// ```rust
48    /// use qubit_function::comparator::{Comparator, FnComparatorOps};
49    /// use std::cmp::Ordering;
50    ///
51    /// let rev = (|a: &i32, b: &i32| a.cmp(b)).reversed();
52    /// assert_eq!(rev.compare(&5, &3), Ordering::Less);
53    /// ```
54    #[inline]
55    fn reversed(self) -> BoxComparator<T>
56    where
57        Self: 'static,
58        T: 'static,
59    {
60        BoxComparator::new(self).reversed()
61    }
62
63    /// Returns a comparator that uses this comparator first, then another
64    /// comparator if this one considers the values equal.
65    ///
66    /// # Parameters
67    ///
68    /// * `other` - The comparator to use for tie-breaking
69    ///
70    /// # Returns
71    ///
72    /// A new `BoxComparator` that chains this comparator with another.
73    ///
74    /// # Examples
75    ///
76    /// ```rust
77    /// use qubit_function::comparator::{Comparator, FnComparatorOps, BoxComparator};
78    /// use std::cmp::Ordering;
79    ///
80    /// let cmp = (|a: &i32, b: &i32| (a % 2).cmp(&(b % 2)))
81    ///     .then_comparing(BoxComparator::new(|a: &i32, b: &i32| a.cmp(b)));
82    /// assert_eq!(cmp.compare(&4, &2), Ordering::Greater);
83    /// ```
84    #[inline]
85    fn then_comparing(self, other: BoxComparator<T>) -> BoxComparator<T>
86    where
87        Self: 'static,
88        T: 'static,
89    {
90        BoxComparator::new(self).then_comparing(other)
91    }
92}
93
94impl<T, F> FnComparatorOps<T> for F where F: Fn(&T, &T) -> Ordering {}