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    fn into_box(self) -> BoxBiPredicate<T, U>
277    where
278        Self: Sized + 'static,
279        T: 'static,
280        U: 'static;
281
282    /// Converts this bi-predicate into an `RcBiPredicate`.
283    ///
284    /// # Returns
285    ///
286    /// An `RcBiPredicate` wrapping this bi-predicate.
287    fn into_rc(self) -> RcBiPredicate<T, U>
288    where
289        Self: Sized + 'static,
290        T: 'static,
291        U: 'static;
292
293    /// Converts this bi-predicate into an `ArcBiPredicate`.
294    ///
295    /// # Returns
296    ///
297    /// An `ArcBiPredicate` wrapping this bi-predicate.
298    fn into_arc(self) -> ArcBiPredicate<T, U>
299    where
300        Self: Sized + Send + Sync + 'static,
301        T: Send + Sync + 'static,
302        U: Send + Sync + 'static;
303
304    /// Converts this bi-predicate into a closure that can be used
305    /// directly with standard library methods.
306    ///
307    /// This method consumes the bi-predicate and returns a closure
308    /// with signature `Fn(&T, &U) -> bool`. Since `Fn` is a subtrait
309    /// of `FnMut`, the returned closure can be used in any context
310    /// that requires either `Fn(&T, &U) -> bool` or
311    /// `FnMut(&T, &U) -> bool`.
312    ///
313    /// # Returns
314    ///
315    /// A closure implementing `Fn(&T, &U) -> bool` (also usable as
316    /// `FnMut(&T, &U) -> bool`).
317    ///
318    /// # Examples
319    ///
320    /// ## Using with Iterator Methods
321    ///
322    /// ```rust
323    /// use prism3_function::bi_predicate::{BiPredicate,
324    ///     BoxBiPredicate};
325    ///
326    /// let pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
327    ///
328    /// let pairs = vec![(1, 2), (-1, 3), (5, -6)];
329    /// let mut closure = pred.into_fn();
330    /// let positives: Vec<_> = pairs.iter()
331    ///     .filter(|(x, y)| closure(x, y))
332    ///     .collect();
333    /// assert_eq!(positives, vec![&(1, 2), &(-1, 3)]);
334    /// ```
335    fn into_fn(self) -> impl Fn(&T, &U) -> bool
336    where
337        Self: Sized + 'static,
338        T: 'static,
339        U: 'static;
340}
341
342/// A Box-based bi-predicate with single ownership.
343///
344/// This type is suitable for one-time use scenarios where the
345/// bi-predicate does not need to be cloned or shared. Composition
346/// methods consume `self`, reflecting the single-ownership model.
347///
348/// # Examples
349///
350/// ```rust
351/// use prism3_function::bi_predicate::{BiPredicate, BoxBiPredicate};
352///
353/// let pred = BoxBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
354/// assert!(pred.test(&5, &3));
355///
356/// // Chaining consumes the bi-predicate
357/// let combined = pred.and(BoxBiPredicate::new(|x, y| x > y));
358/// assert!(combined.test(&10, &5));
359/// ```
360///
361/// # Author
362///
363/// Haixing Hu
364pub struct BoxBiPredicate<T, U> {
365    function: Box<BiPredicateFn<T, U>>,
366    name: Option<String>,
367}
368
369impl<T, U> BoxBiPredicate<T, U> {
370    /// Creates a new `BoxBiPredicate` from a closure.
371    ///
372    /// # Parameters
373    ///
374    /// * `f` - The closure to wrap.
375    ///
376    /// # Returns
377    ///
378    /// A new `BoxBiPredicate` instance.
379    pub fn new<F>(f: F) -> Self
380    where
381        F: Fn(&T, &U) -> bool + 'static,
382    {
383        Self {
384            function: Box::new(f),
385            name: None,
386        }
387    }
388
389    /// Creates a named `BoxBiPredicate` from a closure.
390    ///
391    /// # Parameters
392    ///
393    /// * `name` - The name for this bi-predicate.
394    /// * `f` - The closure to wrap.
395    ///
396    /// # Returns
397    ///
398    /// A new named `BoxBiPredicate` instance.
399    pub fn new_with_name<F>(name: &str, f: F) -> Self
400    where
401        F: Fn(&T, &U) -> bool + 'static,
402    {
403        Self {
404            function: Box::new(f),
405            name: Some(name.to_string()),
406        }
407    }
408
409    /// Creates a bi-predicate that always returns `true`.
410    ///
411    /// # Returns
412    ///
413    /// A new `BoxBiPredicate` that always returns `true`.
414    ///
415    /// # Examples
416    ///
417    /// ```rust
418    /// use prism3_function::bi_predicate::{BiPredicate, BoxBiPredicate};
419    ///
420    /// let pred: BoxBiPredicate<i32, i32> = BoxBiPredicate::always_true();
421    /// assert!(pred.test(&42, &10));
422    /// assert!(pred.test(&-1, &5));
423    /// assert!(pred.test(&0, &0));
424    /// ```
425    pub fn always_true() -> Self {
426        Self {
427            function: Box::new(|_, _| true),
428            name: Some(ALWAYS_TRUE_NAME.to_string()),
429        }
430    }
431
432    /// Creates a bi-predicate that always returns `false`.
433    ///
434    /// # Returns
435    ///
436    /// A new `BoxBiPredicate` that always returns `false`.
437    ///
438    /// # Examples
439    ///
440    /// ```rust
441    /// use prism3_function::bi_predicate::{BiPredicate, BoxBiPredicate};
442    ///
443    /// let pred: BoxBiPredicate<i32, i32> = BoxBiPredicate::always_false();
444    /// assert!(!pred.test(&42, &10));
445    /// assert!(!pred.test(&-1, &5));
446    /// assert!(!pred.test(&0, &0));
447    /// ```
448    pub fn always_false() -> Self {
449        Self {
450            function: Box::new(|_, _| false),
451            name: Some(ALWAYS_FALSE_NAME.to_string()),
452        }
453    }
454
455    /// Returns the name of this bi-predicate, if set.
456    ///
457    /// # Returns
458    ///
459    /// An `Option` containing the bi-predicate's name.
460    pub fn name(&self) -> Option<&str> {
461        self.name.as_deref()
462    }
463
464    /// Sets the name of this bi-predicate.
465    ///
466    /// # Parameters
467    ///
468    /// * `name` - The new name for this bi-predicate.
469    pub fn set_name(&mut self, name: &str) {
470        self.name = Some(name.to_string());
471    }
472
473    /// Returns a bi-predicate that represents the logical AND of this
474    /// bi-predicate and another.
475    ///
476    /// This method consumes `self` due to single-ownership semantics.
477    ///
478    /// # Parameters
479    ///
480    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
481    ///   is passed by value and will transfer ownership.** If you need to
482    ///   preserve the original bi-predicate, clone it first (if it implements
483    ///   `Clone`). Can be:
484    ///   - A closure: `|x: &T, y: &U| -> bool`
485    ///   - A function pointer: `fn(&T, &U) -> bool`
486    ///   - Another `BoxBiPredicate<T, U>`
487    ///   - An `RcBiPredicate<T, U>`
488    ///   - An `ArcBiPredicate<T, U>`
489    ///   - Any type implementing `BiPredicate<T, U>`
490    ///
491    /// # Returns
492    ///
493    /// A new `BoxBiPredicate` representing the logical AND.
494    pub fn and<P>(self, other: P) -> BoxBiPredicate<T, U>
495    where
496        P: BiPredicate<T, U> + 'static,
497        T: 'static,
498        U: 'static,
499    {
500        BoxBiPredicate {
501            function: Box::new(move |first: &T, second: &U| {
502                (self.function)(first, second) && other.test(first, second)
503            }),
504            name: None,
505        }
506    }
507
508    /// Returns a bi-predicate that represents the logical OR of this
509    /// bi-predicate and another.
510    ///
511    /// This method consumes `self` due to single-ownership semantics.
512    ///
513    /// # Parameters
514    ///
515    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
516    ///   is passed by value and will transfer ownership.** If you need to
517    ///   preserve the original bi-predicate, clone it first (if it implements
518    ///   `Clone`). Can be:
519    ///   - A closure: `|x: &T, y: &U| -> bool`
520    ///   - A function pointer: `fn(&T, &U) -> bool`
521    ///   - Another `BoxBiPredicate<T, U>`
522    ///   - An `RcBiPredicate<T, U>`
523    ///   - An `ArcBiPredicate<T, U>`
524    ///   - Any type implementing `BiPredicate<T, U>`
525    ///
526    /// # Returns
527    ///
528    /// A new `BoxBiPredicate` representing the logical OR.
529    pub fn or<P>(self, other: P) -> BoxBiPredicate<T, U>
530    where
531        P: BiPredicate<T, U> + 'static,
532        T: 'static,
533        U: 'static,
534    {
535        BoxBiPredicate {
536            function: Box::new(move |first: &T, second: &U| {
537                (self.function)(first, second) || other.test(first, second)
538            }),
539            name: None,
540        }
541    }
542
543    /// Returns a bi-predicate that represents the logical negation of
544    /// this bi-predicate.
545    ///
546    /// This method consumes `self` due to single-ownership semantics.
547    ///
548    /// # Returns
549    ///
550    /// A new `BoxBiPredicate` representing the logical negation.
551    #[allow(clippy::should_implement_trait)]
552    pub fn not(self) -> BoxBiPredicate<T, U>
553    where
554        T: 'static,
555        U: 'static,
556    {
557        BoxBiPredicate {
558            function: Box::new(move |first: &T, second: &U| !(self.function)(first, second)),
559            name: None,
560        }
561    }
562
563    /// Returns a bi-predicate that represents the logical NAND (NOT
564    /// AND) of this bi-predicate and another.
565    ///
566    /// NAND returns `true` unless both bi-predicates are `true`.
567    /// Equivalent to `!(self AND other)`.
568    ///
569    /// This method consumes `self` due to single-ownership semantics.
570    ///
571    /// # Parameters
572    ///
573    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
574    ///   is passed by value and will transfer ownership.** If you need to
575    ///   preserve the original bi-predicate, clone it first (if it implements
576    ///   `Clone`). Can be:
577    ///   - A closure: `|x: &T, y: &U| -> bool`
578    ///   - A function pointer: `fn(&T, &U) -> bool`
579    ///   - Another `BoxBiPredicate<T, U>`
580    ///   - An `RcBiPredicate<T, U>`
581    ///   - An `ArcBiPredicate<T, U>`
582    ///   - Any type implementing `BiPredicate<T, U>`
583    ///
584    /// # Returns
585    ///
586    /// A new `BoxBiPredicate` representing the logical NAND.
587    pub fn nand<P>(self, other: P) -> BoxBiPredicate<T, U>
588    where
589        P: BiPredicate<T, U> + 'static,
590        T: 'static,
591        U: 'static,
592    {
593        BoxBiPredicate {
594            function: Box::new(move |first: &T, second: &U| {
595                !((self.function)(first, second) && other.test(first, second))
596            }),
597            name: None,
598        }
599    }
600
601    /// Returns a bi-predicate that represents the logical XOR
602    /// (exclusive OR) of this bi-predicate and another.
603    ///
604    /// XOR returns `true` if exactly one of the bi-predicates is
605    /// `true`.
606    ///
607    /// This method consumes `self` due to single-ownership semantics.
608    ///
609    /// # Parameters
610    ///
611    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
612    ///   is passed by value and will transfer ownership.** If you need to
613    ///   preserve the original bi-predicate, clone it first (if it implements
614    ///   `Clone`). Can be:
615    ///   - A closure: `|x: &T, y: &U| -> bool`
616    ///   - A function pointer: `fn(&T, &U) -> bool`
617    ///   - Another `BoxBiPredicate<T, U>`
618    ///   - An `RcBiPredicate<T, U>`
619    ///   - An `ArcBiPredicate<T, U>`
620    ///   - Any type implementing `BiPredicate<T, U>`
621    ///
622    /// # Returns
623    ///
624    /// A new `BoxBiPredicate` representing the logical XOR.
625    pub fn xor<P>(self, other: P) -> BoxBiPredicate<T, U>
626    where
627        P: BiPredicate<T, U> + 'static,
628        T: 'static,
629        U: 'static,
630    {
631        BoxBiPredicate {
632            function: Box::new(move |first: &T, second: &U| {
633                (self.function)(first, second) ^ other.test(first, second)
634            }),
635            name: None,
636        }
637    }
638
639    /// Returns a bi-predicate that represents the logical NOR (NOT
640    /// OR) of this bi-predicate and another.
641    ///
642    /// NOR returns `true` only if both bi-predicates are `false`.
643    /// Equivalent to `!(self OR other)`.
644    ///
645    /// This method consumes `self` due to single-ownership semantics.
646    ///
647    /// # Parameters
648    ///
649    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
650    ///   is passed by value and will transfer ownership.** If you need to
651    ///   preserve the original bi-predicate, clone it first (if it implements
652    ///   `Clone`). Can be:
653    ///   - A closure: `|x: &T, y: &U| -> bool`
654    ///   - A function pointer: `fn(&T, &U) -> bool`
655    ///   - Another `BoxBiPredicate<T, U>`
656    ///   - An `RcBiPredicate<T, U>`
657    ///   - An `ArcBiPredicate<T, U>`
658    ///   - Any type implementing `BiPredicate<T, U>`
659    ///
660    /// # Returns
661    ///
662    /// A new `BoxBiPredicate` representing the logical NOR.
663    pub fn nor<P>(self, other: P) -> BoxBiPredicate<T, U>
664    where
665        P: BiPredicate<T, U> + 'static,
666        T: 'static,
667        U: 'static,
668    {
669        BoxBiPredicate {
670            function: Box::new(move |first: &T, second: &U| {
671                !((self.function)(first, second) || other.test(first, second))
672            }),
673            name: None,
674        }
675    }
676}
677
678impl<T, U> BiPredicate<T, U> for BoxBiPredicate<T, U> {
679    fn test(&self, first: &T, second: &U) -> bool {
680        (self.function)(first, second)
681    }
682
683    fn into_box(self) -> BoxBiPredicate<T, U>
684    where
685        T: 'static,
686        U: 'static,
687    {
688        self
689    }
690
691    fn into_rc(self) -> RcBiPredicate<T, U>
692    where
693        T: 'static,
694        U: 'static,
695    {
696        RcBiPredicate {
697            function: Rc::from(self.function),
698            name: self.name,
699        }
700    }
701
702    fn into_arc(self) -> ArcBiPredicate<T, U>
703    where
704        Self: Send + Sync,
705        T: Send + Sync + 'static,
706        U: Send + Sync + 'static,
707    {
708        panic!("BoxBiPredicate cannot be converted to ArcBiPredicate - use ArcBiPredicate::new directly")
709    }
710
711    fn into_fn(self) -> impl Fn(&T, &U) -> bool
712    where
713        Self: Sized + 'static,
714        T: 'static,
715        U: 'static,
716    {
717        move |first: &T, second: &U| (self.function)(first, second)
718    }
719}
720
721impl<T, U> Display for BoxBiPredicate<T, U> {
722    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
723        write!(
724            f,
725            "BoxBiPredicate({})",
726            self.name.as_deref().unwrap_or("unnamed")
727        )
728    }
729}
730
731impl<T, U> Debug for BoxBiPredicate<T, U> {
732    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
733        f.debug_struct("BoxBiPredicate")
734            .field("name", &self.name)
735            .finish()
736    }
737}
738
739/// An Rc-based bi-predicate with single-threaded shared ownership.
740///
741/// This type is suitable for scenarios where the bi-predicate needs
742/// to be reused in a single-threaded context. Composition methods
743/// borrow `&self`, allowing the original bi-predicate to remain
744/// usable after composition.
745///
746/// # Examples
747///
748/// ```rust
749/// use prism3_function::bi_predicate::{BiPredicate, RcBiPredicate};
750///
751/// let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
752/// assert!(pred.test(&5, &3));
753///
754/// // Original bi-predicate remains usable after composition
755/// let combined = pred.and(RcBiPredicate::new(|x, y| x > y));
756/// assert!(pred.test(&5, &3));  // Still works
757/// ```
758///
759/// # Author
760///
761/// Haixing Hu
762pub struct RcBiPredicate<T, U> {
763    function: Rc<BiPredicateFn<T, U>>,
764    name: Option<String>,
765}
766
767impl<T, U> RcBiPredicate<T, U> {
768    /// Creates a new `RcBiPredicate` from a closure.
769    ///
770    /// # Parameters
771    ///
772    /// * `f` - The closure to wrap.
773    ///
774    /// # Returns
775    ///
776    /// A new `RcBiPredicate` instance.
777    pub fn new<F>(f: F) -> Self
778    where
779        F: Fn(&T, &U) -> bool + 'static,
780    {
781        Self {
782            function: Rc::new(f),
783            name: None,
784        }
785    }
786
787    /// Creates a named `RcBiPredicate` from a closure.
788    ///
789    /// # Parameters
790    ///
791    /// * `name` - The name for this bi-predicate.
792    /// * `f` - The closure to wrap.
793    ///
794    /// # Returns
795    ///
796    /// A new named `RcBiPredicate` instance.
797    pub fn new_with_name<F>(name: &str, f: F) -> Self
798    where
799        F: Fn(&T, &U) -> bool + 'static,
800    {
801        Self {
802            function: Rc::new(f),
803            name: Some(name.to_string()),
804        }
805    }
806
807    /// Creates a bi-predicate that always returns `true`.
808    ///
809    /// # Returns
810    ///
811    /// A new `RcBiPredicate` that always returns `true`.
812    ///
813    /// # Examples
814    ///
815    /// ```rust
816    /// use prism3_function::bi_predicate::{BiPredicate, RcBiPredicate};
817    ///
818    /// let pred: RcBiPredicate<i32, i32> = RcBiPredicate::always_true();
819    /// assert!(pred.test(&42, &10));
820    /// assert!(pred.test(&-1, &5));
821    /// assert!(pred.test(&0, &0));
822    /// ```
823    pub fn always_true() -> Self {
824        Self {
825            function: Rc::new(|_, _| true),
826            name: Some(ALWAYS_TRUE_NAME.to_string()),
827        }
828    }
829
830    /// Creates a bi-predicate that always returns `false`.
831    ///
832    /// # Returns
833    ///
834    /// A new `RcBiPredicate` that always returns `false`.
835    ///
836    /// # Examples
837    ///
838    /// ```rust
839    /// use prism3_function::bi_predicate::{BiPredicate, RcBiPredicate};
840    ///
841    /// let pred: RcBiPredicate<i32, i32> = RcBiPredicate::always_false();
842    /// assert!(!pred.test(&42, &10));
843    /// assert!(!pred.test(&-1, &5));
844    /// assert!(!pred.test(&0, &0));
845    /// ```
846    pub fn always_false() -> Self {
847        Self {
848            function: Rc::new(|_, _| false),
849            name: Some(ALWAYS_FALSE_NAME.to_string()),
850        }
851    }
852
853    /// Returns the name of this bi-predicate, if set.
854    ///
855    /// # Returns
856    ///
857    /// An `Option` containing the bi-predicate's name.
858    pub fn name(&self) -> Option<&str> {
859        self.name.as_deref()
860    }
861
862    /// Sets the name of this bi-predicate.
863    ///
864    /// # Parameters
865    ///
866    /// * `name` - The new name for this bi-predicate.
867    pub fn set_name(&mut self, name: &str) {
868        self.name = Some(name.to_string());
869    }
870
871    /// Returns a bi-predicate that represents the logical AND of this
872    /// bi-predicate and another.
873    ///
874    /// # Parameters
875    ///
876    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
877    ///   is passed by value and will transfer ownership.** If you need to
878    ///   preserve the original bi-predicate, clone it first (if it implements
879    ///   `Clone`). Can be:
880    ///   - A closure: `|x: &T, y: &U| -> bool`
881    ///   - A function pointer: `fn(&T, &U) -> bool`
882    ///   - A `BoxBiPredicate<T, U>`
883    ///   - Another `RcBiPredicate<T, U>` (will be moved)
884    ///   - An `ArcBiPredicate<T, U>`
885    ///   - Any type implementing `BiPredicate<T, U>`
886    ///
887    /// # Returns
888    ///
889    /// A new `RcBiPredicate` representing the logical AND.
890    pub fn and<P>(&self, other: P) -> RcBiPredicate<T, U>
891    where
892        P: BiPredicate<T, U> + 'static,
893        T: 'static,
894        U: 'static,
895    {
896        let self_fn = Rc::clone(&self.function);
897        RcBiPredicate {
898            function: Rc::new(move |first: &T, second: &U| {
899                self_fn(first, second) && other.test(first, second)
900            }),
901            name: None,
902        }
903    }
904
905    /// Returns a bi-predicate that represents the logical OR of this
906    /// bi-predicate and another.
907    ///
908    /// # Parameters
909    ///
910    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
911    ///   is passed by value and will transfer ownership.** If you need to
912    ///   preserve the original bi-predicate, clone it first (if it implements
913    ///   `Clone`). Can be:
914    ///   - A closure: `|x: &T, y: &U| -> bool`
915    ///   - A function pointer: `fn(&T, &U) -> bool`
916    ///   - A `BoxBiPredicate<T, U>`
917    ///   - Another `RcBiPredicate<T, U>` (will be moved)
918    ///   - An `ArcBiPredicate<T, U>`
919    ///   - Any type implementing `BiPredicate<T, U>`
920    ///
921    /// # Returns
922    ///
923    /// A new `RcBiPredicate` representing the logical OR.
924    pub fn or<P>(&self, other: P) -> RcBiPredicate<T, U>
925    where
926        P: BiPredicate<T, U> + 'static,
927        T: 'static,
928        U: 'static,
929    {
930        let self_fn = Rc::clone(&self.function);
931        RcBiPredicate {
932            function: Rc::new(move |first: &T, second: &U| {
933                self_fn(first, second) || other.test(first, second)
934            }),
935            name: None,
936        }
937    }
938
939    /// Returns a bi-predicate that represents the logical negation of
940    /// this bi-predicate.
941    ///
942    /// # Returns
943    ///
944    /// A new `RcBiPredicate` representing the logical negation.
945    #[allow(clippy::should_implement_trait)]
946    pub fn not(&self) -> RcBiPredicate<T, U>
947    where
948        T: 'static,
949        U: 'static,
950    {
951        let self_fn = Rc::clone(&self.function);
952        RcBiPredicate {
953            function: Rc::new(move |first: &T, second: &U| !self_fn(first, second)),
954            name: None,
955        }
956    }
957
958    /// Returns a bi-predicate that represents the logical NAND (NOT
959    /// AND) of this bi-predicate and another.
960    ///
961    /// NAND returns `true` unless both bi-predicates are `true`.
962    /// Equivalent to `!(self AND other)`.
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 NAND.
980    pub fn nand<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: &T, second: &U| {
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 XOR
996    /// (exclusive OR) of this bi-predicate and another.
997    ///
998    /// XOR returns `true` if exactly one of the bi-predicates is
999    /// `true`.
1000    ///
1001    /// # Parameters
1002    ///
1003    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1004    ///   is passed by value and will transfer ownership.** If you need to
1005    ///   preserve the original bi-predicate, clone it first (if it implements
1006    ///   `Clone`). Can be:
1007    ///   - A closure: `|x: &T, y: &U| -> bool`
1008    ///   - A function pointer: `fn(&T, &U) -> bool`
1009    ///   - A `BoxBiPredicate<T, U>`
1010    ///   - Another `RcBiPredicate<T, U>` (will be moved)
1011    ///   - An `ArcBiPredicate<T, U>`
1012    ///   - Any type implementing `BiPredicate<T, U>`
1013    ///
1014    /// # Returns
1015    ///
1016    /// A new `RcBiPredicate` representing the logical XOR.
1017    pub fn xor<P>(&self, other: P) -> RcBiPredicate<T, U>
1018    where
1019        P: BiPredicate<T, U> + 'static,
1020        T: 'static,
1021        U: 'static,
1022    {
1023        let self_fn = Rc::clone(&self.function);
1024        RcBiPredicate {
1025            function: Rc::new(move |first: &T, second: &U| {
1026                self_fn(first, second) ^ other.test(first, second)
1027            }),
1028            name: None,
1029        }
1030    }
1031
1032    /// Returns a bi-predicate that represents the logical NOR (NOT
1033    /// OR) of this bi-predicate and another.
1034    ///
1035    /// NOR returns `true` only if both bi-predicates are `false`.
1036    /// Equivalent to `!(self OR other)`.
1037    ///
1038    /// # Parameters
1039    ///
1040    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1041    ///   is passed by value and will transfer ownership.** If you need to
1042    ///   preserve the original bi-predicate, clone it first (if it implements
1043    ///   `Clone`). Can be:
1044    ///   - A closure: `|x: &T, y: &U| -> bool`
1045    ///   - A function pointer: `fn(&T, &U) -> bool`
1046    ///   - A `BoxBiPredicate<T, U>`
1047    ///   - Another `RcBiPredicate<T, U>` (will be moved)
1048    ///   - An `ArcBiPredicate<T, U>`
1049    ///   - Any type implementing `BiPredicate<T, U>`
1050    ///
1051    /// # Returns
1052    ///
1053    /// A new `RcBiPredicate` representing the logical NOR.
1054    pub fn nor<P>(&self, other: P) -> RcBiPredicate<T, U>
1055    where
1056        P: BiPredicate<T, U> + 'static,
1057        T: 'static,
1058        U: 'static,
1059    {
1060        let self_fn = Rc::clone(&self.function);
1061        RcBiPredicate {
1062            function: Rc::new(move |first: &T, second: &U| {
1063                !(self_fn(first, second) || other.test(first, second))
1064            }),
1065            name: None,
1066        }
1067    }
1068
1069    /// Converts this bi-predicate to a `BoxBiPredicate`.
1070    ///
1071    /// # Returns
1072    ///
1073    /// A `BoxBiPredicate` wrapping this bi-predicate.
1074    pub fn to_box(&self) -> BoxBiPredicate<T, U>
1075    where
1076        T: 'static,
1077        U: 'static,
1078    {
1079        let self_fn = Rc::clone(&self.function);
1080        BoxBiPredicate {
1081            function: Box::new(move |first: &T, second: &U| self_fn(first, second)),
1082            name: self.name.clone(),
1083        }
1084    }
1085
1086    /// Converts this bi-predicate to a closure that can be used
1087    /// directly with standard library methods.
1088    ///
1089    /// This method creates a new closure without consuming the
1090    /// original bi-predicate, since `RcBiPredicate` uses shared
1091    /// ownership. The returned closure has signature
1092    /// `Fn(&T, &U) -> bool`.
1093    ///
1094    /// # Returns
1095    ///
1096    /// A closure implementing `Fn(&T, &U) -> bool`.
1097    pub fn to_fn(&self) -> impl Fn(&T, &U) -> bool
1098    where
1099        T: 'static,
1100        U: 'static,
1101    {
1102        let function = Rc::clone(&self.function);
1103        move |first: &T, second: &U| function(first, second)
1104    }
1105}
1106
1107impl<T, U> BiPredicate<T, U> for RcBiPredicate<T, U> {
1108    fn test(&self, first: &T, second: &U) -> bool {
1109        (self.function)(first, second)
1110    }
1111
1112    fn into_box(self) -> BoxBiPredicate<T, U>
1113    where
1114        T: 'static,
1115        U: 'static,
1116    {
1117        let self_fn = self.function;
1118        BoxBiPredicate {
1119            function: Box::new(move |first: &T, second: &U| self_fn(first, second)),
1120            name: self.name,
1121        }
1122    }
1123
1124    fn into_rc(self) -> RcBiPredicate<T, U>
1125    where
1126        T: 'static,
1127        U: 'static,
1128    {
1129        self
1130    }
1131
1132    fn into_arc(self) -> ArcBiPredicate<T, U>
1133    where
1134        Self: Send + Sync,
1135        T: Send + Sync + 'static,
1136        U: Send + Sync + 'static,
1137    {
1138        panic!("RcBiPredicate cannot be converted to ArcBiPredicate - use ArcBiPredicate::new directly")
1139    }
1140
1141    fn into_fn(self) -> impl Fn(&T, &U) -> bool
1142    where
1143        Self: Sized + 'static,
1144        T: 'static,
1145        U: 'static,
1146    {
1147        let self_fn = self.function;
1148        move |first: &T, second: &U| self_fn(first, second)
1149    }
1150}
1151
1152impl<T, U> Clone for RcBiPredicate<T, U> {
1153    /// Clones this bi-predicate.
1154    ///
1155    /// Creates a new instance that shares the underlying function with
1156    /// the original, allowing multiple references to the same
1157    /// bi-predicate logic.
1158    fn clone(&self) -> Self {
1159        Self {
1160            function: Rc::clone(&self.function),
1161            name: self.name.clone(),
1162        }
1163    }
1164}
1165
1166impl<T, U> Display for RcBiPredicate<T, U> {
1167    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1168        write!(
1169            f,
1170            "RcBiPredicate({})",
1171            self.name.as_deref().unwrap_or("unnamed")
1172        )
1173    }
1174}
1175
1176impl<T, U> Debug for RcBiPredicate<T, U> {
1177    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1178        f.debug_struct("RcBiPredicate")
1179            .field("name", &self.name)
1180            .finish()
1181    }
1182}
1183
1184/// An Arc-based bi-predicate with thread-safe shared ownership.
1185///
1186/// This type is suitable for scenarios where the bi-predicate needs
1187/// to be shared across threads. Composition methods borrow `&self`,
1188/// allowing the original bi-predicate to remain usable after
1189/// composition.
1190///
1191/// # Examples
1192///
1193/// ```rust
1194/// use prism3_function::bi_predicate::{BiPredicate, ArcBiPredicate};
1195///
1196/// let pred = ArcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
1197/// assert!(pred.test(&5, &3));
1198///
1199/// // Original bi-predicate remains usable after composition
1200/// let combined = pred.and(ArcBiPredicate::new(|x, y| x > y));
1201/// assert!(pred.test(&5, &3));  // Still works
1202///
1203/// // Can be cloned and sent across threads
1204/// let pred_clone = pred.clone();
1205/// std::thread::spawn(move || {
1206///     assert!(pred_clone.test(&10, &5));
1207/// }).join().unwrap();
1208/// ```
1209///
1210/// # Author
1211///
1212/// Haixing Hu
1213pub struct ArcBiPredicate<T, U> {
1214    function: Arc<SendSyncBiPredicateFn<T, U>>,
1215    name: Option<String>,
1216}
1217
1218impl<T, U> ArcBiPredicate<T, U> {
1219    /// Creates a new `ArcBiPredicate` from a closure.
1220    ///
1221    /// # Parameters
1222    ///
1223    /// * `f` - The closure to wrap.
1224    ///
1225    /// # Returns
1226    ///
1227    /// A new `ArcBiPredicate` instance.
1228    pub fn new<F>(f: F) -> Self
1229    where
1230        F: Fn(&T, &U) -> bool + Send + Sync + 'static,
1231    {
1232        Self {
1233            function: Arc::new(f),
1234            name: None,
1235        }
1236    }
1237
1238    /// Creates a named `ArcBiPredicate` from a closure.
1239    ///
1240    /// # Parameters
1241    ///
1242    /// * `name` - The name for this bi-predicate.
1243    /// * `f` - The closure to wrap.
1244    ///
1245    /// # Returns
1246    ///
1247    /// A new named `ArcBiPredicate` instance.
1248    pub fn new_with_name<F>(name: &str, f: F) -> Self
1249    where
1250        F: Fn(&T, &U) -> bool + Send + Sync + 'static,
1251    {
1252        Self {
1253            function: Arc::new(f),
1254            name: Some(name.to_string()),
1255        }
1256    }
1257
1258    /// Creates a bi-predicate that always returns `true`.
1259    ///
1260    /// # Returns
1261    ///
1262    /// A new `ArcBiPredicate` that always returns `true`.
1263    ///
1264    /// # Examples
1265    ///
1266    /// ```rust
1267    /// use prism3_function::bi_predicate::{BiPredicate, ArcBiPredicate};
1268    ///
1269    /// let pred: ArcBiPredicate<i32, i32> = ArcBiPredicate::always_true();
1270    /// assert!(pred.test(&42, &10));
1271    /// assert!(pred.test(&-1, &5));
1272    /// assert!(pred.test(&0, &0));
1273    /// ```
1274    pub fn always_true() -> Self {
1275        Self {
1276            function: Arc::new(|_, _| true),
1277            name: Some(ALWAYS_TRUE_NAME.to_string()),
1278        }
1279    }
1280
1281    /// Creates a bi-predicate that always returns `false`.
1282    ///
1283    /// # Returns
1284    ///
1285    /// A new `ArcBiPredicate` that always returns `false`.
1286    ///
1287    /// # Examples
1288    ///
1289    /// ```rust
1290    /// use prism3_function::bi_predicate::{BiPredicate, ArcBiPredicate};
1291    ///
1292    /// let pred: ArcBiPredicate<i32, i32> = ArcBiPredicate::always_false();
1293    /// assert!(!pred.test(&42, &10));
1294    /// assert!(!pred.test(&-1, &5));
1295    /// assert!(!pred.test(&0, &0));
1296    /// ```
1297    pub fn always_false() -> Self {
1298        Self {
1299            function: Arc::new(|_, _| false),
1300            name: Some(ALWAYS_FALSE_NAME.to_string()),
1301        }
1302    }
1303
1304    /// Returns the name of this bi-predicate, if set.
1305    ///
1306    /// # Returns
1307    ///
1308    /// An `Option` containing the bi-predicate's name.
1309    pub fn name(&self) -> Option<&str> {
1310        self.name.as_deref()
1311    }
1312
1313    /// Sets the name of this bi-predicate.
1314    ///
1315    /// # Parameters
1316    ///
1317    /// * `name` - The new name for this bi-predicate.
1318    pub fn set_name(&mut self, name: &str) {
1319        self.name = Some(name.to_string());
1320    }
1321
1322    /// Returns a bi-predicate that represents the logical AND of this
1323    /// bi-predicate and another.
1324    ///
1325    /// # Parameters
1326    ///
1327    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1328    ///   is passed by value and will transfer ownership.** If you need to
1329    ///   preserve the original bi-predicate, clone it first (if it implements
1330    ///   `Clone`). Can be:
1331    ///   - A closure: `|x: &T, y: &U| -> bool`
1332    ///   - A function pointer: `fn(&T, &U) -> bool`
1333    ///   - A `BoxBiPredicate<T, U>`
1334    ///   - An `RcBiPredicate<T, U>`
1335    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1336    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1337    ///
1338    /// # Returns
1339    ///
1340    /// A new `ArcBiPredicate` representing the logical AND.
1341    pub fn and<P>(&self, other: P) -> ArcBiPredicate<T, U>
1342    where
1343        T: Send + Sync + 'static,
1344        U: Send + Sync + 'static,
1345        P: BiPredicate<T, U> + Send + Sync + 'static,
1346    {
1347        let self_fn = Arc::clone(&self.function);
1348        ArcBiPredicate {
1349            function: Arc::new(move |first: &T, second: &U| {
1350                self_fn(first, second) && other.test(first, second)
1351            }),
1352            name: None,
1353        }
1354    }
1355
1356    /// Returns a bi-predicate that represents the logical OR of this
1357    /// bi-predicate and another.
1358    ///
1359    /// # Parameters
1360    ///
1361    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1362    ///   is passed by value and will transfer ownership.** If you need to
1363    ///   preserve the original bi-predicate, clone it first (if it implements
1364    ///   `Clone`). Can be:
1365    ///   - A closure: `|x: &T, y: &U| -> bool`
1366    ///   - A function pointer: `fn(&T, &U) -> bool`
1367    ///   - A `BoxBiPredicate<T, U>`
1368    ///   - An `RcBiPredicate<T, U>`
1369    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1370    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1371    ///
1372    /// # Returns
1373    ///
1374    /// A new `ArcBiPredicate` representing the logical OR.
1375    /// Thread-safe.
1376    pub fn or<P>(&self, other: P) -> ArcBiPredicate<T, U>
1377    where
1378        T: Send + Sync + 'static,
1379        U: Send + Sync + 'static,
1380        P: BiPredicate<T, U> + Send + Sync + 'static,
1381    {
1382        let self_fn = Arc::clone(&self.function);
1383        ArcBiPredicate {
1384            function: Arc::new(move |first: &T, second: &U| {
1385                self_fn(first, second) || other.test(first, second)
1386            }),
1387            name: None,
1388        }
1389    }
1390
1391    /// Returns a bi-predicate that represents the logical negation of
1392    /// this bi-predicate.
1393    ///
1394    /// # Returns
1395    ///
1396    /// A new `ArcBiPredicate` representing the logical negation.
1397    #[allow(clippy::should_implement_trait)]
1398    pub fn not(&self) -> ArcBiPredicate<T, U>
1399    where
1400        T: Send + Sync + 'static,
1401        U: Send + Sync + 'static,
1402    {
1403        let self_fn = Arc::clone(&self.function);
1404        ArcBiPredicate {
1405            function: Arc::new(move |first: &T, second: &U| !self_fn(first, second)),
1406            name: None,
1407        }
1408    }
1409
1410    /// Returns a bi-predicate that represents the logical NAND (NOT
1411    /// AND) of this bi-predicate and another.
1412    ///
1413    /// NAND returns `true` unless both bi-predicates are `true`.
1414    /// Equivalent to `!(self AND other)`.
1415    ///
1416    /// # Parameters
1417    ///
1418    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1419    ///   is passed by value and will transfer ownership.** If you need to
1420    ///   preserve the original bi-predicate, clone it first (if it implements
1421    ///   `Clone`). Can be:
1422    ///   - A closure: `|x: &T, y: &U| -> bool`
1423    ///   - A function pointer: `fn(&T, &U) -> bool`
1424    ///   - A `BoxBiPredicate<T, U>`
1425    ///   - An `RcBiPredicate<T, U>`
1426    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1427    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1428    ///
1429    /// # Returns
1430    ///
1431    /// A new `ArcBiPredicate` representing the logical NAND.
1432    /// Thread-safe.
1433    pub fn nand<P>(&self, other: P) -> ArcBiPredicate<T, U>
1434    where
1435        T: Send + Sync + 'static,
1436        U: Send + Sync + 'static,
1437        P: BiPredicate<T, U> + Send + Sync + 'static,
1438    {
1439        let self_fn = Arc::clone(&self.function);
1440        ArcBiPredicate {
1441            function: Arc::new(move |first: &T, second: &U| {
1442                !(self_fn(first, second) && other.test(first, second))
1443            }),
1444            name: None,
1445        }
1446    }
1447
1448    /// Returns a bi-predicate that represents the logical XOR
1449    /// (exclusive OR) of this bi-predicate and another.
1450    ///
1451    /// XOR returns `true` if exactly one of the bi-predicates is
1452    /// `true`.
1453    ///
1454    /// # Parameters
1455    ///
1456    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1457    ///   is passed by value and will transfer ownership.** If you need to
1458    ///   preserve the original bi-predicate, clone it first (if it implements
1459    ///   `Clone`). Can be:
1460    ///   - A closure: `|x: &T, y: &U| -> bool`
1461    ///   - A function pointer: `fn(&T, &U) -> bool`
1462    ///   - A `BoxBiPredicate<T, U>`
1463    ///   - An `RcBiPredicate<T, U>`
1464    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1465    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1466    ///
1467    /// # Returns
1468    ///
1469    /// A new `ArcBiPredicate` representing the logical XOR.
1470    pub fn xor<P>(&self, other: P) -> ArcBiPredicate<T, U>
1471    where
1472        T: Send + Sync + 'static,
1473        U: Send + Sync + 'static,
1474        P: BiPredicate<T, U> + Send + Sync + 'static,
1475    {
1476        let self_fn = Arc::clone(&self.function);
1477        ArcBiPredicate {
1478            function: Arc::new(move |first: &T, second: &U| {
1479                self_fn(first, second) ^ other.test(first, second)
1480            }),
1481            name: None,
1482        }
1483    }
1484
1485    /// Returns a bi-predicate that represents the logical NOR (NOT
1486    /// OR) of this bi-predicate and another.
1487    ///
1488    /// NOR returns `true` only if both bi-predicates are `false`.
1489    /// Equivalent to `!(self OR other)`.
1490    ///
1491    /// # Parameters
1492    ///
1493    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1494    ///   is passed by value and will transfer ownership.** If you need to
1495    ///   preserve the original bi-predicate, clone it first (if it implements
1496    ///   `Clone`). Can be:
1497    ///   - A closure: `|x: &T, y: &U| -> bool`
1498    ///   - A function pointer: `fn(&T, &U) -> bool`
1499    ///   - A `BoxBiPredicate<T, U>`
1500    ///   - An `RcBiPredicate<T, U>`
1501    ///   - Another `ArcBiPredicate<T, U>` (will be moved)
1502    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1503    ///
1504    /// # Returns
1505    ///
1506    /// A new `ArcBiPredicate` representing the logical NOR.
1507    /// Thread-safe.
1508    pub fn nor<P>(&self, other: P) -> ArcBiPredicate<T, U>
1509    where
1510        T: Send + Sync + 'static,
1511        U: Send + Sync + 'static,
1512        P: BiPredicate<T, U> + Send + Sync + 'static,
1513    {
1514        let self_fn = Arc::clone(&self.function);
1515        ArcBiPredicate {
1516            function: Arc::new(move |first: &T, second: &U| {
1517                !(self_fn(first, second) || other.test(first, second))
1518            }),
1519            name: None,
1520        }
1521    }
1522
1523    /// Converts this bi-predicate to a `BoxBiPredicate`.
1524    ///
1525    /// # Returns
1526    ///
1527    /// A `BoxBiPredicate` wrapping this bi-predicate.
1528    pub fn to_box(&self) -> BoxBiPredicate<T, U>
1529    where
1530        T: 'static,
1531        U: 'static,
1532    {
1533        let self_fn = Arc::clone(&self.function);
1534        BoxBiPredicate {
1535            function: Box::new(move |first: &T, second: &U| self_fn(first, second)),
1536            name: self.name.clone(),
1537        }
1538    }
1539
1540    /// Converts this bi-predicate to an `RcBiPredicate`.
1541    ///
1542    /// # Returns
1543    ///
1544    /// An `RcBiPredicate` wrapping this bi-predicate.
1545    pub fn to_rc(&self) -> RcBiPredicate<T, U>
1546    where
1547        T: 'static,
1548        U: 'static,
1549    {
1550        let self_fn = Arc::clone(&self.function);
1551        RcBiPredicate {
1552            function: Rc::new(move |first: &T, second: &U| self_fn(first, second)),
1553            name: self.name.clone(),
1554        }
1555    }
1556
1557    /// Converts this bi-predicate to a closure that can be used
1558    /// directly with standard library methods.
1559    ///
1560    /// This method creates a new closure without consuming the
1561    /// original bi-predicate, since `ArcBiPredicate` uses shared
1562    /// ownership. The returned closure has signature
1563    /// `Fn(&T, &U) -> bool + Send + Sync` and is thread-safe.
1564    ///
1565    /// # Returns
1566    ///
1567    /// A closure implementing `Fn(&T, &U) -> bool + Send + Sync`.
1568    pub fn to_fn(&self) -> impl Fn(&T, &U) -> bool + Send + Sync
1569    where
1570        T: Send + Sync + 'static,
1571        U: Send + Sync + 'static,
1572    {
1573        let self_fn = Arc::clone(&self.function);
1574        move |first: &T, second: &U| self_fn(first, second)
1575    }
1576}
1577
1578impl<T, U> BiPredicate<T, U> for ArcBiPredicate<T, U> {
1579    fn test(&self, first: &T, second: &U) -> bool {
1580        (self.function)(first, second)
1581    }
1582
1583    fn into_box(self) -> BoxBiPredicate<T, U>
1584    where
1585        T: 'static,
1586        U: 'static,
1587    {
1588        let name = self.name.clone();
1589        BoxBiPredicate {
1590            function: Box::new(move |first, second| self.test(first, second)),
1591            name,
1592        }
1593    }
1594
1595    fn into_rc(self) -> RcBiPredicate<T, U>
1596    where
1597        T: 'static,
1598        U: 'static,
1599    {
1600        let name = self.name.clone();
1601        RcBiPredicate {
1602            function: Rc::new(move |first, second| self.test(first, second)),
1603            name,
1604        }
1605    }
1606
1607    fn into_arc(self) -> ArcBiPredicate<T, U>
1608    where
1609        T: Send + Sync + 'static,
1610        U: Send + Sync + 'static,
1611    {
1612        self
1613    }
1614
1615    fn into_fn(self) -> impl Fn(&T, &U) -> bool
1616    where
1617        Self: Sized + 'static,
1618        T: 'static,
1619        U: 'static,
1620    {
1621        let self_fn = self.function;
1622        move |first: &T, second: &U| self_fn(first, second)
1623    }
1624}
1625
1626impl<T, U> Clone for ArcBiPredicate<T, U> {
1627    /// Clones this bi-predicate.
1628    ///
1629    /// Creates a new instance that shares the underlying function with
1630    /// the original, allowing multiple references to the same
1631    /// bi-predicate logic.
1632    fn clone(&self) -> Self {
1633        Self {
1634            function: Arc::clone(&self.function),
1635            name: self.name.clone(),
1636        }
1637    }
1638}
1639
1640impl<T, U> Display for ArcBiPredicate<T, U> {
1641    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1642        write!(
1643            f,
1644            "ArcBiPredicate({})",
1645            self.name.as_deref().unwrap_or("unnamed")
1646        )
1647    }
1648}
1649
1650impl<T, U> Debug for ArcBiPredicate<T, U> {
1651    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1652        f.debug_struct("ArcBiPredicate")
1653            .field("name", &self.name)
1654            .finish()
1655    }
1656}
1657
1658// Blanket implementation for all closures that match Fn(&T, &U) -> bool
1659impl<T: 'static, U: 'static, F> BiPredicate<T, U> for F
1660where
1661    F: Fn(&T, &U) -> bool + 'static,
1662{
1663    fn test(&self, first: &T, second: &U) -> bool {
1664        self(first, second)
1665    }
1666
1667    fn into_box(self) -> BoxBiPredicate<T, U> {
1668        BoxBiPredicate::new(self)
1669    }
1670
1671    fn into_rc(self) -> RcBiPredicate<T, U> {
1672        RcBiPredicate::new(self)
1673    }
1674
1675    fn into_arc(self) -> ArcBiPredicate<T, U>
1676    where
1677        Self: Send + Sync,
1678        T: Send + Sync,
1679        U: Send + Sync,
1680    {
1681        ArcBiPredicate::new(self)
1682    }
1683
1684    fn into_fn(self) -> impl Fn(&T, &U) -> bool {
1685        self
1686    }
1687}
1688
1689/// Extension trait providing logical composition methods for closures.
1690///
1691/// This trait is automatically implemented for all closures and
1692/// function pointers that match `Fn(&T, &U) -> bool`, enabling method
1693/// chaining starting from a closure.
1694///
1695/// # Examples
1696///
1697/// ```rust
1698/// use prism3_function::bi_predicate::{BiPredicate, FnBiPredicateOps};
1699///
1700/// let is_sum_positive = |x: &i32, y: &i32| x + y > 0;
1701/// let first_larger = |x: &i32, y: &i32| x > y;
1702///
1703/// // Combine bi-predicates using extension methods
1704/// let pred = is_sum_positive.and(first_larger);
1705/// assert!(pred.test(&10, &5));
1706/// assert!(!pred.test(&3, &8));
1707/// ```
1708///
1709/// # Author
1710///
1711/// Haixing Hu
1712pub trait FnBiPredicateOps<T, U>: Fn(&T, &U) -> bool + Sized + 'static {
1713    /// Returns a bi-predicate that represents the logical AND of this
1714    /// bi-predicate and another.
1715    ///
1716    /// # Parameters
1717    ///
1718    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1719    ///   is passed by value and will transfer ownership.** If you need to
1720    ///   preserve the original bi-predicate, clone it first (if it implements
1721    ///   `Clone`). Can be:
1722    ///   - Another closure: `|x: &T, y: &U| -> bool`
1723    ///   - A function pointer: `fn(&T, &U) -> bool`
1724    ///   - A `BoxBiPredicate<T, U>`
1725    ///   - An `RcBiPredicate<T, U>`
1726    ///   - An `ArcBiPredicate<T, U>`
1727    ///   - Any type implementing `BiPredicate<T, U>`
1728    ///
1729    /// # Returns
1730    ///
1731    /// A `BoxBiPredicate` representing the logical AND.
1732    fn and<P>(self, other: P) -> BoxBiPredicate<T, U>
1733    where
1734        P: BiPredicate<T, U> + 'static,
1735        T: 'static,
1736        U: 'static,
1737    {
1738        BoxBiPredicate::new(move |first, second| self(first, second) && other.test(first, second))
1739    }
1740
1741    /// Returns a bi-predicate that represents the logical OR of this
1742    /// bi-predicate and another.
1743    ///
1744    /// # Parameters
1745    ///
1746    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1747    ///   is passed by value and will transfer ownership.** If you need to
1748    ///   preserve the original bi-predicate, clone it first (if it implements
1749    ///   `Clone`). Can be:
1750    ///   - Another closure: `|x: &T, y: &U| -> bool`
1751    ///   - A function pointer: `fn(&T, &U) -> bool`
1752    ///   - A `BoxBiPredicate<T, U>`
1753    ///   - An `RcBiPredicate<T, U>`
1754    ///   - An `ArcBiPredicate<T, U>`
1755    ///   - Any type implementing `BiPredicate<T, U>`
1756    ///
1757    /// # Returns
1758    ///
1759    /// A `BoxBiPredicate` representing the logical OR.
1760    fn or<P>(self, other: P) -> BoxBiPredicate<T, U>
1761    where
1762        P: BiPredicate<T, U> + 'static,
1763        T: 'static,
1764        U: 'static,
1765    {
1766        BoxBiPredicate::new(move |first, second| self(first, second) || other.test(first, second))
1767    }
1768
1769    /// Returns a bi-predicate that represents the logical negation of
1770    /// this bi-predicate.
1771    ///
1772    /// # Returns
1773    ///
1774    /// A `BoxBiPredicate` representing the logical negation.
1775    fn not(self) -> BoxBiPredicate<T, U>
1776    where
1777        T: 'static,
1778        U: 'static,
1779    {
1780        BoxBiPredicate::new(move |first, second| !self(first, second))
1781    }
1782
1783    /// Returns a bi-predicate that represents the logical NAND (NOT
1784    /// AND) of this bi-predicate and another.
1785    ///
1786    /// NAND returns `true` unless both bi-predicates are `true`.
1787    /// Equivalent to `!(self AND other)`.
1788    ///
1789    /// # Parameters
1790    ///
1791    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1792    ///   is passed by value and will transfer ownership.** If you need to
1793    ///   preserve the original bi-predicate, clone it first (if it implements
1794    ///   `Clone`). Can be:
1795    ///   - Another closure: `|x: &T, y: &U| -> bool`
1796    ///   - A function pointer: `fn(&T, &U) -> bool`
1797    ///   - A `BoxBiPredicate<T, U>`
1798    ///   - An `RcBiPredicate<T, U>`
1799    ///   - An `ArcBiPredicate<T, U>`
1800    ///   - Any type implementing `BiPredicate<T, U>`
1801    ///
1802    /// # Returns
1803    ///
1804    /// A `BoxBiPredicate` representing the logical NAND.
1805    fn nand<P>(self, other: P) -> BoxBiPredicate<T, U>
1806    where
1807        P: BiPredicate<T, U> + 'static,
1808        T: 'static,
1809        U: 'static,
1810    {
1811        BoxBiPredicate::new(move |first, second| {
1812            !(self(first, second) && other.test(first, second))
1813        })
1814    }
1815
1816    /// Returns a bi-predicate that represents the logical XOR
1817    /// (exclusive OR) of this bi-predicate and another.
1818    ///
1819    /// XOR returns `true` if exactly one of the bi-predicates is
1820    /// `true`.
1821    ///
1822    /// # Parameters
1823    ///
1824    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1825    ///   is passed by value and will transfer ownership.** If you need to
1826    ///   preserve the original bi-predicate, clone it first (if it implements
1827    ///   `Clone`). Can be:
1828    ///   - Another closure: `|x: &T, y: &U| -> bool`
1829    ///   - A function pointer: `fn(&T, &U) -> bool`
1830    ///   - A `BoxBiPredicate<T, U>`
1831    ///   - An `RcBiPredicate<T, U>`
1832    ///   - An `ArcBiPredicate<T, U>`
1833    ///   - Any type implementing `BiPredicate<T, U>`
1834    ///
1835    /// # Returns
1836    ///
1837    /// A `BoxBiPredicate` representing the logical XOR.
1838    fn xor<P>(self, other: P) -> BoxBiPredicate<T, U>
1839    where
1840        P: BiPredicate<T, U> + 'static,
1841        T: 'static,
1842        U: 'static,
1843    {
1844        BoxBiPredicate::new(move |first, second| self(first, second) ^ other.test(first, second))
1845    }
1846
1847    /// Returns a bi-predicate that represents the logical NOR (NOT
1848    /// OR) of this bi-predicate and another.
1849    ///
1850    /// NOR returns `true` only if both bi-predicates are `false`.
1851    /// Equivalent to `!(self OR other)`.
1852    ///
1853    /// # Parameters
1854    ///
1855    /// * `other` - The other bi-predicate to combine with. **Note: This parameter
1856    ///   is passed by value and will transfer ownership.** If you need to
1857    ///   preserve the original bi-predicate, clone it first (if it implements
1858    ///   `Clone`). Can be:
1859    ///   - Another closure: `|x: &T, y: &U| -> bool`
1860    ///   - A function pointer: `fn(&T, &U) -> bool`
1861    ///   - A `BoxBiPredicate<T, U>`
1862    ///   - An `RcBiPredicate<T, U>`
1863    ///   - An `ArcBiPredicate<T, U>`
1864    ///   - Any type implementing `BiPredicate<T, U>`
1865    ///
1866    /// # Returns
1867    ///
1868    /// A `BoxBiPredicate` representing the logical NOR.
1869    fn nor<P>(self, other: P) -> BoxBiPredicate<T, U>
1870    where
1871        P: BiPredicate<T, U> + 'static,
1872        T: 'static,
1873        U: 'static,
1874    {
1875        BoxBiPredicate::new(move |first, second| {
1876            !(self(first, second) || other.test(first, second))
1877        })
1878    }
1879}
1880
1881// Blanket implementation for all closures
1882impl<T, U, F> FnBiPredicateOps<T, U> for F where F: Fn(&T, &U) -> bool + 'static {}