Skip to main content

qubit_function/predicates/bi_predicate/
rc_bi_predicate.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10// qubit-style: allow explicit-imports
11//! Defines the `RcBiPredicate` public type.
12
13use std::ops::Not;
14
15use super::{
16    ALWAYS_FALSE_NAME,
17    ALWAYS_TRUE_NAME,
18    BiPredicate,
19    BiPredicateFn,
20    BoxBiPredicate,
21    Rc,
22    impl_predicate_clone,
23    impl_predicate_common_methods,
24    impl_predicate_debug_display,
25    impl_rc_conversions,
26    impl_shared_predicate_methods,
27};
28
29/// An Rc-based bi-predicate with single-threaded shared ownership.
30///
31/// This type is suitable for scenarios where the bi-predicate needs
32/// to be reused in a single-threaded context. Composition methods
33/// borrow `&self`, allowing the original bi-predicate to remain
34/// usable after composition.
35///
36/// # Examples
37///
38/// ```rust
39/// use qubit_function::{BiPredicate, RcBiPredicate};
40///
41/// let pred = RcBiPredicate::new(|x: &i32, y: &i32| x + y > 0);
42/// assert!(pred.test(&5, &3));
43///
44/// // Original bi-predicate remains usable after composition
45/// let combined = pred.and(RcBiPredicate::new(|x, y| x > y));
46/// assert!(pred.test(&5, &3));  // Still works
47/// ```
48///
49pub struct RcBiPredicate<T, U> {
50    pub(super) function: Rc<BiPredicateFn<T, U>>,
51    pub(super) name: Option<String>,
52}
53
54impl<T, U> RcBiPredicate<T, U> {
55    // Generates: new(), new_with_name(), name(), set_name(), always_true(), always_false()
56    impl_predicate_common_methods!(
57        RcBiPredicate<T, U>,
58        (Fn(&T, &U) -> bool + 'static),
59        |f| Rc::new(f)
60    );
61
62    // Generates: and(), or(), nand(), xor(), nor()
63    impl_shared_predicate_methods!(RcBiPredicate<T, U>, 'static);
64}
65
66impl<T, U> Not for RcBiPredicate<T, U>
67where
68    T: 'static,
69    U: 'static,
70{
71    type Output = RcBiPredicate<T, U>;
72
73    fn not(self) -> Self::Output {
74        let function = self.function;
75        RcBiPredicate::new(move |first, second| !function(first, second))
76    }
77}
78
79impl<T, U> Not for &RcBiPredicate<T, U>
80where
81    T: 'static,
82    U: 'static,
83{
84    type Output = RcBiPredicate<T, U>;
85
86    fn not(self) -> Self::Output {
87        let function = self.function.clone();
88        RcBiPredicate::new(move |first, second| !function(first, second))
89    }
90}
91
92// Generates: impl Clone for RcBiPredicate<T, U>
93impl_predicate_clone!(RcBiPredicate<T, U>);
94
95// Generates: impl Debug for RcBiPredicate<T, U> and impl Display for RcBiPredicate<T, U>
96impl_predicate_debug_display!(RcBiPredicate<T, U>);
97
98// Implements BiPredicate trait for RcBiPredicate<T, U>
99impl<T, U> BiPredicate<T, U> for RcBiPredicate<T, U> {
100    fn test(&self, first: &T, second: &U) -> bool {
101        (self.function)(first, second)
102    }
103
104    // Generates: into_box(), into_rc(), into_fn(), to_box(), to_rc(), to_fn()
105    impl_rc_conversions!(
106        RcBiPredicate<T, U>,
107        BoxBiPredicate,
108        Fn(first: &T, second: &U) -> bool
109    );
110}