prism3_function/
bi_predicate.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # BiPredicate Abstraction
10//!
11//! Provides a Rust implementation similar to Java's `BiPredicate`
12//! interface for testing whether two values satisfy a condition.
13//!
14//! ## Core Semantics
15//!
16//! A **BiPredicate** is fundamentally a pure judgment operation that
17//! tests whether two values satisfy a specific condition. It should
18//! be:
19//!
20//! - **Read-only**: Does not modify the tested values
21//! - **Side-effect free**: Does not change external state (from the
22//!   user's perspective)
23//! - **Repeatable**: Same inputs should produce the same result
24//! - **Deterministic**: Judgment logic should be predictable
25//!
26//! ## Design Philosophy
27//!
28//! This module follows the same principles as the `Predicate` module:
29//!
30//! 1. **Single Trait**: Only one `BiPredicate<T, U>` trait with
31//!    `&self`, keeping the API simple and semantically clear
32//! 2. **No BiPredicateMut**: All stateful scenarios use interior
33//!    mutability (`RefCell`, `Cell`, `Mutex`) instead of `&mut self`
34//! 3. **No BiPredicateOnce**: Violates bi-predicate semantics -
35//!    judgments should be repeatable
36//! 4. **Three Implementations**: `BoxBiPredicate`, `RcBiPredicate`,
37//!    and `ArcBiPredicate` cover all ownership scenarios
38//!
39//! ## Type Selection Guide
40//!
41//! | Scenario | Recommended Type | Reason |
42//! |----------|------------------|--------|
43//! | One-time use | `BoxBiPredicate` | Single ownership, no overhead |
44//! | Multi-threaded | `ArcBiPredicate` | Thread-safe, clonable |
45//! | Single-threaded reuse | `RcBiPredicate` | Better performance |
46//! | Stateful predicate | Any type + `RefCell`/`Cell`/`Mutex` | Interior mutability |
47//!
48//! ## Examples
49//!
50//! ### Basic Usage with Closures
51//!
52//! ```rust
53//! use prism3_function::bi_predicate::BiPredicate;
54//!
55//! let is_sum_positive = |x: &i32, y: &i32| x + y > 0;
56//! assert!(is_sum_positive.test(&5, &3));
57//! assert!(!is_sum_positive.test(&-3, &-7));
58//! ```
59//!
60//! ### BoxBiPredicate - Single Ownership
61//!
62//! ```rust
63//! use prism3_function::bi_predicate::{BiPredicate, BoxBiPredicate};
64//!
65//! let pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0)
66//!     .and(BoxBiPredicate::new(|x, y| x > y));
67//! assert!(pred.test(&10, &5));
68//! ```
69//!
70//! ### Closure Composition with Extension Methods
71//!
72//! Closures automatically gain `and`, `or`, `not` methods through the
73//! `FnBiPredicateOps` extension trait, returning `BoxBiPredicate`:
74//!
75//! ```rust
76//! use prism3_function::bi_predicate::{BiPredicate,
77//!     FnBiPredicateOps};
78//!
79//! // Compose closures directly - result is BoxBiPredicate
80//! let is_sum_positive = |x: &i32, y: &i32| x + y > 0;
81//! let first_larger = |x: &i32, y: &i32| x > y;
82//!
83//! let combined = is_sum_positive.and(first_larger);
84//! assert!(combined.test(&10, &5));
85//! assert!(!combined.test(&3, &8));
86//!
87//! // Use `or` for disjunction
88//! let negative_sum = |x: &i32, y: &i32| x + y < 0;
89//! let both_large = |x: &i32, y: &i32| *x > 100 && *y > 100;
90//! let either = negative_sum.or(both_large);
91//! assert!(either.test(&-10, &5));
92//! assert!(either.test(&200, &150));
93//! ```
94//!
95//! ### RcBiPredicate - Single-threaded Reuse
96//!
97//! ```rust
98//! use prism3_function::bi_predicate::{BiPredicate, RcBiPredicate};
99//!
100//! let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
101//! let combined1 = pred.and(RcBiPredicate::new(|x, y| x > y));
102//! let combined2 = pred.or(RcBiPredicate::new(|x, y| *x > 100));
103//!
104//! // Original predicate is still usable
105//! assert!(pred.test(&5, &3));
106//! ```
107//!
108//! ### ArcBiPredicate - Thread-safe Sharing
109//!
110//! ```rust
111//! use prism3_function::bi_predicate::{BiPredicate, ArcBiPredicate};
112//! use std::thread;
113//!
114//! let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
115//! let pred_clone = pred.clone();
116//!
117//! let handle = thread::spawn(move || {
118//!     pred_clone.test(&10, &5)
119//! });
120//!
121//! assert!(handle.join().unwrap());
122//! assert!(pred.test(&3, &7));  // Original still usable
123//! ```
124//!
125//! ### Stateful BiPredicates with Interior Mutability
126//!
127//! ```rust
128//! use prism3_function::bi_predicate::{BiPredicate, BoxBiPredicate};
129//! use std::cell::Cell;
130//!
131//! let count = Cell::new(0);
132//! let pred = BoxBiPredicate::new(move |x: &i32, y: &i32| {
133//!     count.set(count.get() + 1);
134//!     x + y > 0
135//! });
136//!
137//! // No need for `mut` - interior mutability handles state
138//! assert!(pred.test(&5, &3));
139//! assert!(!pred.test(&-8, &-3));
140//! ```
141//!
142//! ## Author
143//!
144//! Haixing Hu
145
146use std::fmt::{Debug, Display};
147use std::rc::Rc;
148use std::sync::Arc;
149
150/// Type alias for bi-predicate function to simplify complex types.
151///
152/// This type alias represents a function that takes two references and returns a boolean.
153/// It is used to reduce type complexity in struct definitions.
154type BiPredicateFn<T, U> = dyn Fn(&T, &U) -> bool;
155
156/// Type alias for thread-safe bi-predicate function to simplify complex types.
157///
158/// This type alias represents a function that takes two references and returns a boolean,
159/// with Send + Sync bounds for thread-safe usage. It is used to reduce type complexity
160/// in Arc-based struct definitions.
161type SendSyncBiPredicateFn<T, U> = dyn Fn(&T, &U) -> bool + Send + Sync;
162
163/// BiPredicate name constant for always-true bi-predicates
164const ALWAYS_TRUE_NAME: &str = "always_true";
165
166/// BiPredicate name constant for always-false bi-predicates
167const ALWAYS_FALSE_NAME: &str = "always_false";
168
169/// A bi-predicate trait for testing whether two values satisfy a
170/// condition.
171///
172/// This trait represents a **pure judgment operation** - it tests
173/// whether two given values meet certain criteria without modifying
174/// either the values or the bi-predicate itself (from the user's
175/// perspective). This semantic clarity distinguishes bi-predicates
176/// from consumers or transformers.
177///
178/// ## Design Rationale
179///
180/// This is a **minimal trait** that only defines:
181/// - The core `test` method using `&self` (immutable borrow)
182/// - Type conversion methods (`into_box`, `into_rc`, `into_arc`)
183/// - Closure conversion method (`into_fn`)
184///
185/// Logical composition methods (`and`, `or`, `not`, `xor`, `nand`,
186/// `nor`) are intentionally **not** part of the trait. Instead, they
187/// are implemented on concrete types (`BoxBiPredicate`,
188/// `RcBiPredicate`, `ArcBiPredicate`), allowing each implementation
189/// to maintain its specific ownership characteristics:
190///
191/// - `BoxBiPredicate`: Methods consume `self` (single ownership)
192/// - `RcBiPredicate`: Methods borrow `&self` (shared ownership)
193/// - `ArcBiPredicate`: Methods borrow `&self` (thread-safe shared
194///   ownership)
195///
196/// ## Why `&self` Instead of `&mut self`?
197///
198/// Bi-predicates use `&self` because:
199///
200/// 1. **Semantic Clarity**: A bi-predicate is a judgment, not a
201///    mutation
202/// 2. **Flexibility**: Can be used in immutable contexts
203/// 3. **Simplicity**: No need for `mut` in user code
204/// 4. **Interior Mutability**: State (if needed) can be managed with
205///    `RefCell`, `Cell`, or `Mutex`
206///
207/// ## Automatic Implementation for Closures
208///
209/// Any closure matching `Fn(&T, &U) -> bool` automatically implements
210/// this trait, providing seamless integration with Rust's closure
211/// system.
212///
213/// ## Examples
214///
215/// ### Basic Usage
216///
217/// ```rust
218/// use prism3_function::bi_predicate::BiPredicate;
219///
220/// let is_sum_positive = |x: &i32, y: &i32| x + y > 0;
221/// assert!(is_sum_positive.test(&5, &3));
222/// assert!(!is_sum_positive.test(&-5, &-3));
223/// ```
224///
225/// ### Type Conversion
226///
227/// ```rust
228/// use prism3_function::bi_predicate::{BiPredicate,
229///     BoxBiPredicate};
230///
231/// let closure = |x: &i32, y: &i32| x + y > 0;
232/// let boxed: BoxBiPredicate<i32, i32> = closure.into_box();
233/// assert!(boxed.test(&5, &3));
234/// ```
235///
236/// ### Stateful BiPredicate with Interior Mutability
237///
238/// ```rust
239/// use prism3_function::bi_predicate::{BiPredicate,
240///     BoxBiPredicate};
241/// use std::cell::Cell;
242///
243/// let count = Cell::new(0);
244/// let counting_pred = BoxBiPredicate::new(move |x: &i32, y: &i32| {
245///     count.set(count.get() + 1);
246///     x + y > 0
247/// });
248///
249/// // Note: No `mut` needed - interior mutability handles state
250/// assert!(counting_pred.test(&5, &3));
251/// assert!(!counting_pred.test(&-5, &-3));
252/// ```
253///
254/// ## Author
255///
256/// Haixing Hu
257pub trait BiPredicate<T, U> {
258    /// Tests whether the given values satisfy this bi-predicate.
259    ///
260    /// # Parameters
261    ///
262    /// * `first` - The first value to test.
263    /// * `second` - The second value to test.
264    ///
265    /// # Returns
266    ///
267    /// `true` if the values satisfy this bi-predicate, `false`
268    /// otherwise.
269    fn test(&self, first: &T, second: &U) -> bool;
270
271    /// Converts this bi-predicate into a `BoxBiPredicate`.
272    ///
273    /// # Returns
274    ///
275    /// A `BoxBiPredicate` wrapping this bi-predicate.
276    ///
277    /// # Default Implementation
278    ///
279    /// The default implementation wraps the bi-predicate in a
280    /// closure that calls `test`, providing automatic conversion
281    /// for custom types that only implement the core `test`
282    /// method.
283    fn into_box(self) -> BoxBiPredicate<T, U>
284    where
285        Self: Sized + 'static,
286        T: 'static,
287        U: 'static,
288    {
289        BoxBiPredicate::new(move |first, second| self.test(first, second))
290    }
291
292    /// Converts this bi-predicate into an `RcBiPredicate`.
293    ///
294    /// # Returns
295    ///
296    /// An `RcBiPredicate` wrapping this bi-predicate.
297    ///
298    /// # Default Implementation
299    ///
300    /// The default implementation wraps the bi-predicate in a
301    /// closure that calls `test`, providing automatic conversion
302    /// for custom types that only implement the core `test`
303    /// method.
304    fn into_rc(self) -> RcBiPredicate<T, U>
305    where
306        Self: Sized + 'static,
307        T: 'static,
308        U: 'static,
309    {
310        RcBiPredicate::new(move |first, second| self.test(first, second))
311    }
312
313    /// Converts this bi-predicate into an `ArcBiPredicate`.
314    ///
315    /// # Returns
316    ///
317    /// An `ArcBiPredicate` wrapping this bi-predicate.
318    ///
319    /// # Default Implementation
320    ///
321    /// The default implementation wraps the bi-predicate in a
322    /// closure that calls `test`, providing automatic conversion
323    /// for custom types that only implement the core `test`
324    /// method. Note that this requires `Send + Sync` bounds for
325    /// thread-safe sharing.
326    fn into_arc(self) -> ArcBiPredicate<T, U>
327    where
328        Self: Sized + Send + Sync + 'static,
329        T: Send + Sync + 'static,
330        U: Send + Sync + 'static,
331    {
332        ArcBiPredicate::new(move |first, second| self.test(first, second))
333    }
334
335    /// Converts this bi-predicate into a closure that can be used
336    /// directly with standard library methods.
337    ///
338    /// This method consumes the bi-predicate and returns a closure
339    /// with signature `Fn(&T, &U) -> bool`. Since `Fn` is a subtrait
340    /// of `FnMut`, the returned closure can be used in any context
341    /// that requires either `Fn(&T, &U) -> bool` or
342    /// `FnMut(&T, &U) -> bool`.
343    ///
344    /// # Returns
345    ///
346    /// A closure implementing `Fn(&T, &U) -> bool` (also usable as
347    /// `FnMut(&T, &U) -> bool`).
348    ///
349    /// # Default Implementation
350    ///
351    /// The default implementation returns a closure that calls the
352    /// `test` method, providing automatic conversion for custom
353    /// types.
354    ///
355    /// # Examples
356    ///
357    /// ## Using with Iterator Methods
358    ///
359    /// ```rust
360    /// use prism3_function::bi_predicate::{BiPredicate,
361    ///     BoxBiPredicate};
362    ///
363    /// let pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
364    ///
365    /// let pairs = vec![(1, 2), (-1, 3), (5, -6)];
366    /// let mut closure = pred.into_fn();
367    /// let positives: Vec<_> = pairs.iter()
368    ///     .filter(|(x, y)| closure(x, y))
369    ///     .collect();
370    /// assert_eq!(positives, vec![&(1, 2), &(-1, 3)]);
371    /// ```
372    fn into_fn(self) -> impl Fn(&T, &U) -> bool
373    where
374        Self: Sized + 'static,
375        T: 'static,
376        U: 'static,
377    {
378        move |first, second| self.test(first, second)
379    }
380
381    fn to_box(&self) -> BoxBiPredicate<T, U>
382    where
383        Self: Sized + Clone + 'static,
384        T: 'static,
385        U: 'static,
386    {
387        self.clone().into_box()
388    }
389
390    fn to_rc(&self) -> RcBiPredicate<T, U>
391    where
392        Self: Sized + Clone + 'static,
393        T: 'static,
394        U: 'static,
395    {
396        self.clone().into_rc()
397    }
398
399    fn to_arc(&self) -> ArcBiPredicate<T, U>
400    where
401        Self: Sized + Clone + Send + Sync + 'static,
402        T: Send + Sync + 'static,
403        U: Send + Sync + 'static,
404    {
405        self.clone().into_arc()
406    }
407
408    fn to_fn(&self) -> impl Fn(&T, &U) -> bool
409    where
410        Self: Sized + Clone + 'static,
411        T: 'static,
412        U: 'static,
413    {
414        self.clone().into_fn()
415    }
416}
417
418/// A Box-based bi-predicate with single ownership.
419///
420/// This type is suitable for one-time use scenarios where the
421/// bi-predicate does not need to be cloned or shared. Composition
422/// methods consume `self`, reflecting the single-ownership model.
423///
424/// # Examples
425///
426/// ```rust
427/// use prism3_function::bi_predicate::{BiPredicate, BoxBiPredicate};
428///
429/// let pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
430/// assert!(pred.test(&5, &3));
431///
432/// // Chaining consumes the bi-predicate
433/// let combined = pred.and(BoxBiPredicate::new(|x, y| x > y));
434/// assert!(combined.test(&10, &5));
435/// ```
436///
437/// # Author
438///
439/// Haixing Hu
440pub struct BoxBiPredicate<T, U> {
441    function: Box<BiPredicateFn<T, U>>,
442    name: Option<String>,
443}
444
445impl<T, U> BoxBiPredicate<T, U> {
446    /// Creates a new `BoxBiPredicate` from a closure.
447    ///
448    /// # Parameters
449    ///
450    /// * `f` - The closure to wrap.
451    ///
452    /// # Returns
453    ///
454    /// A new `BoxBiPredicate` instance.
455    pub fn new<F>(f: F) -> Self
456    where
457        F: Fn(&T, &U) -> bool + 'static,
458    {
459        Self {
460            function: Box::new(f),
461            name: None,
462        }
463    }
464
465    /// Creates a named `BoxBiPredicate` from a closure.
466    ///
467    /// # Parameters
468    ///
469    /// * `name` - The name for this bi-predicate.
470    /// * `f` - The closure to wrap.
471    ///
472    /// # Returns
473    ///
474    /// A new named `BoxBiPredicate` instance.
475    pub fn new_with_name<F>(name: &str, f: F) -> Self
476    where
477        F: Fn(&T, &U) -> bool + 'static,
478    {
479        Self {
480            function: Box::new(f),
481            name: Some(name.to_string()),
482        }
483    }
484
485    /// Creates a bi-predicate that always returns `true`.
486    ///
487    /// # Returns
488    ///
489    /// A new `BoxBiPredicate` that always returns `true`.
490    ///
491    /// # Examples
492    ///
493    /// ```rust
494    /// use prism3_function::bi_predicate::{BiPredicate, BoxBiPredicate};
495    ///
496    /// let pred: BoxBiPredicate<i32, i32> = BoxBiPredicate::always_true();
497    /// assert!(pred.test(&42, &10));
498    /// assert!(pred.test(&-1, &5));
499    /// assert!(pred.test(&0, &0));
500    /// ```
501    pub fn always_true() -> Self {
502        Self {
503            function: Box::new(|_, _| true),
504            name: Some(ALWAYS_TRUE_NAME.to_string()),
505        }
506    }
507
508    /// Creates a bi-predicate that always returns `false`.
509    ///
510    /// # Returns
511    ///
512    /// A new `BoxBiPredicate` that always returns `false`.
513    ///
514    /// # Examples
515    ///
516    /// ```rust
517    /// use prism3_function::bi_predicate::{BiPredicate, BoxBiPredicate};
518    ///
519    /// let pred: BoxBiPredicate<i32, i32> = BoxBiPredicate::always_false();
520    /// assert!(!pred.test(&42, &10));
521    /// assert!(!pred.test(&-1, &5));
522    /// assert!(!pred.test(&0, &0));
523    /// ```
524    pub fn always_false() -> Self {
525        Self {
526            function: Box::new(|_, _| false),
527            name: Some(ALWAYS_FALSE_NAME.to_string()),
528        }
529    }
530
531    /// Returns the name of this bi-predicate, if set.
532    ///
533    /// # Returns
534    ///
535    /// An `Option` containing the bi-predicate's name.
536    pub fn name(&self) -> Option<&str> {
537        self.name.as_deref()
538    }
539
540    /// Sets the name of this bi-predicate.
541    ///
542    /// # Parameters
543    ///
544    /// * `name` - The new name for this bi-predicate.
545    pub fn set_name(&mut self, name: &str) {
546        self.name = Some(name.to_string());
547    }
548
549    /// Returns a bi-predicate that represents the logical AND of this
550    /// bi-predicate and another.
551    ///
552    /// This method consumes `self` due to single-ownership semantics.
553    ///
554    /// # Parameters
555    ///
556    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
557    ///   is passed by value and will transfer ownership.** If you need to
558    ///   preserve the original bi-predicate, clone it first (if it implements
559    ///   `Clone`). Can be:
560    ///   - A closure: `|x: &T, y: &U| -> bool`
561    ///   - A function pointer: `fn(&T, &U) -> bool`
562    ///   - Another `BoxBiPredicate<T, U>`
563    ///   - An `RcBiPredicate<T, U>`
564    ///   - An `ArcBiPredicate<T, U>`
565    ///   - Any type implementing `BiPredicate<T, U>`
566    ///
567    /// # Returns
568    ///
569    /// A new `BoxBiPredicate` representing the logical AND.
570    pub fn and<P>(self, other: P) -> BoxBiPredicate<T, U>
571    where
572        P: BiPredicate<T, U> + 'static,
573        T: 'static,
574        U: 'static,
575    {
576        BoxBiPredicate::new(move |first, second| {
577            (self.function)(first, second) && other.test(first, second)
578        })
579    }
580
581    /// Returns a bi-predicate that represents the logical OR of this
582    /// bi-predicate and another.
583    ///
584    /// This method consumes `self` due to single-ownership semantics.
585    ///
586    /// # Parameters
587    ///
588    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
589    ///   is passed by value and will transfer ownership.** If you need to
590    ///   preserve the original bi-predicate, clone it first (if it implements
591    ///   `Clone`). Can be:
592    ///   - A closure: `|x: &T, y: &U| -> bool`
593    ///   - A function pointer: `fn(&T, &U) -> bool`
594    ///   - Another `BoxBiPredicate<T, U>`
595    ///   - An `RcBiPredicate<T, U>`
596    ///   - An `ArcBiPredicate<T, U>`
597    ///   - Any type implementing `BiPredicate<T, U>`
598    ///
599    /// # Returns
600    ///
601    /// A new `BoxBiPredicate` representing the logical OR.
602    pub fn or<P>(self, other: P) -> BoxBiPredicate<T, U>
603    where
604        P: BiPredicate<T, U> + 'static,
605        T: 'static,
606        U: 'static,
607    {
608        BoxBiPredicate::new(move |first, second| {
609            (self.function)(first, second) || other.test(first, second)
610        })
611    }
612
613    /// Returns a bi-predicate that represents the logical negation of
614    /// this bi-predicate.
615    ///
616    /// This method consumes `self` due to single-ownership semantics.
617    ///
618    /// # Returns
619    ///
620    /// A new `BoxBiPredicate` representing the logical negation.
621    #[allow(clippy::should_implement_trait)]
622    pub fn not(self) -> BoxBiPredicate<T, U>
623    where
624        T: 'static,
625        U: 'static,
626    {
627        BoxBiPredicate::new(move |first, second| !(self.function)(first, second))
628    }
629
630    /// Returns a bi-predicate that represents the logical NAND (NOT
631    /// AND) of this bi-predicate and another.
632    ///
633    /// NAND returns `true` unless both bi-predicates are `true`.
634    /// Equivalent to `!(self AND other)`.
635    ///
636    /// This method consumes `self` due to single-ownership semantics.
637    ///
638    /// # Parameters
639    ///
640    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
641    ///   is passed by value and will transfer ownership.** If you need to
642    ///   preserve the original bi-predicate, clone it first (if it implements
643    ///   `Clone`). Can be:
644    ///   - A closure: `|x: &T, y: &U| -> bool`
645    ///   - A function pointer: `fn(&T, &U) -> bool`
646    ///   - Another `BoxBiPredicate<T, U>`
647    ///   - An `RcBiPredicate<T, U>`
648    ///   - An `ArcBiPredicate<T, U>`
649    ///   - Any type implementing `BiPredicate<T, U>`
650    ///
651    /// # Returns
652    ///
653    /// A new `BoxBiPredicate` representing the logical NAND.
654    pub fn nand<P>(self, other: P) -> BoxBiPredicate<T, U>
655    where
656        P: BiPredicate<T, U> + 'static,
657        T: 'static,
658        U: 'static,
659    {
660        BoxBiPredicate::new(move |first, second| {
661            !((self.function)(first, second) && other.test(first, second))
662        })
663    }
664
665    /// Returns a bi-predicate that represents the logical XOR
666    /// (exclusive OR) of this bi-predicate and another.
667    ///
668    /// XOR returns `true` if exactly one of the bi-predicates is
669    /// `true`.
670    ///
671    /// This method consumes `self` due to single-ownership semantics.
672    ///
673    /// # Parameters
674    ///
675    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
676    ///   is passed by value and will transfer ownership.** If you need to
677    ///   preserve the original bi-predicate, clone it first (if it implements
678    ///   `Clone`). Can be:
679    ///   - A closure: `|x: &T, y: &U| -> bool`
680    ///   - A function pointer: `fn(&T, &U) -> bool`
681    ///   - Another `BoxBiPredicate<T, U>`
682    ///   - An `RcBiPredicate<T, U>`
683    ///   - An `ArcBiPredicate<T, U>`
684    ///   - Any type implementing `BiPredicate<T, U>`
685    ///
686    /// # Returns
687    ///
688    /// A new `BoxBiPredicate` representing the logical XOR.
689    pub fn xor<P>(self, other: P) -> BoxBiPredicate<T, U>
690    where
691        P: BiPredicate<T, U> + 'static,
692        T: 'static,
693        U: 'static,
694    {
695        BoxBiPredicate::new(move |first, second| {
696            (self.function)(first, second) ^ other.test(first, second)
697        })
698    }
699
700    /// Returns a bi-predicate that represents the logical NOR (NOT
701    /// OR) of this bi-predicate and another.
702    ///
703    /// NOR returns `true` only if both bi-predicates are `false`.
704    /// Equivalent to `!(self OR other)`.
705    ///
706    /// This method consumes `self` due to single-ownership semantics.
707    ///
708    /// # Parameters
709    ///
710    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
711    ///   is passed by value and will transfer ownership.** If you need to
712    ///   preserve the original bi-predicate, clone it first (if it implements
713    ///   `Clone`). Can be:
714    ///   - A closure: `|x: &T, y: &U| -> bool`
715    ///   - A function pointer: `fn(&T, &U) -> bool`
716    ///   - Another `BoxBiPredicate<T, U>`
717    ///   - An `RcBiPredicate<T, U>`
718    ///   - An `ArcBiPredicate<T, U>`
719    ///   - Any type implementing `BiPredicate<T, U>`
720    ///
721    /// # Returns
722    ///
723    /// A new `BoxBiPredicate` representing the logical NOR.
724    pub fn nor<P>(self, other: P) -> BoxBiPredicate<T, U>
725    where
726        P: BiPredicate<T, U> + 'static,
727        T: 'static,
728        U: 'static,
729    {
730        BoxBiPredicate::new(move |first, second| {
731            !((self.function)(first, second) || other.test(first, second))
732        })
733    }
734}
735
736impl<T, U> BiPredicate<T, U> for BoxBiPredicate<T, U> {
737    fn test(&self, first: &T, second: &U) -> bool {
738        (self.function)(first, second)
739    }
740
741    // Use optimized zero-cost conversion for into_box
742    fn into_box(self) -> BoxBiPredicate<T, U>
743    where
744        T: 'static,
745        U: 'static,
746    {
747        self
748    }
749
750    fn into_rc(self) -> RcBiPredicate<T, U>
751    where
752        T: 'static,
753        U: 'static,
754    {
755        RcBiPredicate {
756            function: Rc::new(move |first, second| (self.function)(first, second)),
757            name: self.name.clone(),
758        }
759    }
760
761    // do NOT override BoxBiPredicate::into_arc() because BoxBiPredicate is not Send + Sync
762    // and calling BoxBiPredicate::into_arc() will cause a compile error
763
764    fn into_fn(self) -> impl Fn(&T, &U) -> bool
765    where
766        Self: Sized + 'static,
767        T: 'static,
768        U: 'static,
769    {
770        move |first, second| (self.function)(first, second)
771    }
772
773    // do NOT override BoxBiPredicate::to_xxx() because BoxBiPredicate is not Clone
774    // and calling BoxBiPredicate::to_xxx() will cause a compile error
775}
776
777impl<T, U> Display for BoxBiPredicate<T, U> {
778    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
779        write!(
780            f,
781            "BoxBiPredicate({})",
782            self.name.as_deref().unwrap_or("unnamed")
783        )
784    }
785}
786
787impl<T, U> Debug for BoxBiPredicate<T, U> {
788    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
789        f.debug_struct("BoxBiPredicate")
790            .field("name", &self.name)
791            .finish()
792    }
793}
794
795/// An Rc-based bi-predicate with single-threaded shared ownership.
796///
797/// This type is suitable for scenarios where the bi-predicate needs
798/// to be reused in a single-threaded context. Composition methods
799/// borrow `&self`, allowing the original bi-predicate to remain
800/// usable after composition.
801///
802/// # Examples
803///
804/// ```rust
805/// use prism3_function::bi_predicate::{BiPredicate, RcBiPredicate};
806///
807/// let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
808/// assert!(pred.test(&5, &3));
809///
810/// // Original bi-predicate remains usable after composition
811/// let combined = pred.and(RcBiPredicate::new(|x, y| x > y));
812/// assert!(pred.test(&5, &3));  // Still works
813/// ```
814///
815/// # Author
816///
817/// Haixing Hu
818pub struct RcBiPredicate<T, U> {
819    function: Rc<BiPredicateFn<T, U>>,
820    name: Option<String>,
821}
822
823impl<T, U> RcBiPredicate<T, U> {
824    /// Creates a new `RcBiPredicate` from a closure.
825    ///
826    /// # Parameters
827    ///
828    /// * `f` - The closure to wrap.
829    ///
830    /// # Returns
831    ///
832    /// A new `RcBiPredicate` instance.
833    pub fn new<F>(f: F) -> Self
834    where
835        F: Fn(&T, &U) -> bool + 'static,
836    {
837        Self {
838            function: Rc::new(f),
839            name: None,
840        }
841    }
842
843    /// Creates a named `RcBiPredicate` from a closure.
844    ///
845    /// # Parameters
846    ///
847    /// * `name` - The name for this bi-predicate.
848    /// * `f` - The closure to wrap.
849    ///
850    /// # Returns
851    ///
852    /// A new named `RcBiPredicate` instance.
853    pub fn new_with_name<F>(name: &str, f: F) -> Self
854    where
855        F: Fn(&T, &U) -> bool + 'static,
856    {
857        Self {
858            function: Rc::new(f),
859            name: Some(name.to_string()),
860        }
861    }
862
863    /// Creates a bi-predicate that always returns `true`.
864    ///
865    /// # Returns
866    ///
867    /// A new `RcBiPredicate` that always returns `true`.
868    ///
869    /// # Examples
870    ///
871    /// ```rust
872    /// use prism3_function::bi_predicate::{BiPredicate, RcBiPredicate};
873    ///
874    /// let pred: RcBiPredicate<i32, i32> = RcBiPredicate::always_true();
875    /// assert!(pred.test(&42, &10));
876    /// assert!(pred.test(&-1, &5));
877    /// assert!(pred.test(&0, &0));
878    /// ```
879    pub fn always_true() -> Self {
880        Self {
881            function: Rc::new(|_, _| true),
882            name: Some(ALWAYS_TRUE_NAME.to_string()),
883        }
884    }
885
886    /// Creates a bi-predicate that always returns `false`.
887    ///
888    /// # Returns
889    ///
890    /// A new `RcBiPredicate` that always returns `false`.
891    ///
892    /// # Examples
893    ///
894    /// ```rust
895    /// use prism3_function::bi_predicate::{BiPredicate, RcBiPredicate};
896    ///
897    /// let pred: RcBiPredicate<i32, i32> = RcBiPredicate::always_false();
898    /// assert!(!pred.test(&42, &10));
899    /// assert!(!pred.test(&-1, &5));
900    /// assert!(!pred.test(&0, &0));
901    /// ```
902    pub fn always_false() -> Self {
903        Self {
904            function: Rc::new(|_, _| false),
905            name: Some(ALWAYS_FALSE_NAME.to_string()),
906        }
907    }
908
909    /// Returns the name of this bi-predicate, if set.
910    ///
911    /// # Returns
912    ///
913    /// An `Option` containing the bi-predicate's name.
914    pub fn name(&self) -> Option<&str> {
915        self.name.as_deref()
916    }
917
918    /// Sets the name of this bi-predicate.
919    ///
920    /// # Parameters
921    ///
922    /// * `name` - The new name for this bi-predicate.
923    pub fn set_name(&mut self, name: &str) {
924        self.name = Some(name.to_string());
925    }
926
927    /// Returns a bi-predicate that represents the logical AND of this
928    /// bi-predicate and another.
929    ///
930    /// # Parameters
931    ///
932    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
933    ///   is passed by value and will transfer ownership.** If you need to
934    ///   preserve the original bi-predicate, clone it first (if it implements
935    ///   `Clone`). Can be:
936    ///   - A closure: `|x: &T, y: &U| -> bool`
937    ///   - A function pointer: `fn(&T, &U) -> bool`
938    ///   - A `BoxBiPredicate<T, U>`
939    ///   - Another `RcBiPredicate<T, U>` (will be moved)
940    ///   - An `ArcBiPredicate<T, U>`
941    ///   - Any type implementing `BiPredicate<T, U>`
942    ///
943    /// # Returns
944    ///
945    /// A new `RcBiPredicate` representing the logical AND.
946    pub fn and<P>(&self, other: P) -> RcBiPredicate<T, U>
947    where
948        P: BiPredicate<T, U> + 'static,
949        T: 'static,
950        U: 'static,
951    {
952        let self_fn = Rc::clone(&self.function);
953        RcBiPredicate {
954            function: Rc::new(move |first, second| {
955                self_fn(first, second) && other.test(first, second)
956            }),
957            name: None,
958        }
959    }
960
961    /// Returns a bi-predicate that represents the logical OR of this
962    /// bi-predicate and another.
963    ///
964    /// # Parameters
965    ///
966    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
967    ///   is passed by value and will transfer ownership.** If you need to
968    ///   preserve the original bi-predicate, clone it first (if it implements
969    ///   `Clone`). Can be:
970    ///   - A closure: `|x: &T, y: &U| -> bool`
971    ///   - A function pointer: `fn(&T, &U) -> bool`
972    ///   - A `BoxBiPredicate<T, U>`
973    ///   - Another `RcBiPredicate<T, U>` (will be moved)
974    ///   - An `ArcBiPredicate<T, U>`
975    ///   - Any type implementing `BiPredicate<T, U>`
976    ///
977    /// # Returns
978    ///
979    /// A new `RcBiPredicate` representing the logical OR.
980    pub fn or<P>(&self, other: P) -> RcBiPredicate<T, U>
981    where
982        P: BiPredicate<T, U> + 'static,
983        T: 'static,
984        U: 'static,
985    {
986        let self_fn = Rc::clone(&self.function);
987        RcBiPredicate {
988            function: Rc::new(move |first, second| {
989                self_fn(first, second) || other.test(first, second)
990            }),
991            name: None,
992        }
993    }
994
995    /// Returns a bi-predicate that represents the logical negation of
996    /// this bi-predicate.
997    ///
998    /// # Returns
999    ///
1000    /// A new `RcBiPredicate` representing the logical negation.
1001    #[allow(clippy::should_implement_trait)]
1002    pub fn not(&self) -> RcBiPredicate<T, U>
1003    where
1004        T: 'static,
1005        U: 'static,
1006    {
1007        let self_fn = Rc::clone(&self.function);
1008        RcBiPredicate {
1009            function: Rc::new(move |first, second| !self_fn(first, second)),
1010            name: None,
1011        }
1012    }
1013
1014    /// Returns a bi-predicate that represents the logical NAND (NOT
1015    /// AND) of this bi-predicate and another.
1016    ///
1017    /// NAND returns `true` unless both bi-predicates are `true`.
1018    /// Equivalent to `!(self AND other)`.
1019    ///
1020    /// # Parameters
1021    ///
1022    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1023    ///   is passed by value and will transfer ownership.** If you need to
1024    ///   preserve the original bi-predicate, clone it first (if it implements
1025    ///   `Clone`). Can be:
1026    ///   - A closure: `|x: &T, y: &U| -> bool`
1027    ///   - A function pointer: `fn(&T, &U) -> bool`
1028    ///   - A `BoxBiPredicate<T, U>`
1029    ///   - Another `RcBiPredicate<T, U>` (will be moved)
1030    ///   - An `ArcBiPredicate<T, U>`
1031    ///   - Any type implementing `BiPredicate<T, U>`
1032    ///
1033    /// # Returns
1034    ///
1035    /// A new `RcBiPredicate` representing the logical NAND.
1036    pub fn nand<P>(&self, other: P) -> RcBiPredicate<T, U>
1037    where
1038        P: BiPredicate<T, U> + 'static,
1039        T: 'static,
1040        U: 'static,
1041    {
1042        let self_fn = Rc::clone(&self.function);
1043        RcBiPredicate {
1044            function: Rc::new(move |first, second| {
1045                !(self_fn(first, second) && other.test(first, second))
1046            }),
1047            name: None,
1048        }
1049    }
1050
1051    /// Returns a bi-predicate that represents the logical XOR
1052    /// (exclusive OR) of this bi-predicate and another.
1053    ///
1054    /// XOR returns `true` if exactly one of the bi-predicates is
1055    /// `true`.
1056    ///
1057    /// # Parameters
1058    ///
1059    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1060    ///   is passed by value and will transfer ownership.** If you need to
1061    ///   preserve the original bi-predicate, clone it first (if it implements
1062    ///   `Clone`). Can be:
1063    ///   - A closure: `|x: &T, y: &U| -> bool`
1064    ///   - A function pointer: `fn(&T, &U) -> bool`
1065    ///   - A `BoxBiPredicate<T, U>`
1066    ///   - Another `RcBiPredicate<T, U>` (will be moved)
1067    ///   - An `ArcBiPredicate<T, U>`
1068    ///   - Any type implementing `BiPredicate<T, U>`
1069    ///
1070    /// # Returns
1071    ///
1072    /// A new `RcBiPredicate` representing the logical XOR.
1073    pub fn xor<P>(&self, other: P) -> RcBiPredicate<T, U>
1074    where
1075        P: BiPredicate<T, U> + 'static,
1076        T: 'static,
1077        U: 'static,
1078    {
1079        let self_fn = Rc::clone(&self.function);
1080        RcBiPredicate {
1081            function: Rc::new(move |first, second| {
1082                self_fn(first, second) ^ other.test(first, second)
1083            }),
1084            name: None,
1085        }
1086    }
1087
1088    /// Returns a bi-predicate that represents the logical NOR (NOT
1089    /// OR) of this bi-predicate and another.
1090    ///
1091    /// NOR returns `true` only if both bi-predicates are `false`.
1092    /// Equivalent to `!(self OR other)`.
1093    ///
1094    /// # Parameters
1095    ///
1096    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1097    ///   is passed by value and will transfer ownership.** If you need to
1098    ///   preserve the original bi-predicate, clone it first (if it implements
1099    ///   `Clone`). Can be:
1100    ///   - A closure: `|x: &T, y: &U| -> bool`
1101    ///   - A function pointer: `fn(&T, &U) -> bool`
1102    ///   - A `BoxBiPredicate<T, U>`
1103    ///   - Another `RcBiPredicate<T, U>` (will be moved)
1104    ///   - An `ArcBiPredicate<T, U>`
1105    ///   - Any type implementing `BiPredicate<T, U>`
1106    ///
1107    /// # Returns
1108    ///
1109    /// A new `RcBiPredicate` representing the logical NOR.
1110    pub fn nor<P>(&self, other: P) -> RcBiPredicate<T, U>
1111    where
1112        P: BiPredicate<T, U> + 'static,
1113        T: 'static,
1114        U: 'static,
1115    {
1116        let self_fn = Rc::clone(&self.function);
1117        RcBiPredicate {
1118            function: Rc::new(move |first, second| {
1119                !(self_fn(first, second) || other.test(first, second))
1120            }),
1121            name: None,
1122        }
1123    }
1124}
1125
1126impl<T, U> BiPredicate<T, U> for RcBiPredicate<T, U> {
1127    fn test(&self, first: &T, second: &U) -> bool {
1128        (self.function)(first, second)
1129    }
1130
1131    // Use optimized conversion for into_box that preserves the
1132    // existing Rc
1133    fn into_box(self) -> BoxBiPredicate<T, U>
1134    where
1135        T: 'static,
1136        U: 'static,
1137    {
1138        BoxBiPredicate {
1139            function: Box::new(move |first, second| (self.function)(first, second)),
1140            name: self.name,
1141        }
1142    }
1143
1144    // Use optimized zero-cost conversion for into_rc
1145    fn into_rc(self) -> RcBiPredicate<T, U>
1146    where
1147        T: 'static,
1148        U: 'static,
1149    {
1150        self
1151    }
1152
1153    // do NOT override RcBiPredicate::into_arc() because RcBiPredicate is not Send + Sync
1154    // and calling RcBiPredicate::into_arc() will cause a compile error
1155
1156    fn into_fn(self) -> impl Fn(&T, &U) -> bool
1157    where
1158        Self: Sized + 'static,
1159        T: 'static,
1160        U: 'static,
1161    {
1162        move |first, second| (self.function)(first, second)
1163    }
1164
1165    fn to_box(&self) -> BoxBiPredicate<T, U>
1166    where
1167        T: 'static,
1168        U: 'static,
1169    {
1170        let self_fn = self.function.clone();
1171        BoxBiPredicate {
1172            function: Box::new(move |first, second| self_fn(first, second)),
1173            name: self.name.clone(),
1174        }
1175    }
1176
1177    // do NOT override RcBiPredicate::to_rc() because RcBiPredicate is not Clone
1178    // and calling RcBiPredicate::to_rc() will cause a compile error
1179
1180    fn to_rc(&self) -> RcBiPredicate<T, U>
1181    where
1182        T: 'static,
1183        U: 'static,
1184    {
1185        self.clone()
1186    }
1187
1188    fn to_fn(&self) -> impl Fn(&T, &U) -> bool
1189    where
1190        T: 'static,
1191        U: 'static,
1192    {
1193        let self_fn = self.function.clone();
1194        move |first, second| self_fn(first, second)
1195    }
1196}
1197
1198impl<T, U> Clone for RcBiPredicate<T, U> {
1199    /// Clones this bi-predicate.
1200    ///
1201    /// Creates a new instance that shares the underlying function with
1202    /// the original, allowing multiple references to the same
1203    /// bi-predicate logic.
1204    fn clone(&self) -> Self {
1205        RcBiPredicate {
1206            function: Rc::clone(&self.function),
1207            name: self.name.clone(),
1208        }
1209    }
1210}
1211
1212impl<T, U> Display for RcBiPredicate<T, U> {
1213    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1214        write!(
1215            f,
1216            "RcBiPredicate({})",
1217            self.name.as_deref().unwrap_or("unnamed")
1218        )
1219    }
1220}
1221
1222impl<T, U> Debug for RcBiPredicate<T, U> {
1223    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1224        f.debug_struct("RcBiPredicate")
1225            .field("name", &self.name)
1226            .finish()
1227    }
1228}
1229
1230/// An Arc-based bi-predicate with thread-safe shared ownership.
1231///
1232/// This type is suitable for scenarios where the bi-predicate needs
1233/// to be shared across threads. Composition methods borrow `&self`,
1234/// allowing the original bi-predicate to remain usable after
1235/// composition.
1236///
1237/// # Examples
1238///
1239/// ```rust
1240/// use prism3_function::bi_predicate::{BiPredicate, ArcBiPredicate};
1241///
1242/// let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
1243/// assert!(pred.test(&5, &3));
1244///
1245/// // Original bi-predicate remains usable after composition
1246/// let combined = pred.and(ArcBiPredicate::new(|x, y| x > y));
1247/// assert!(pred.test(&5, &3));  // Still works
1248///
1249/// // Can be cloned and sent across threads
1250/// let pred_clone = pred.clone();
1251/// std::thread::spawn(move || {
1252///     assert!(pred_clone.test(&10, &5));
1253/// }).join().unwrap();
1254/// ```
1255///
1256/// # Author
1257///
1258/// Haixing Hu
1259pub struct ArcBiPredicate<T, U> {
1260    function: Arc<SendSyncBiPredicateFn<T, U>>,
1261    name: Option<String>,
1262}
1263
1264impl<T, U> ArcBiPredicate<T, U> {
1265    /// Creates a new `ArcBiPredicate` from a closure.
1266    ///
1267    /// # Parameters
1268    ///
1269    /// * `f` - The closure to wrap.
1270    ///
1271    /// # Returns
1272    ///
1273    /// A new `ArcBiPredicate` instance.
1274    pub fn new<F>(f: F) -> Self
1275    where
1276        F: Fn(&T, &U) -> bool + Send + Sync + 'static,
1277    {
1278        Self {
1279            function: Arc::new(f),
1280            name: None,
1281        }
1282    }
1283
1284    /// Creates a named `ArcBiPredicate` from a closure.
1285    ///
1286    /// # Parameters
1287    ///
1288    /// * `name` - The name for this bi-predicate.
1289    /// * `f` - The closure to wrap.
1290    ///
1291    /// # Returns
1292    ///
1293    /// A new named `ArcBiPredicate` instance.
1294    pub fn new_with_name<F>(name: &str, f: F) -> Self
1295    where
1296        F: Fn(&T, &U) -> bool + Send + Sync + 'static,
1297    {
1298        Self {
1299            function: Arc::new(f),
1300            name: Some(name.to_string()),
1301        }
1302    }
1303
1304    /// Creates a bi-predicate that always returns `true`.
1305    ///
1306    /// # Returns
1307    ///
1308    /// A new `ArcBiPredicate` that always returns `true`.
1309    ///
1310    /// # Examples
1311    ///
1312    /// ```rust
1313    /// use prism3_function::bi_predicate::{BiPredicate, ArcBiPredicate};
1314    ///
1315    /// let pred: ArcBiPredicate<i32, i32> = ArcBiPredicate::always_true();
1316    /// assert!(pred.test(&42, &10));
1317    /// assert!(pred.test(&-1, &5));
1318    /// assert!(pred.test(&0, &0));
1319    /// ```
1320    pub fn always_true() -> Self {
1321        Self {
1322            function: Arc::new(|_, _| true),
1323            name: Some(ALWAYS_TRUE_NAME.to_string()),
1324        }
1325    }
1326
1327    /// Creates a bi-predicate that always returns `false`.
1328    ///
1329    /// # Returns
1330    ///
1331    /// A new `ArcBiPredicate` that always returns `false`.
1332    ///
1333    /// # Examples
1334    ///
1335    /// ```rust
1336    /// use prism3_function::bi_predicate::{BiPredicate, ArcBiPredicate};
1337    ///
1338    /// let pred: ArcBiPredicate<i32, i32> = ArcBiPredicate::always_false();
1339    /// assert!(!pred.test(&42, &10));
1340    /// assert!(!pred.test(&-1, &5));
1341    /// assert!(!pred.test(&0, &0));
1342    /// ```
1343    pub fn always_false() -> Self {
1344        Self {
1345            function: Arc::new(|_, _| false),
1346            name: Some(ALWAYS_FALSE_NAME.to_string()),
1347        }
1348    }
1349
1350    /// Returns the name of this bi-predicate, if set.
1351    ///
1352    /// # Returns
1353    ///
1354    /// An `Option` containing the bi-predicate's name.
1355    pub fn name(&self) -> Option<&str> {
1356        self.name.as_deref()
1357    }
1358
1359    /// Sets the name of this bi-predicate.
1360    ///
1361    /// # Parameters
1362    ///
1363    /// * `name` - The new name for this bi-predicate.
1364    pub fn set_name(&mut self, name: &str) {
1365        self.name = Some(name.to_string());
1366    }
1367
1368    /// Returns a bi-predicate that represents the logical AND of this
1369    /// bi-predicate and another.
1370    ///
1371    /// # Parameters
1372    ///
1373    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1374    ///   is passed by value and will transfer ownership.** If you need to
1375    ///   preserve the original bi-predicate, clone it first (if it implements
1376    ///   `Clone`). Can be:
1377    ///   - A closure: `|x: &T, y: &U| -> bool`
1378    ///   - A function pointer: `fn(&T, &U) -> bool`
1379    ///   - A `BoxBiPredicate<T, U>`
1380    ///   - An `RcBiPredicate<T, U>`
1381    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1382    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1383    ///
1384    /// # Returns
1385    ///
1386    /// A new `ArcBiPredicate` representing the logical AND.
1387    pub fn and<P>(&self, other: P) -> ArcBiPredicate<T, U>
1388    where
1389        T: Send + Sync + 'static,
1390        U: Send + Sync + 'static,
1391        P: BiPredicate<T, U> + Send + Sync + 'static,
1392    {
1393        let self_fn = Arc::clone(&self.function);
1394        ArcBiPredicate {
1395            function: Arc::new(move |first, second| {
1396                self_fn(first, second) && other.test(first, second)
1397            }),
1398            name: None,
1399        }
1400    }
1401
1402    /// Returns a bi-predicate that represents the logical OR of this
1403    /// bi-predicate and another.
1404    ///
1405    /// # Parameters
1406    ///
1407    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1408    ///   is passed by value and will transfer ownership.** If you need to
1409    ///   preserve the original bi-predicate, clone it first (if it implements
1410    ///   `Clone`). Can be:
1411    ///   - A closure: `|x: &T, y: &U| -> bool`
1412    ///   - A function pointer: `fn(&T, &U) -> bool`
1413    ///   - A `BoxBiPredicate<T, U>`
1414    ///   - An `RcBiPredicate<T, U>`
1415    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1416    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1417    ///
1418    /// # Returns
1419    ///
1420    /// A new `ArcBiPredicate` representing the logical OR.
1421    /// Thread-safe.
1422    pub fn or<P>(&self, other: P) -> ArcBiPredicate<T, U>
1423    where
1424        T: Send + Sync + 'static,
1425        U: Send + Sync + 'static,
1426        P: BiPredicate<T, U> + Send + Sync + 'static,
1427    {
1428        let self_fn = Arc::clone(&self.function);
1429        ArcBiPredicate {
1430            function: Arc::new(move |first, second| {
1431                self_fn(first, second) || other.test(first, second)
1432            }),
1433            name: None,
1434        }
1435    }
1436
1437    /// Returns a bi-predicate that represents the logical negation of
1438    /// this bi-predicate.
1439    ///
1440    /// # Returns
1441    ///
1442    /// A new `ArcBiPredicate` representing the logical negation.
1443    #[allow(clippy::should_implement_trait)]
1444    pub fn not(&self) -> ArcBiPredicate<T, U>
1445    where
1446        T: Send + Sync + 'static,
1447        U: Send + Sync + 'static,
1448    {
1449        let self_fn = Arc::clone(&self.function);
1450        ArcBiPredicate {
1451            function: Arc::new(move |first, second| !self_fn(first, second)),
1452            name: None,
1453        }
1454    }
1455
1456    /// Returns a bi-predicate that represents the logical NAND (NOT
1457    /// AND) of this bi-predicate and another.
1458    ///
1459    /// NAND returns `true` unless both bi-predicates are `true`.
1460    /// Equivalent to `!(self AND other)`.
1461    ///
1462    /// # Parameters
1463    ///
1464    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1465    ///   is passed by value and will transfer ownership.** If you need to
1466    ///   preserve the original bi-predicate, clone it first (if it implements
1467    ///   `Clone`). Can be:
1468    ///   - A closure: `|x: &T, y: &U| -> bool`
1469    ///   - A function pointer: `fn(&T, &U) -> bool`
1470    ///   - A `BoxBiPredicate<T, U>`
1471    ///   - An `RcBiPredicate<T, U>`
1472    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1473    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1474    ///
1475    /// # Returns
1476    ///
1477    /// A new `ArcBiPredicate` representing the logical NAND.
1478    /// Thread-safe.
1479    pub fn nand<P>(&self, other: P) -> ArcBiPredicate<T, U>
1480    where
1481        T: Send + Sync + 'static,
1482        U: Send + Sync + 'static,
1483        P: BiPredicate<T, U> + Send + Sync + 'static,
1484    {
1485        let self_fn = Arc::clone(&self.function);
1486        ArcBiPredicate {
1487            function: Arc::new(move |first, second| {
1488                !(self_fn(first, second) && other.test(first, second))
1489            }),
1490            name: None,
1491        }
1492    }
1493
1494    /// Returns a bi-predicate that represents the logical XOR
1495    /// (exclusive OR) of this bi-predicate and another.
1496    ///
1497    /// XOR returns `true` if exactly one of the bi-predicates is
1498    /// `true`.
1499    ///
1500    /// # Parameters
1501    ///
1502    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1503    ///   is passed by value and will transfer ownership.** If you need to
1504    ///   preserve the original bi-predicate, clone it first (if it implements
1505    ///   `Clone`). Can be:
1506    ///   - A closure: `|x: &T, y: &U| -> bool`
1507    ///   - A function pointer: `fn(&T, &U) -> bool`
1508    ///   - A `BoxBiPredicate<T, U>`
1509    ///   - An `RcBiPredicate<T, U>`
1510    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1511    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1512    ///
1513    /// # Returns
1514    ///
1515    /// A new `ArcBiPredicate` representing the logical XOR.
1516    pub fn xor<P>(&self, other: P) -> ArcBiPredicate<T, U>
1517    where
1518        T: Send + Sync + 'static,
1519        U: Send + Sync + 'static,
1520        P: BiPredicate<T, U> + Send + Sync + 'static,
1521    {
1522        let self_fn = Arc::clone(&self.function);
1523        ArcBiPredicate {
1524            function: Arc::new(move |first, second| {
1525                self_fn(first, second) ^ other.test(first, second)
1526            }),
1527            name: None,
1528        }
1529    }
1530
1531    /// Returns a bi-predicate that represents the logical NOR (NOT
1532    /// OR) of this bi-predicate and another.
1533    ///
1534    /// NOR returns `true` only if both bi-predicates are `false`.
1535    /// Equivalent to `!(self OR other)`.
1536    ///
1537    /// # Parameters
1538    ///
1539    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1540    ///   is passed by value and will transfer ownership.** If you need to
1541    ///   preserve the original bi-predicate, clone it first (if it implements
1542    ///   `Clone`). Can be:
1543    ///   - A closure: `|x: &T, y: &U| -> bool`
1544    ///   - A function pointer: `fn(&T, &U) -> bool`
1545    ///   - A `BoxBiPredicate<T, U>`
1546    ///   - An `RcBiPredicate<T, U>`
1547    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1548    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1549    ///
1550    /// # Returns
1551    ///
1552    /// A new `ArcBiPredicate` representing the logical NOR.
1553    /// Thread-safe.
1554    pub fn nor<P>(&self, other: P) -> ArcBiPredicate<T, U>
1555    where
1556        T: Send + Sync + 'static,
1557        U: Send + Sync + 'static,
1558        P: BiPredicate<T, U> + Send + Sync + 'static,
1559    {
1560        let self_fn = Arc::clone(&self.function);
1561        ArcBiPredicate {
1562            function: Arc::new(move |first, second| {
1563                !(self_fn(first, second) || other.test(first, second))
1564            }),
1565            name: None,
1566        }
1567    }
1568}
1569
1570impl<T, U> BiPredicate<T, U> for ArcBiPredicate<T, U> {
1571    fn test(&self, first: &T, second: &U) -> bool {
1572        (self.function)(first, second)
1573    }
1574
1575    // Use optimized conversion for into_box that preserves the
1576    // existing Arc
1577    fn into_box(self) -> BoxBiPredicate<T, U>
1578    where
1579        T: 'static,
1580        U: 'static,
1581    {
1582        BoxBiPredicate {
1583            function: Box::new(move |first, second| (self.function)(first, second)),
1584            name: self.name,
1585        }
1586    }
1587
1588    // Use optimized conversion for into_rc that preserves the
1589    // existing Arc
1590    fn into_rc(self) -> RcBiPredicate<T, U>
1591    where
1592        T: 'static,
1593        U: 'static,
1594    {
1595        RcBiPredicate {
1596            function: Rc::new(move |first, second| (self.function)(first, second)),
1597            name: self.name,
1598        }
1599    }
1600
1601    // Use optimized zero-cost conversion for into_arc
1602    fn into_arc(self) -> ArcBiPredicate<T, U>
1603    where
1604        T: Send + Sync + 'static,
1605        U: Send + Sync + 'static,
1606    {
1607        self
1608    }
1609
1610    // Use optimized conversion for into_fn that preserves the
1611    // existing Arc
1612    fn into_fn(self) -> impl Fn(&T, &U) -> bool
1613    where
1614        Self: Sized + 'static,
1615        T: 'static,
1616        U: 'static,
1617    {
1618        move |first, second| (self.function)(first, second)
1619    }
1620
1621    fn to_box(&self) -> BoxBiPredicate<T, U>
1622    where
1623        T: 'static,
1624        U: 'static,
1625    {
1626        let self_fn = self.function.clone();
1627        BoxBiPredicate {
1628            function: Box::new(move |first, second| self_fn(first, second)),
1629            name: self.name.clone(),
1630        }
1631    }
1632
1633    fn to_rc(&self) -> RcBiPredicate<T, U>
1634    where
1635        T: 'static,
1636        U: 'static,
1637    {
1638        let self_fn = self.function.clone();
1639        RcBiPredicate {
1640            function: Rc::new(move |first, second| self_fn(first, second)),
1641            name: self.name.clone(),
1642        }
1643    }
1644
1645    fn to_arc(&self) -> ArcBiPredicate<T, U>
1646    where
1647        T: Send + Sync + 'static,
1648        U: Send + Sync + 'static,
1649    {
1650        self.clone()
1651    }
1652
1653    fn to_fn(&self) -> impl Fn(&T, &U) -> bool
1654    where
1655        T: 'static,
1656        U: 'static,
1657    {
1658        let self_fn = self.function.clone();
1659        move |first, second| self_fn(first, second)
1660    }
1661}
1662
1663impl<T, U> Clone for ArcBiPredicate<T, U> {
1664    /// Clones this bi-predicate.
1665    ///
1666    /// Creates a new instance that shares the underlying function with
1667    /// the original, allowing multiple references to the same
1668    /// bi-predicate logic.
1669    fn clone(&self) -> Self {
1670        ArcBiPredicate {
1671            function: Arc::clone(&self.function),
1672            name: self.name.clone(),
1673        }
1674    }
1675}
1676
1677impl<T, U> Display for ArcBiPredicate<T, U> {
1678    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1679        write!(
1680            f,
1681            "ArcBiPredicate({})",
1682            self.name.as_deref().unwrap_or("unnamed")
1683        )
1684    }
1685}
1686
1687impl<T, U> Debug for ArcBiPredicate<T, U> {
1688    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1689        f.debug_struct("ArcBiPredicate")
1690            .field("name", &self.name)
1691            .finish()
1692    }
1693}
1694
1695// Blanket implementation for all closures that match
1696// Fn(&T, &U) -> bool. This provides optimal implementations for
1697// closures by wrapping them directly into the target type.
1698impl<T: 'static, U: 'static, F> BiPredicate<T, U> for F
1699where
1700    F: Fn(&T, &U) -> bool + 'static,
1701{
1702    fn test(&self, first: &T, second: &U) -> bool {
1703        self(first, second)
1704    }
1705
1706    // Optimal implementation for closures: wrap directly in Box
1707    fn into_box(self) -> BoxBiPredicate<T, U> {
1708        BoxBiPredicate::new(self)
1709    }
1710
1711    // Optimal implementation for closures: wrap directly in Rc
1712    fn into_rc(self) -> RcBiPredicate<T, U> {
1713        RcBiPredicate::new(self)
1714    }
1715
1716    // Optimal implementation for closures: wrap directly in Arc
1717    fn into_arc(self) -> ArcBiPredicate<T, U>
1718    where
1719        Self: Send + Sync,
1720        T: Send + Sync,
1721        U: Send + Sync,
1722    {
1723        ArcBiPredicate::new(self)
1724    }
1725
1726    // Optimal implementation for closures: return self (zero-cost)
1727    fn into_fn(self) -> impl Fn(&T, &U) -> bool {
1728        self
1729    }
1730
1731    fn to_box(&self) -> BoxBiPredicate<T, U>
1732    where
1733        Self: Sized + Clone + 'static,
1734        T: 'static,
1735        U: 'static,
1736    {
1737        BoxBiPredicate::new(self.clone())
1738    }
1739
1740    fn to_rc(&self) -> RcBiPredicate<T, U>
1741    where
1742        Self: Sized + Clone + 'static,
1743        T: 'static,
1744        U: 'static,
1745    {
1746        RcBiPredicate::new(self.clone())
1747    }
1748
1749    fn to_arc(&self) -> ArcBiPredicate<T, U>
1750    where
1751        Self: Sized + Clone + Send + Sync + 'static,
1752        T: Send + Sync + 'static,
1753        U: Send + Sync + 'static,
1754    {
1755        ArcBiPredicate::new(self.clone())
1756    }
1757
1758    fn to_fn(&self) -> impl Fn(&T, &U) -> bool
1759    where
1760        Self: Sized + Clone + 'static,
1761        T: 'static,
1762        U: 'static,
1763    {
1764        self.clone()
1765    }
1766}
1767
1768/// Extension trait providing logical composition methods for closures.
1769///
1770/// This trait is automatically implemented for all closures and
1771/// function pointers that match `Fn(&T, &U) -> bool`, enabling method
1772/// chaining starting from a closure.
1773///
1774/// # Examples
1775///
1776/// ```rust
1777/// use prism3_function::bi_predicate::{BiPredicate, FnBiPredicateOps};
1778///
1779/// let is_sum_positive = |x: &i32, y: &i32| x + y > 0;
1780/// let first_larger = |x: &i32, y: &i32| x > y;
1781///
1782/// // Combine bi-predicates using extension methods
1783/// let pred = is_sum_positive.and(first_larger);
1784/// assert!(pred.test(&10, &5));
1785/// assert!(!pred.test(&3, &8));
1786/// ```
1787///
1788/// # Author
1789///
1790/// Haixing Hu
1791pub trait FnBiPredicateOps<T, U>: Fn(&T, &U) -> bool + Sized + 'static {
1792    /// Returns a bi-predicate that represents the logical AND of this
1793    /// bi-predicate and another.
1794    ///
1795    /// # Parameters
1796    ///
1797    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1798    ///   is passed by value and will transfer ownership.** If you need to
1799    ///   preserve the original bi-predicate, clone it first (if it implements
1800    ///   `Clone`). Can be:
1801    ///   - Another closure: `|x: &T, y: &U| -> bool`
1802    ///   - A function pointer: `fn(&T, &U) -> bool`
1803    ///   - A `BoxBiPredicate<T, U>`
1804    ///   - An `RcBiPredicate<T, U>`
1805    ///   - An `ArcBiPredicate<T, U>`
1806    ///   - Any type implementing `BiPredicate<T, U>`
1807    ///
1808    /// # Returns
1809    ///
1810    /// A `BoxBiPredicate` representing the logical AND.
1811    fn and<P>(self, other: P) -> BoxBiPredicate<T, U>
1812    where
1813        P: BiPredicate<T, U> + 'static,
1814        T: 'static,
1815        U: 'static,
1816    {
1817        BoxBiPredicate::new(move |first, second| self(first, second) && other.test(first, second))
1818    }
1819
1820    /// Returns a bi-predicate that represents the logical OR of this
1821    /// bi-predicate and another.
1822    ///
1823    /// # Parameters
1824    ///
1825    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1826    ///   is passed by value and will transfer ownership.** If you need to
1827    ///   preserve the original bi-predicate, clone it first (if it implements
1828    ///   `Clone`). Can be:
1829    ///   - Another closure: `|x: &T, y: &U| -> bool`
1830    ///   - A function pointer: `fn(&T, &U) -> bool`
1831    ///   - A `BoxBiPredicate<T, U>`
1832    ///   - An `RcBiPredicate<T, U>`
1833    ///   - An `ArcBiPredicate<T, U>`
1834    ///   - Any type implementing `BiPredicate<T, U>`
1835    ///
1836    /// # Returns
1837    ///
1838    /// A `BoxBiPredicate` representing the logical OR.
1839    fn or<P>(self, other: P) -> BoxBiPredicate<T, U>
1840    where
1841        P: BiPredicate<T, U> + 'static,
1842        T: 'static,
1843        U: 'static,
1844    {
1845        BoxBiPredicate::new(move |first, second| self(first, second) || other.test(first, second))
1846    }
1847
1848    /// Returns a bi-predicate that represents the logical negation of
1849    /// this bi-predicate.
1850    ///
1851    /// # Returns
1852    ///
1853    /// A `BoxBiPredicate` representing the logical negation.
1854    fn not(self) -> BoxBiPredicate<T, U>
1855    where
1856        T: 'static,
1857        U: 'static,
1858    {
1859        BoxBiPredicate::new(move |first, second| !self(first, second))
1860    }
1861
1862    /// Returns a bi-predicate that represents the logical NAND (NOT
1863    /// AND) of this bi-predicate and another.
1864    ///
1865    /// NAND returns `true` unless both bi-predicates are `true`.
1866    /// Equivalent to `!(self AND other)`.
1867    ///
1868    /// # Parameters
1869    ///
1870    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1871    ///   is passed by value and will transfer ownership.** If you need to
1872    ///   preserve the original bi-predicate, clone it first (if it implements
1873    ///   `Clone`). Can be:
1874    ///   - Another closure: `|x: &T, y: &U| -> bool`
1875    ///   - A function pointer: `fn(&T, &U) -> bool`
1876    ///   - A `BoxBiPredicate<T, U>`
1877    ///   - An `RcBiPredicate<T, U>`
1878    ///   - An `ArcBiPredicate<T, U>`
1879    ///   - Any type implementing `BiPredicate<T, U>`
1880    ///
1881    /// # Returns
1882    ///
1883    /// A `BoxBiPredicate` representing the logical NAND.
1884    fn nand<P>(self, other: P) -> BoxBiPredicate<T, U>
1885    where
1886        P: BiPredicate<T, U> + 'static,
1887        T: 'static,
1888        U: 'static,
1889    {
1890        BoxBiPredicate::new(move |first, second| {
1891            !(self(first, second) && other.test(first, second))
1892        })
1893    }
1894
1895    /// Returns a bi-predicate that represents the logical XOR
1896    /// (exclusive OR) of this bi-predicate and another.
1897    ///
1898    /// XOR returns `true` if exactly one of the bi-predicates is
1899    /// `true`.
1900    ///
1901    /// # Parameters
1902    ///
1903    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1904    ///   is passed by value and will transfer ownership.** If you need to
1905    ///   preserve the original bi-predicate, clone it first (if it implements
1906    ///   `Clone`). Can be:
1907    ///   - Another closure: `|x: &T, y: &U| -> bool`
1908    ///   - A function pointer: `fn(&T, &U) -> bool`
1909    ///   - A `BoxBiPredicate<T, U>`
1910    ///   - An `RcBiPredicate<T, U>`
1911    ///   - An `ArcBiPredicate<T, U>`
1912    ///   - Any type implementing `BiPredicate<T, U>`
1913    ///
1914    /// # Returns
1915    ///
1916    /// A `BoxBiPredicate` representing the logical XOR.
1917    fn xor<P>(self, other: P) -> BoxBiPredicate<T, U>
1918    where
1919        P: BiPredicate<T, U> + 'static,
1920        T: 'static,
1921        U: 'static,
1922    {
1923        BoxBiPredicate::new(move |first, second| self(first, second) ^ other.test(first, second))
1924    }
1925
1926    /// Returns a bi-predicate that represents the logical NOR (NOT
1927    /// OR) of this bi-predicate and another.
1928    ///
1929    /// NOR returns `true` only if both bi-predicates are `false`.
1930    /// Equivalent to `!(self OR other)`.
1931    ///
1932    /// # Parameters
1933    ///
1934    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1935    ///   is passed by value and will transfer ownership.** If you need to
1936    ///   preserve the original bi-predicate, clone it first (if it implements
1937    ///   `Clone`). Can be:
1938    ///   - Another closure: `|x: &T, y: &U| -> bool`
1939    ///   - A function pointer: `fn(&T, &U) -> bool`
1940    ///   - A `BoxBiPredicate<T, U>`
1941    ///   - An `RcBiPredicate<T, U>`
1942    ///   - An `ArcBiPredicate<T, U>`
1943    ///   - Any type implementing `BiPredicate<T, U>`
1944    ///
1945    /// # Returns
1946    ///
1947    /// A `BoxBiPredicate` representing the logical NOR.
1948    fn nor<P>(self, other: P) -> BoxBiPredicate<T, U>
1949    where
1950        P: BiPredicate<T, U> + 'static,
1951        T: 'static,
1952        U: 'static,
1953    {
1954        BoxBiPredicate::new(move |first, second| {
1955            !(self(first, second) || other.test(first, second))
1956        })
1957    }
1958}
1959
1960// Blanket implementation for all closures
1961impl<T, U, F> FnBiPredicateOps<T, U> for F where F: Fn(&T, &U) -> bool + 'static {}