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}