prism3_function/tester.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025.
4 * 3-Prism Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # Tester Type
10//!
11//! Provides tester implementations that test conditions or states and return
12//! boolean values, without accepting input parameters.
13//!
14//! # Overview
15//!
16//! **Tester** is a functional abstraction for testing conditions or states
17//! without accepting input. It can check system status, wait for conditions,
18//! or perform health checks.
19//!
20//! This module implements **Option 3** from the design document: a unified
21//! `Tester` trait with multiple concrete implementations optimized for
22//! different ownership and concurrency scenarios.
23//!
24//! # Core Design Principles
25//!
26//! 1. **Returns boolean**: `Tester` returns `bool` to indicate test results
27//! 2. **Uses `&self`**: Tester is only responsible for "judgment", not
28//! "state management"
29//! 3. **No TesterOnce**: Very limited use cases, lacks practical examples
30//! 4. **State management is caller's responsibility**: Tester only reads
31//! state, does not modify state
32//!
33//! # Three Implementations
34//!
35//! - **`BoxTester`**: Single ownership using `Box<dyn Fn() -> bool>`.
36//! Zero overhead, cannot be cloned. Best for one-time use and builder
37//! patterns.
38//!
39//! - **`ArcTester`**: Thread-safe shared ownership using
40//! `Arc<dyn Fn() -> bool + Send + Sync>`. Can be cloned and sent across
41//! threads. Lock-free overhead.
42//!
43//! - **`RcTester`**: Single-threaded shared ownership using
44//! `Rc<dyn Fn() -> bool>`. Can be cloned but cannot be sent across
45//! threads. Lower overhead than `ArcTester`.
46//!
47//! # Comparison with Other Functional Abstractions
48//!
49//! | Type | Input | Output | self | Modify? | Use Cases |
50//! |-----------|-------|--------|-----------|---------|-------------|
51//! | Tester | None | `bool` | `&self` | No | State Check |
52//! | Predicate | `&T` | `bool` | `&self` | No | Filter |
53//! | Supplier | None | `T` | `&mut` | Yes | Factory |
54//!
55//! # Examples
56//!
57//! ## Basic State Checking
58//!
59//! ```rust
60//! use prism3_function::{BoxTester, Tester};
61//! use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
62//!
63//! // State managed externally
64//! let count = Arc::new(AtomicUsize::new(0));
65//! let count_clone = Arc::clone(&count);
66//!
67//! let tester = BoxTester::new(move || {
68//! count_clone.load(Ordering::Relaxed) <= 3
69//! });
70//!
71//! assert!(tester.test()); // true (0)
72//! count.fetch_add(1, Ordering::Relaxed);
73//! assert!(tester.test()); // true (1)
74//! count.fetch_add(1, Ordering::Relaxed);
75//! assert!(tester.test()); // true (2)
76//! count.fetch_add(1, Ordering::Relaxed);
77//! assert!(tester.test()); // true (3)
78//! count.fetch_add(1, Ordering::Relaxed);
79//! assert!(!tester.test()); // false (4)
80//! ```
81//!
82//! ## Logical Combination
83//!
84//! ```rust
85//! use prism3_function::{BoxTester, Tester};
86//! use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering}};
87//!
88//! // 模拟微服务健康检查场景
89//! let cpu_usage = Arc::new(AtomicUsize::new(0));
90//! let memory_usage = Arc::new(AtomicUsize::new(0));
91//! let is_healthy = Arc::new(AtomicBool::new(true));
92//! let is_ready = Arc::new(AtomicBool::new(false));
93//! let max_cpu = 80;
94//! let max_memory = 90;
95//!
96//! let cpu_clone = Arc::clone(&cpu_usage);
97//! let memory_clone = Arc::clone(&memory_usage);
98//! let health_clone = Arc::clone(&is_healthy);
99//! let ready_clone = Arc::clone(&is_ready);
100//!
101//! // 系统资源检查:CPU和内存都在安全范围内
102//! let resources_ok = BoxTester::new(move || {
103//! cpu_clone.load(Ordering::Relaxed) < max_cpu
104//! })
105//! .and(move || {
106//! memory_clone.load(Ordering::Relaxed) < max_memory
107//! });
108//!
109//! // 服务状态检查:健康或就绪
110//! let service_ok = BoxTester::new(move || {
111//! health_clone.load(Ordering::Relaxed)
112//! })
113//! .or(move || {
114//! ready_clone.load(Ordering::Relaxed)
115//! });
116//!
117//! // 组合条件:资源正常且服务可用
118//! let can_accept_traffic = resources_ok.and(service_ok);
119//!
120//! // 测试不同状态组合
121//! // 初始状态:资源正常且服务健康
122//! cpu_usage.store(50, Ordering::Relaxed);
123//! memory_usage.store(60, Ordering::Relaxed);
124//! assert!(can_accept_traffic.test()); // 资源正常且服务健康
125//!
126//! // 服务不健康但就绪
127//! is_healthy.store(false, Ordering::Relaxed);
128//! is_ready.store(true, Ordering::Relaxed);
129//! assert!(can_accept_traffic.test()); // 资源正常且服务就绪
130//!
131//! // CPU使用率过高
132//! cpu_usage.store(95, Ordering::Relaxed);
133//! assert!(!can_accept_traffic.test()); // 资源超限
134//!
135//! // 服务不健康但就绪
136//! is_healthy.store(false, Ordering::Relaxed);
137//! cpu_usage.store(50, Ordering::Relaxed);
138//! assert!(can_accept_traffic.test()); // 仍然就绪
139//! ```
140//!
141//! ## Thread-Safe Sharing
142//!
143//! ```rust
144//! use prism3_function::{ArcTester, Tester};
145//! use std::thread;
146//!
147//! let shared = ArcTester::new(|| true);
148//! let clone = shared.clone();
149//!
150//! let handle = thread::spawn(move || {
151//! clone.test()
152//! });
153//!
154//! assert!(handle.join().unwrap());
155//! ```
156//!
157//! # Author
158//!
159//! Hu Haixing
160
161use std::rc::Rc;
162use std::sync::Arc;
163
164// ============================================================================
165// Core Tester Trait
166// ============================================================================
167
168/// Tests whether a state or condition holds
169///
170/// Tester is a functional abstraction for testing states or conditions. It
171/// accepts no parameters and returns a boolean value indicating the test
172/// result of some state or condition.
173///
174/// # Core Characteristics
175///
176/// - **No input parameters**: Captures context through closures
177/// - **Returns boolean**: Indicates test results
178/// - **Uses `&self`**: Does not modify its own state, only reads external
179/// state
180/// - **Repeatable calls**: The same Tester can call `test()` multiple times
181///
182/// # Use Cases
183///
184/// - **State checking**: Check system or service status
185/// - **Condition waiting**: Repeatedly check until conditions are met
186/// - **Health monitoring**: Check system health status
187/// - **Precondition validation**: Verify conditions before operations
188///
189/// # Design Philosophy
190///
191/// Tester's responsibility is "test judgment", not "state management".
192/// State management is the caller's responsibility. Tester only reads state
193/// and returns judgment results.
194///
195/// # Examples
196///
197/// ```rust
198/// use prism3_function::{BoxTester, Tester};
199/// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
200///
201/// // State managed externally
202/// let ready = Arc::new(AtomicBool::new(false));
203/// let ready_clone = Arc::clone(&ready);
204///
205/// // Tester only responsible for reading state
206/// let tester = BoxTester::new(move || {
207/// ready_clone.load(Ordering::Acquire)
208/// });
209///
210/// // Can be called multiple times
211/// assert!(!tester.test());
212/// ready.store(true, Ordering::Release);
213/// assert!(tester.test());
214/// ```
215///
216/// # Author
217///
218/// Hu Haixing
219pub trait Tester {
220 /// Executes the test and returns the test result
221 ///
222 /// This method can be called multiple times without modifying the Tester's
223 /// own state.
224 ///
225 /// # Return Value
226 ///
227 /// Returns `true` if the condition holds, otherwise returns `false`
228 ///
229 /// # Examples
230 ///
231 /// ```rust
232 /// use prism3_function::{BoxTester, Tester};
233 ///
234 /// let tester = BoxTester::new(|| true);
235 /// assert!(tester.test());
236 /// ```
237 fn test(&self) -> bool;
238
239 /// Converts this tester to `BoxTester`
240 ///
241 /// # Return Value
242 ///
243 /// A `BoxTester` that wraps this tester
244 ///
245 /// # Examples
246 ///
247 /// ```rust
248 /// use prism3_function::{Tester, BoxTester};
249 ///
250 /// let closure = || true;
251 /// let boxed: BoxTester = closure.into_box();
252 /// ```
253 fn into_box(self) -> BoxTester
254 where
255 Self: Sized + 'static;
256
257 /// Converts this tester to `RcTester`
258 ///
259 /// # Return Value
260 ///
261 /// A `RcTester` that wraps this tester
262 ///
263 /// # Examples
264 ///
265 /// ```rust
266 /// use prism3_function::{Tester, RcTester};
267 ///
268 /// let closure = || true;
269 /// let rc: RcTester = closure.into_rc();
270 /// ```
271 fn into_rc(self) -> RcTester
272 where
273 Self: Sized + 'static;
274
275 /// Converts this tester to `ArcTester`
276 ///
277 /// # Return Value
278 ///
279 /// An `ArcTester` that wraps this tester
280 ///
281 /// # Examples
282 ///
283 /// ```rust
284 /// use prism3_function::{Tester, ArcTester};
285 ///
286 /// let closure = || true;
287 /// let arc: ArcTester = closure.into_arc();
288 /// ```
289 fn into_arc(self) -> ArcTester
290 where
291 Self: Sized + Send + Sync + 'static,
292 {
293 panic!("into_arc() is not supported for this type")
294 }
295}
296
297// ============================================================================
298// BoxTester: Single Ownership Implementation
299// ============================================================================
300
301/// Single ownership Tester implemented using `Box`
302///
303/// `BoxTester` wraps a closure in `Box<dyn Fn() -> bool>`, providing single
304/// ownership semantics with no additional allocation overhead beyond the
305/// initial boxing.
306///
307/// # Characteristics
308///
309/// - **Single ownership**: Cannot be cloned
310/// - **Zero overhead**: Single heap allocation
311/// - **Consuming combination**: `and()`/`or()`/`not()` consume `self`
312/// - **Type flexibility**: Accepts any `Tester` implementation
313///
314/// # Use Cases
315///
316/// - One-time testing scenarios
317/// - Builder patterns requiring ownership transfer
318/// - Simple state checking without sharing
319/// - Chained calls with ownership transfer
320///
321/// # Examples
322///
323/// ```rust
324/// use prism3_function::{BoxTester, Tester};
325/// use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
326///
327/// // State managed externally
328/// let count = Arc::new(AtomicUsize::new(0));
329/// let count_clone = Arc::clone(&count);
330///
331/// let tester = BoxTester::new(move || {
332/// count_clone.load(Ordering::Relaxed) < 3
333/// });
334///
335/// assert!(tester.test());
336/// count.fetch_add(1, Ordering::Relaxed);
337/// assert!(tester.test());
338/// count.fetch_add(1, Ordering::Relaxed);
339/// assert!(tester.test());
340/// count.fetch_add(1, Ordering::Relaxed);
341/// assert!(!tester.test());
342///
343/// // Logical combination
344/// let combined = BoxTester::new(|| true)
345/// .and(|| false)
346/// .or(|| true);
347/// assert!(combined.test());
348/// ```
349///
350/// # Author
351///
352/// Hu Haixing
353pub struct BoxTester {
354 func: Box<dyn Fn() -> bool>,
355}
356
357impl BoxTester {
358 /// Creates a new `BoxTester` from a closure
359 ///
360 /// # Type Parameters
361 ///
362 /// * `F` - Closure type implementing `Fn() -> bool`
363 ///
364 /// # Parameters
365 ///
366 /// * `f` - The closure to wrap
367 ///
368 /// # Return Value
369 ///
370 /// A new `BoxTester` instance
371 ///
372 /// # Examples
373 ///
374 /// ```rust
375 /// use prism3_function::BoxTester;
376 ///
377 /// let tester = BoxTester::new(|| true);
378 /// ```
379 pub fn new<F>(f: F) -> Self
380 where
381 F: Fn() -> bool + 'static,
382 {
383 BoxTester { func: Box::new(f) }
384 }
385
386 /// Combines this tester with another tester using logical AND
387 ///
388 /// Returns a new `BoxTester` that returns `true` only when both tests
389 /// pass. Short-circuit evaluation: if the first test fails, the second
390 /// will not be executed.
391 ///
392 /// # Type Parameters
393 ///
394 /// * `T` - Type implementing `Tester`
395 ///
396 /// # Parameters
397 ///
398 /// * `next` - The tester to combine with
399 ///
400 /// # Return Value
401 ///
402 /// A new `BoxTester` representing logical AND
403 ///
404 /// # Examples
405 ///
406 /// ```rust
407 /// use prism3_function::{BoxTester, Tester};
408 /// use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering}};
409 ///
410 /// // 模拟服务状态
411 /// let request_count = Arc::new(AtomicUsize::new(0));
412 /// let is_available = Arc::new(AtomicBool::new(true));
413 /// let max_requests = 1000;
414 ///
415 /// let count_clone = Arc::clone(&request_count);
416 /// let available_clone = Arc::clone(&is_available);
417 ///
418 /// // 服务可用且请求数未超限
419 /// let service_ok = BoxTester::new(move || {
420 /// available_clone.load(Ordering::Relaxed)
421 /// })
422 /// .and(move || {
423 /// count_clone.load(Ordering::Relaxed) < max_requests
424 /// });
425 ///
426 /// // 初始状态:可用且请求数为0
427 /// assert!(service_ok.test());
428 ///
429 /// // 模拟请求增加
430 /// request_count.store(500, Ordering::Relaxed);
431 /// assert!(service_ok.test());
432 ///
433 /// // 请求数超限
434 /// request_count.store(1500, Ordering::Relaxed);
435 /// assert!(!service_ok.test());
436 ///
437 /// // 服务不可用
438 /// is_available.store(false, Ordering::Relaxed);
439 /// assert!(!service_ok.test());
440 /// ```
441 pub fn and<T>(self, next: T) -> BoxTester
442 where
443 T: Tester + 'static,
444 {
445 let first = self.func;
446 let second = next;
447 BoxTester::new(move || first() && second.test())
448 }
449
450 /// Combines this tester with another tester using logical OR
451 ///
452 /// Returns a new `BoxTester` that returns `true` if either test passes.
453 /// Short-circuit evaluation: if the first test passes, the second will
454 /// not be executed.
455 ///
456 /// # Type Parameters
457 ///
458 /// * `T` - Type implementing `Tester`
459 ///
460 /// # Parameters
461 ///
462 /// * `next` - The tester to combine with
463 ///
464 /// # Return Value
465 ///
466 /// A new `BoxTester` representing logical OR
467 ///
468 /// # Examples
469 ///
470 /// ```rust
471 /// use prism3_function::{BoxTester, Tester};
472 /// use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering}};
473 ///
474 /// // 模拟服务状态
475 /// let request_count = Arc::new(AtomicUsize::new(0));
476 /// let is_healthy = Arc::new(AtomicBool::new(true));
477 /// let max_requests = 100;
478 ///
479 /// let count_clone = Arc::clone(&request_count);
480 /// let health_clone = Arc::clone(&is_healthy);
481 ///
482 /// // 服务健康或请求数较少
483 /// let can_serve = BoxTester::new(move || {
484 /// health_clone.load(Ordering::Relaxed)
485 /// })
486 /// .or(move || {
487 /// count_clone.load(Ordering::Relaxed) < max_requests
488 /// });
489 ///
490 /// // 初始状态:健康且请求数为0
491 /// assert!(can_serve.test());
492 ///
493 /// // 请求数增加但仍在限制内
494 /// request_count.store(50, Ordering::Relaxed);
495 /// assert!(can_serve.test());
496 ///
497 /// // 请求数超限但服务健康
498 /// request_count.store(150, Ordering::Relaxed);
499 /// assert!(can_serve.test()); // 仍然健康
500 ///
501 /// // 服务不健康但请求数少
502 /// is_healthy.store(false, Ordering::Relaxed);
503 /// request_count.store(50, Ordering::Relaxed);
504 /// assert!(can_serve.test()); // 请求数少
505 ///
506 /// // 既不健康又请求数多
507 /// request_count.store(150, Ordering::Relaxed);
508 /// assert!(!can_serve.test());
509 /// ```
510 pub fn or<T>(self, next: T) -> BoxTester
511 where
512 T: Tester + 'static,
513 {
514 let first = self.func;
515 let second = next;
516 BoxTester::new(move || first() || second.test())
517 }
518
519 /// Negates the result of this tester
520 ///
521 /// Returns a new `BoxTester` that returns the opposite value of the
522 /// original test result.
523 ///
524 /// # Return Value
525 ///
526 /// A new `BoxTester` representing logical NOT
527 ///
528 /// # Examples
529 ///
530 /// ```rust
531 /// use prism3_function::{BoxTester, Tester};
532 /// use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
533 ///
534 /// // 模拟资源使用情况
535 /// let memory_usage = Arc::new(AtomicUsize::new(0));
536 /// let max_memory = 1024; // MB
537 ///
538 /// let memory_clone = Arc::clone(&memory_usage);
539 ///
540 /// // 内存使用是否超限
541 /// let memory_ok = BoxTester::new(move || {
542 /// memory_clone.load(Ordering::Relaxed) <= max_memory
543 /// });
544 ///
545 /// // 初始状态:内存使用正常
546 /// memory_usage.store(512, Ordering::Relaxed);
547 /// assert!(memory_ok.test());
548 ///
549 /// // 内存使用是否超限(取反)
550 /// let memory_critical = memory_ok.not();
551 /// assert!(!memory_critical.test());
552 ///
553 /// // 内存使用超限
554 /// memory_usage.store(2048, Ordering::Relaxed);
555 /// assert!(memory_critical.test());
556 /// ```
557 #[allow(clippy::should_implement_trait)]
558 pub fn not(self) -> BoxTester {
559 let func = self.func;
560 BoxTester::new(move || !func())
561 }
562
563 /// Combines this tester with another tester using logical NAND
564 ///
565 /// Returns a new `BoxTester` that returns `true` unless both tests pass.
566 /// Equivalent to `!(self AND other)`.
567 ///
568 /// # Type Parameters
569 ///
570 /// * `T` - Type implementing `Tester`
571 ///
572 /// # Parameters
573 ///
574 /// * `next` - The tester to combine with
575 ///
576 /// # Return Value
577 ///
578 /// A new `BoxTester` representing logical NAND
579 ///
580 /// # Examples
581 ///
582 /// ```rust
583 /// use prism3_function::{BoxTester, Tester};
584 /// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
585 ///
586 /// let flag1 = Arc::new(AtomicBool::new(true));
587 /// let flag2 = Arc::new(AtomicBool::new(true));
588 ///
589 /// let flag1_clone = Arc::clone(&flag1);
590 /// let flag2_clone = Arc::clone(&flag2);
591 ///
592 /// let nand = BoxTester::new(move || {
593 /// flag1_clone.load(Ordering::Relaxed)
594 /// })
595 /// .nand(move || {
596 /// flag2_clone.load(Ordering::Relaxed)
597 /// });
598 ///
599 /// // 两个都为 true 时返回 false
600 /// assert!(!nand.test());
601 ///
602 /// // 至少一个为 false 时返回 true
603 /// flag1.store(false, Ordering::Relaxed);
604 /// assert!(nand.test());
605 /// ```
606 pub fn nand<T>(self, next: T) -> BoxTester
607 where
608 T: Tester + 'static,
609 {
610 let first = self.func;
611 let second = next;
612 BoxTester::new(move || !(first() && second.test()))
613 }
614
615 /// Combines this tester with another tester using logical XOR
616 ///
617 /// Returns a new `BoxTester` that returns `true` if exactly one test
618 /// passes.
619 ///
620 /// # Type Parameters
621 ///
622 /// * `T` - Type implementing `Tester`
623 ///
624 /// # Parameters
625 ///
626 /// * `next` - The tester to combine with
627 ///
628 /// # Return Value
629 ///
630 /// A new `BoxTester` representing logical XOR
631 ///
632 /// # Examples
633 ///
634 /// ```rust
635 /// use prism3_function::{BoxTester, Tester};
636 /// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
637 ///
638 /// let flag1 = Arc::new(AtomicBool::new(true));
639 /// let flag2 = Arc::new(AtomicBool::new(false));
640 ///
641 /// let flag1_clone1 = Arc::clone(&flag1);
642 /// let flag2_clone1 = Arc::clone(&flag2);
643 ///
644 /// let xor = BoxTester::new(move || {
645 /// flag1_clone1.load(Ordering::Relaxed)
646 /// })
647 /// .xor(move || {
648 /// flag2_clone1.load(Ordering::Relaxed)
649 /// });
650 ///
651 /// // 一个 true 一个 false 时返回 true
652 /// assert!(xor.test());
653 ///
654 /// // 两个都为 true 时返回 false
655 /// flag2.store(true, Ordering::Relaxed);
656 /// assert!(!xor.test());
657 ///
658 /// // 两个都为 false 时返回 false
659 /// flag1.store(false, Ordering::Relaxed);
660 /// flag2.store(false, Ordering::Relaxed);
661 /// assert!(!xor.test());
662 /// ```
663 pub fn xor<T>(self, next: T) -> BoxTester
664 where
665 T: Tester + 'static,
666 {
667 let first = self.func;
668 let second = next;
669 BoxTester::new(move || first() ^ second.test())
670 }
671
672 /// Combines this tester with another tester using logical NOR
673 ///
674 /// Returns a new `BoxTester` that returns `true` only when both tests
675 /// fail. Equivalent to `!(self OR other)`.
676 ///
677 /// # Type Parameters
678 ///
679 /// * `T` - Type implementing `Tester`
680 ///
681 /// # Parameters
682 ///
683 /// * `next` - The tester to combine with
684 ///
685 /// # Return Value
686 ///
687 /// A new `BoxTester` representing logical NOR
688 ///
689 /// # Examples
690 ///
691 /// ```rust
692 /// use prism3_function::{BoxTester, Tester};
693 /// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
694 ///
695 /// let flag1 = Arc::new(AtomicBool::new(false));
696 /// let flag2 = Arc::new(AtomicBool::new(false));
697 ///
698 /// let flag1_clone = Arc::clone(&flag1);
699 /// let flag2_clone = Arc::clone(&flag2);
700 ///
701 /// let nor = BoxTester::new(move || {
702 /// flag1_clone.load(Ordering::Relaxed)
703 /// })
704 /// .nor(move || {
705 /// flag2_clone.load(Ordering::Relaxed)
706 /// });
707 ///
708 /// // 两个都为 false 时返回 true
709 /// assert!(nor.test());
710 ///
711 /// // 至少一个为 true 时返回 false
712 /// flag1.store(true, Ordering::Relaxed);
713 /// assert!(!nor.test());
714 /// ```
715 pub fn nor<T>(self, next: T) -> BoxTester
716 where
717 T: Tester + 'static,
718 {
719 let first = self.func;
720 let second = next;
721 BoxTester::new(move || !(first() || second.test()))
722 }
723}
724
725impl Tester for BoxTester {
726 fn test(&self) -> bool {
727 (self.func)()
728 }
729
730 fn into_box(self) -> BoxTester {
731 self
732 }
733
734 fn into_rc(self) -> RcTester {
735 let func = self.func;
736 RcTester {
737 func: Rc::new(func),
738 }
739 }
740
741 fn into_arc(self) -> ArcTester {
742 // Note: This conversion is impossible because Box<dyn Fn() -> bool>
743 // may not implement Send + Sync. Users should create ArcTester
744 // directly.
745 panic!(
746 "Cannot convert BoxTester to ArcTester. Create ArcTester \
747 directly with ArcTester::new()"
748 )
749 }
750}
751
752// ============================================================================
753// ArcTester: Thread-Safe Shared Ownership Implementation
754// ============================================================================
755
756/// Thread-safe shared ownership Tester implemented using `Arc`
757///
758/// `ArcTester` wraps a closure in `Arc<dyn Fn() -> bool + Send + Sync>`,
759/// allowing the tester to be cloned and safely shared across threads.
760///
761/// # Characteristics
762///
763/// - **Shared ownership**: Can be cloned
764/// - **Thread-safe**: Can be sent across threads
765/// - **Lock-free overhead**: Uses `Fn` without needing `Mutex`
766/// - **Borrowing combination**: `and()`/`or()`/`not()` borrow `&self`
767///
768/// # Use Cases
769///
770/// - Multi-threaded testing scenarios
771/// - Health checks shared across threads
772/// - Test states requiring concurrent access
773/// - Background monitoring tasks
774///
775/// # Examples
776///
777/// ```rust
778/// use prism3_function::{ArcTester, Tester};
779/// use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
780/// use std::thread;
781///
782/// // Shared atomic counter
783/// let counter = Arc::new(AtomicUsize::new(0));
784/// let counter_clone = Arc::clone(&counter);
785///
786/// let shared = ArcTester::new(move || {
787/// counter_clone.load(Ordering::Relaxed) <= 5
788/// });
789///
790/// let clone = shared.clone();
791/// let handle = thread::spawn(move || {
792/// clone.test()
793/// });
794///
795/// assert!(handle.join().unwrap());
796/// counter.fetch_add(1, Ordering::Relaxed);
797/// assert!(shared.test());
798/// ```
799///
800/// # Author
801///
802/// Hu Haixing
803pub struct ArcTester {
804 func: Arc<dyn Fn() -> bool + Send + Sync>,
805}
806
807impl ArcTester {
808 /// Creates a new `ArcTester` from a closure
809 ///
810 /// # Type Parameters
811 ///
812 /// * `F` - Closure type implementing `Fn() -> bool + Send + Sync`
813 ///
814 /// # Parameters
815 ///
816 /// * `f` - The closure to wrap
817 ///
818 /// # Return Value
819 ///
820 /// A new `ArcTester` instance
821 ///
822 /// # Examples
823 ///
824 /// ```rust
825 /// use prism3_function::ArcTester;
826 ///
827 /// let tester = ArcTester::new(|| true);
828 /// ```
829 pub fn new<F>(f: F) -> Self
830 where
831 F: Fn() -> bool + Send + Sync + 'static,
832 {
833 ArcTester { func: Arc::new(f) }
834 }
835
836 /// Combines this tester with another tester using logical AND
837 ///
838 /// Returns a new `ArcTester` that returns `true` only when both tests
839 /// pass. Borrows `&self`, so the original tester remains available.
840 ///
841 /// # Parameters
842 ///
843 /// * `next` - The tester to combine with
844 ///
845 /// # Return Value
846 ///
847 /// A new `ArcTester` representing logical AND
848 ///
849 /// # Examples
850 ///
851 /// ```rust
852 /// use prism3_function::{ArcTester, Tester};
853 /// use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering}};
854 /// use std::thread;
855 ///
856 /// // 模拟数据库连接池状态
857 /// let active_connections = Arc::new(AtomicUsize::new(0));
858 /// let is_pool_healthy = Arc::new(AtomicBool::new(true));
859 /// let max_connections = 50;
860 ///
861 /// let conn_clone = Arc::clone(&active_connections);
862 /// let health_clone = Arc::clone(&is_pool_healthy);
863 ///
864 /// // 连接池健康检查
865 /// let pool_healthy = ArcTester::new(move || {
866 /// health_clone.load(Ordering::Relaxed)
867 /// });
868 ///
869 /// // 连接数检查
870 /// let conn_ok = ArcTester::new(move || {
871 /// conn_clone.load(Ordering::Relaxed) < max_connections
872 /// });
873 ///
874 /// // 组合检查:连接池健康且连接数未超限
875 /// let pool_ready = pool_healthy.and(&conn_ok);
876 ///
877 /// // 多线程测试
878 /// let pool_ready_clone = pool_ready.clone();
879 /// let handle = thread::spawn(move || {
880 /// pool_ready_clone.test()
881 /// });
882 ///
883 /// // 初始状态应该通过
884 /// assert!(handle.join().unwrap());
885 /// assert!(pool_ready.test());
886 ///
887 /// // 连接数超限
888 /// active_connections.store(60, Ordering::Relaxed);
889 /// assert!(!pool_ready.test());
890 ///
891 /// // 连接池不健康
892 /// is_pool_healthy.store(false, Ordering::Relaxed);
893 /// assert!(!pool_ready.test());
894 /// ```
895 pub fn and(&self, next: &ArcTester) -> ArcTester {
896 let first = Arc::clone(&self.func);
897 let second = Arc::clone(&next.func);
898 ArcTester {
899 func: Arc::new(move || first() && second()),
900 }
901 }
902
903 /// Combines this tester with another tester using logical OR
904 ///
905 /// Returns a new `ArcTester` that returns `true` if either test passes.
906 /// Borrows `&self`, so the original tester remains available.
907 ///
908 /// # Parameters
909 ///
910 /// * `next` - The tester to combine with
911 ///
912 /// # Return Value
913 ///
914 /// A new `ArcTester` representing logical OR
915 ///
916 /// # Examples
917 ///
918 /// ```rust
919 /// use prism3_function::{ArcTester, Tester};
920 /// use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering}};
921 /// use std::thread;
922 ///
923 /// // 模拟负载均衡器状态
924 /// let server_load = Arc::new(AtomicUsize::new(0));
925 /// let is_server_healthy = Arc::new(AtomicBool::new(true));
926 /// let max_load = 80;
927 /// let emergency_mode = Arc::new(AtomicBool::new(false));
928 ///
929 /// let load_clone = Arc::clone(&server_load);
930 /// let health_clone = Arc::clone(&is_server_healthy);
931 /// let emergency_clone = Arc::clone(&emergency_mode);
932 ///
933 /// // 服务器负载低
934 /// let low_load = ArcTester::new(move || {
935 /// load_clone.load(Ordering::Relaxed) < max_load
936 /// });
937 ///
938 /// // 紧急模式检查
939 /// let emergency_check = ArcTester::new(move || {
940 /// emergency_clone.load(Ordering::Relaxed)
941 /// });
942 ///
943 /// // 服务器健康检查
944 /// let server_healthy = ArcTester::new(move || {
945 /// health_clone.load(Ordering::Relaxed)
946 /// });
947 ///
948 /// // 紧急模式或服务器健康
949 /// let can_handle_requests = emergency_check.or(&server_healthy);
950 ///
951 /// // 组合条件:负载低或可以处理请求
952 /// let should_route_here = low_load.or(&can_handle_requests);
953 ///
954 /// // 多线程测试
955 /// let router_clone = should_route_here.clone();
956 /// let handle = thread::spawn(move || {
957 /// router_clone.test()
958 /// });
959 ///
960 /// // 初始状态:负载低且健康
961 /// assert!(handle.join().unwrap());
962 /// assert!(should_route_here.test());
963 ///
964 /// // 负载高但服务器健康
965 /// server_load.store(90, Ordering::Relaxed);
966 /// assert!(should_route_here.test()); // 仍然健康
967 ///
968 /// // 服务器不健康但紧急模式
969 /// is_server_healthy.store(false, Ordering::Relaxed);
970 /// emergency_mode.store(true, Ordering::Relaxed);
971 /// assert!(should_route_here.test()); // 紧急模式
972 ///
973 /// // 既不健康又非紧急模式
974 /// emergency_mode.store(false, Ordering::Relaxed);
975 /// assert!(!should_route_here.test());
976 /// ```
977 pub fn or(&self, next: &ArcTester) -> ArcTester {
978 let first = Arc::clone(&self.func);
979 let second = Arc::clone(&next.func);
980 ArcTester {
981 func: Arc::new(move || first() || second()),
982 }
983 }
984
985 /// Negates the result of this tester
986 ///
987 /// Returns a new `ArcTester` that returns the opposite value of the
988 /// original test result. Borrows `&self`, so the original tester remains
989 /// available.
990 ///
991 /// # Return Value
992 ///
993 /// A new `ArcTester` representing logical NOT
994 ///
995 /// # Examples
996 ///
997 /// ```rust
998 /// use prism3_function::{ArcTester, Tester};
999 /// use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
1000 /// use std::thread;
1001 ///
1002 /// // 模拟任务队列状态
1003 /// let pending_tasks = Arc::new(AtomicUsize::new(0));
1004 /// let max_queue_size = 100;
1005 ///
1006 /// let tasks_clone = Arc::clone(&pending_tasks);
1007 ///
1008 /// // 队列未满
1009 /// let queue_available = ArcTester::new(move || {
1010 /// tasks_clone.load(Ordering::Relaxed) < max_queue_size
1011 /// });
1012 ///
1013 /// // 队列已满(取反)
1014 /// let queue_full = queue_available.not();
1015 ///
1016 /// // 多线程测试
1017 /// let queue_full_clone = queue_full.clone();
1018 /// let handle = thread::spawn(move || {
1019 /// queue_full_clone.test()
1020 /// });
1021 ///
1022 /// // 初始状态:队列未满
1023 /// pending_tasks.store(50, Ordering::Relaxed);
1024 /// assert!(queue_available.test());
1025 /// assert!(!handle.join().unwrap());
1026 /// assert!(!queue_full.test());
1027 ///
1028 /// // 队列接近满载
1029 /// pending_tasks.store(95, Ordering::Relaxed);
1030 /// assert!(queue_available.test());
1031 /// assert!(!queue_full.test());
1032 ///
1033 /// // 队列已满
1034 /// pending_tasks.store(120, Ordering::Relaxed);
1035 /// assert!(!queue_available.test());
1036 /// assert!(queue_full.test());
1037 /// ```
1038 #[allow(clippy::should_implement_trait)]
1039 pub fn not(&self) -> ArcTester {
1040 let func = Arc::clone(&self.func);
1041 ArcTester {
1042 func: Arc::new(move || !func()),
1043 }
1044 }
1045
1046 /// Combines this tester with another tester using logical NAND
1047 ///
1048 /// Returns a new `ArcTester` that returns `true` unless both tests pass.
1049 /// Borrows `&self`, so the original tester remains available.
1050 ///
1051 /// # Parameters
1052 ///
1053 /// * `next` - The tester to combine with
1054 ///
1055 /// # Return Value
1056 ///
1057 /// A new `ArcTester` representing logical NAND
1058 ///
1059 /// # Examples
1060 ///
1061 /// ```rust
1062 /// use prism3_function::{ArcTester, Tester};
1063 /// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
1064 /// use std::thread;
1065 ///
1066 /// let flag1 = Arc::new(AtomicBool::new(true));
1067 /// let flag2 = Arc::new(AtomicBool::new(true));
1068 ///
1069 /// let flag1_clone = Arc::clone(&flag1);
1070 /// let flag2_clone = Arc::clone(&flag2);
1071 ///
1072 /// let tester1 = ArcTester::new(move || {
1073 /// flag1_clone.load(Ordering::Relaxed)
1074 /// });
1075 ///
1076 /// let tester2 = ArcTester::new(move || {
1077 /// flag2_clone.load(Ordering::Relaxed)
1078 /// });
1079 ///
1080 /// let nand = tester1.nand(&tester2);
1081 ///
1082 /// // 两个都为 true 时返回 false
1083 /// assert!(!nand.test());
1084 ///
1085 /// // 至少一个为 false 时返回 true
1086 /// flag1.store(false, Ordering::Relaxed);
1087 /// assert!(nand.test());
1088 ///
1089 /// // 原始 tester 仍然可用
1090 /// assert!(!tester1.test());
1091 /// assert!(tester2.test());
1092 /// ```
1093 pub fn nand(&self, next: &ArcTester) -> ArcTester {
1094 let first = Arc::clone(&self.func);
1095 let second = Arc::clone(&next.func);
1096 ArcTester {
1097 func: Arc::new(move || !(first() && second())),
1098 }
1099 }
1100
1101 /// Combines this tester with another tester using logical XOR
1102 ///
1103 /// Returns a new `ArcTester` that returns `true` if exactly one test
1104 /// passes. Borrows `&self`, so the original tester remains available.
1105 ///
1106 /// # Parameters
1107 ///
1108 /// * `next` - The tester to combine with
1109 ///
1110 /// # Return Value
1111 ///
1112 /// A new `ArcTester` representing logical XOR
1113 ///
1114 /// # Examples
1115 ///
1116 /// ```rust
1117 /// use prism3_function::{ArcTester, Tester};
1118 /// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
1119 /// use std::thread;
1120 ///
1121 /// let flag1 = Arc::new(AtomicBool::new(true));
1122 /// let flag2 = Arc::new(AtomicBool::new(false));
1123 ///
1124 /// let flag1_clone = Arc::clone(&flag1);
1125 /// let flag2_clone = Arc::clone(&flag2);
1126 ///
1127 /// let tester1 = ArcTester::new(move || {
1128 /// flag1_clone.load(Ordering::Relaxed)
1129 /// });
1130 ///
1131 /// let tester2 = ArcTester::new(move || {
1132 /// flag2_clone.load(Ordering::Relaxed)
1133 /// });
1134 ///
1135 /// let xor = tester1.xor(&tester2);
1136 ///
1137 /// // 一个 true 一个 false 时返回 true
1138 /// assert!(xor.test());
1139 ///
1140 /// // 两个都为 true 时返回 false
1141 /// flag2.store(true, Ordering::Relaxed);
1142 /// assert!(!xor.test());
1143 ///
1144 /// // 两个都为 false 时返回 false
1145 /// flag1.store(false, Ordering::Relaxed);
1146 /// flag2.store(false, Ordering::Relaxed);
1147 /// assert!(!xor.test());
1148 ///
1149 /// // 原始 tester 仍然可用
1150 /// assert!(!tester1.test());
1151 /// assert!(!tester2.test());
1152 /// ```
1153 pub fn xor(&self, next: &ArcTester) -> ArcTester {
1154 let first = Arc::clone(&self.func);
1155 let second = Arc::clone(&next.func);
1156 ArcTester {
1157 func: Arc::new(move || first() ^ second()),
1158 }
1159 }
1160
1161 /// Combines this tester with another tester using logical NOR
1162 ///
1163 /// Returns a new `ArcTester` that returns `true` only when both tests
1164 /// fail. Borrows `&self`, so the original tester remains available.
1165 ///
1166 /// # Parameters
1167 ///
1168 /// * `next` - The tester to combine with
1169 ///
1170 /// # Return Value
1171 ///
1172 /// A new `ArcTester` representing logical NOR
1173 ///
1174 /// # Examples
1175 ///
1176 /// ```rust
1177 /// use prism3_function::{ArcTester, Tester};
1178 /// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
1179 /// use std::thread;
1180 ///
1181 /// let flag1 = Arc::new(AtomicBool::new(false));
1182 /// let flag2 = Arc::new(AtomicBool::new(false));
1183 ///
1184 /// let flag1_clone = Arc::clone(&flag1);
1185 /// let flag2_clone = Arc::clone(&flag2);
1186 ///
1187 /// let tester1 = ArcTester::new(move || {
1188 /// flag1_clone.load(Ordering::Relaxed)
1189 /// });
1190 ///
1191 /// let tester2 = ArcTester::new(move || {
1192 /// flag2_clone.load(Ordering::Relaxed)
1193 /// });
1194 ///
1195 /// let nor = tester1.nor(&tester2);
1196 ///
1197 /// // 两个都为 false 时返回 true
1198 /// assert!(nor.test());
1199 ///
1200 /// // 至少一个为 true 时返回 false
1201 /// flag1.store(true, Ordering::Relaxed);
1202 /// assert!(!nor.test());
1203 ///
1204 /// // 原始 tester 仍然可用
1205 /// assert!(tester1.test());
1206 /// assert!(!tester2.test());
1207 /// ```
1208 pub fn nor(&self, next: &ArcTester) -> ArcTester {
1209 let first = Arc::clone(&self.func);
1210 let second = Arc::clone(&next.func);
1211 ArcTester {
1212 func: Arc::new(move || !(first() || second())),
1213 }
1214 }
1215}
1216
1217impl Tester for ArcTester {
1218 fn test(&self) -> bool {
1219 (self.func)()
1220 }
1221
1222 fn into_box(self) -> BoxTester {
1223 let func = self.func;
1224 BoxTester {
1225 func: Box::new(move || func()),
1226 }
1227 }
1228
1229 fn into_rc(self) -> RcTester {
1230 let func = self.func;
1231 RcTester {
1232 func: Rc::new(move || func()),
1233 }
1234 }
1235
1236 fn into_arc(self) -> ArcTester {
1237 self
1238 }
1239}
1240
1241impl Clone for ArcTester {
1242 /// Creates a clone of this `ArcTester`.
1243 ///
1244 /// The cloned instance shares the same underlying function with
1245 /// the original, allowing multiple references to the same test
1246 /// logic.
1247 fn clone(&self) -> Self {
1248 Self {
1249 func: Arc::clone(&self.func),
1250 }
1251 }
1252}
1253
1254// ============================================================================
1255// RcTester: Single-Threaded Shared Ownership Implementation
1256// ============================================================================
1257
1258/// Single-threaded shared ownership Tester implemented using `Rc`
1259///
1260/// `RcTester` wraps a closure in `Rc<dyn Fn() -> bool>`, allowing the tester
1261/// to be cloned and shared within a single thread. Since it doesn't use atomic
1262/// operations, it has lower overhead than `ArcTester`.
1263///
1264/// # Characteristics
1265///
1266/// - **Shared ownership**: Can be cloned
1267/// - **Single-threaded**: Cannot be sent across threads
1268/// - **Low overhead**: Uses `Fn` without needing `RefCell`
1269/// - **Borrowing combination**: `and()`/`or()`/`not()` borrow `&self`
1270///
1271/// # Use Cases
1272///
1273/// - Single-threaded testing scenarios requiring sharing
1274/// - Event-driven systems (single-threaded)
1275/// - Callback-intensive code requiring cloneable tests
1276/// - Performance-sensitive single-threaded code
1277///
1278/// # Examples
1279///
1280/// ```rust
1281/// use prism3_function::{RcTester, Tester};
1282///
1283/// let shared = RcTester::new(|| true);
1284///
1285/// // Clone for multiple uses
1286/// let clone1 = shared.clone();
1287/// let clone2 = shared.clone();
1288///
1289/// // Non-consuming combination
1290/// let combined = shared.and(&clone1);
1291/// ```
1292///
1293/// # Author
1294///
1295/// Hu Haixing
1296pub struct RcTester {
1297 func: Rc<dyn Fn() -> bool>,
1298}
1299
1300impl RcTester {
1301 /// Creates a new `RcTester` from a closure
1302 ///
1303 /// # Type Parameters
1304 ///
1305 /// * `F` - Closure type implementing `Fn() -> bool`
1306 ///
1307 /// # Parameters
1308 ///
1309 /// * `f` - The closure to wrap
1310 ///
1311 /// # Return Value
1312 ///
1313 /// A new `RcTester` instance
1314 ///
1315 /// # Examples
1316 ///
1317 /// ```rust
1318 /// use prism3_function::RcTester;
1319 ///
1320 /// let tester = RcTester::new(|| true);
1321 /// ```
1322 pub fn new<F>(f: F) -> Self
1323 where
1324 F: Fn() -> bool + 'static,
1325 {
1326 RcTester { func: Rc::new(f) }
1327 }
1328
1329 /// Combines this tester with another tester using logical AND
1330 ///
1331 /// Returns a new `RcTester` that returns `true` only when both tests
1332 /// pass. Borrows `&self`, so the original tester remains available.
1333 ///
1334 /// # Parameters
1335 ///
1336 /// * `next` - The tester to combine with
1337 ///
1338 /// # Return Value
1339 ///
1340 /// A new `RcTester` representing logical AND
1341 ///
1342 /// # Examples
1343 ///
1344 /// ```rust
1345 /// use prism3_function::{RcTester, Tester};
1346 ///
1347 /// let first = RcTester::new(|| true);
1348 /// let second = RcTester::new(|| true);
1349 /// let combined = first.and(&second);
1350 /// // first and second are still available
1351 /// ```
1352 pub fn and(&self, next: &RcTester) -> RcTester {
1353 let first = Rc::clone(&self.func);
1354 let second = Rc::clone(&next.func);
1355 RcTester {
1356 func: Rc::new(move || first() && second()),
1357 }
1358 }
1359
1360 /// Combines this tester with another tester using logical OR
1361 ///
1362 /// Returns a new `RcTester` that returns `true` if either test passes.
1363 /// Borrows `&self`, so the original tester remains available.
1364 ///
1365 /// # Parameters
1366 ///
1367 /// * `next` - The tester to combine with
1368 ///
1369 /// # Return Value
1370 ///
1371 /// A new `RcTester` representing logical OR
1372 ///
1373 /// # Examples
1374 ///
1375 /// ```rust
1376 /// use prism3_function::{RcTester, Tester};
1377 ///
1378 /// let first = RcTester::new(|| false);
1379 /// let second = RcTester::new(|| true);
1380 /// let combined = first.or(&second);
1381 /// // first and second are still available
1382 /// ```
1383 pub fn or(&self, next: &RcTester) -> RcTester {
1384 let first = Rc::clone(&self.func);
1385 let second = Rc::clone(&next.func);
1386 RcTester {
1387 func: Rc::new(move || first() || second()),
1388 }
1389 }
1390
1391 /// Negates the result of this tester
1392 ///
1393 /// Returns a new `RcTester` that returns the opposite value of the
1394 /// original test result. Borrows `&self`, so the original tester remains
1395 /// available.
1396 ///
1397 /// # Return Value
1398 ///
1399 /// A new `RcTester` representing logical NOT
1400 ///
1401 /// # Examples
1402 ///
1403 /// ```rust
1404 /// use prism3_function::{RcTester, Tester};
1405 ///
1406 /// let original = RcTester::new(|| true);
1407 /// let negated = original.not();
1408 /// // original is still available
1409 /// ```
1410 #[allow(clippy::should_implement_trait)]
1411 pub fn not(&self) -> RcTester {
1412 let func = Rc::clone(&self.func);
1413 RcTester {
1414 func: Rc::new(move || !func()),
1415 }
1416 }
1417
1418 /// Combines this tester with another tester using logical NAND
1419 ///
1420 /// Returns a new `RcTester` that returns `true` unless both tests pass.
1421 /// Borrows `&self`, so the original tester remains available.
1422 ///
1423 /// # Parameters
1424 ///
1425 /// * `next` - The tester to combine with
1426 ///
1427 /// # Return Value
1428 ///
1429 /// A new `RcTester` representing logical NAND
1430 ///
1431 /// # Examples
1432 ///
1433 /// ```rust
1434 /// use prism3_function::{RcTester, Tester};
1435 ///
1436 /// let first = RcTester::new(|| true);
1437 /// let second = RcTester::new(|| true);
1438 /// let nand = first.nand(&second);
1439 ///
1440 /// // 两个都为 true 时返回 false
1441 /// assert!(!nand.test());
1442 ///
1443 /// // first 和 second 仍然可用
1444 /// assert!(first.test());
1445 /// assert!(second.test());
1446 /// ```
1447 pub fn nand(&self, next: &RcTester) -> RcTester {
1448 let first = Rc::clone(&self.func);
1449 let second = Rc::clone(&next.func);
1450 RcTester {
1451 func: Rc::new(move || !(first() && second())),
1452 }
1453 }
1454
1455 /// Combines this tester with another tester using logical XOR
1456 ///
1457 /// Returns a new `RcTester` that returns `true` if exactly one test
1458 /// passes. Borrows `&self`, so the original tester remains available.
1459 ///
1460 /// # Parameters
1461 ///
1462 /// * `next` - The tester to combine with
1463 ///
1464 /// # Return Value
1465 ///
1466 /// A new `RcTester` representing logical XOR
1467 ///
1468 /// # Examples
1469 ///
1470 /// ```rust
1471 /// use prism3_function::{RcTester, Tester};
1472 ///
1473 /// let first = RcTester::new(|| true);
1474 /// let second = RcTester::new(|| false);
1475 /// let xor = first.xor(&second);
1476 ///
1477 /// // 一个 true 一个 false 时返回 true
1478 /// assert!(xor.test());
1479 ///
1480 /// // first 和 second 仍然可用
1481 /// assert!(first.test());
1482 /// assert!(!second.test());
1483 /// ```
1484 pub fn xor(&self, next: &RcTester) -> RcTester {
1485 let first = Rc::clone(&self.func);
1486 let second = Rc::clone(&next.func);
1487 RcTester {
1488 func: Rc::new(move || first() ^ second()),
1489 }
1490 }
1491
1492 /// Combines this tester with another tester using logical NOR
1493 ///
1494 /// Returns a new `RcTester` that returns `true` only when both tests
1495 /// fail. Borrows `&self`, so the original tester remains available.
1496 ///
1497 /// # Parameters
1498 ///
1499 /// * `next` - The tester to combine with
1500 ///
1501 /// # Return Value
1502 ///
1503 /// A new `RcTester` representing logical NOR
1504 ///
1505 /// # Examples
1506 ///
1507 /// ```rust
1508 /// use prism3_function::{RcTester, Tester};
1509 ///
1510 /// let first = RcTester::new(|| false);
1511 /// let second = RcTester::new(|| false);
1512 /// let nor = first.nor(&second);
1513 ///
1514 /// // 两个都为 false 时返回 true
1515 /// assert!(nor.test());
1516 ///
1517 /// // first 和 second 仍然可用
1518 /// assert!(!first.test());
1519 /// assert!(!second.test());
1520 /// ```
1521 pub fn nor(&self, next: &RcTester) -> RcTester {
1522 let first = Rc::clone(&self.func);
1523 let second = Rc::clone(&next.func);
1524 RcTester {
1525 func: Rc::new(move || !(first() || second())),
1526 }
1527 }
1528}
1529
1530impl Tester for RcTester {
1531 fn test(&self) -> bool {
1532 (self.func)()
1533 }
1534
1535 fn into_box(self) -> BoxTester {
1536 let func = self.func;
1537 BoxTester {
1538 func: Box::new(move || func()),
1539 }
1540 }
1541
1542 fn into_rc(self) -> RcTester {
1543 self
1544 }
1545
1546 fn into_arc(self) -> ArcTester {
1547 // Note: RcTester is not Send, so this conversion is impossible.
1548 // Users should create ArcTester directly.
1549 panic!(
1550 "Cannot convert RcTester to ArcTester. Create ArcTester \
1551 directly with ArcTester::new()"
1552 )
1553 }
1554}
1555
1556impl Clone for RcTester {
1557 /// Creates a clone of this `RcTester`.
1558 ///
1559 /// The cloned instance shares the same underlying function with
1560 /// the original, allowing multiple references to the same test
1561 /// logic.
1562 fn clone(&self) -> Self {
1563 Self {
1564 func: Rc::clone(&self.func),
1565 }
1566 }
1567}
1568
1569// ============================================================================
1570// Tester Implementation for Closures
1571// ============================================================================
1572
1573impl<F> Tester for F
1574where
1575 F: Fn() -> bool,
1576{
1577 fn test(&self) -> bool {
1578 self()
1579 }
1580
1581 fn into_box(self) -> BoxTester
1582 where
1583 Self: Sized + 'static,
1584 {
1585 BoxTester::new(self)
1586 }
1587
1588 fn into_rc(self) -> RcTester
1589 where
1590 Self: Sized + 'static,
1591 {
1592 RcTester::new(self)
1593 }
1594
1595 fn into_arc(self) -> ArcTester
1596 where
1597 Self: Sized + Send + Sync + 'static,
1598 {
1599 ArcTester::new(self)
1600 }
1601}
1602
1603// ============================================================================
1604// Extension Trait for Convenient Closure Conversion
1605// ============================================================================
1606
1607/// Extension trait providing logical composition methods for closures
1608///
1609/// This trait is automatically implemented for all closures and function
1610/// pointers that match `Fn() -> bool`, enabling method chaining starting
1611/// from a closure.
1612///
1613/// # Examples
1614///
1615/// ```rust
1616/// use prism3_function::{FnTesterOps, Tester};
1617///
1618/// let is_ready = || true;
1619/// let is_available = || true;
1620///
1621/// // Combine testers using extension methods
1622/// let combined = is_ready.and(is_available);
1623/// assert!(combined.test());
1624/// ```
1625///
1626/// # Author
1627///
1628/// Hu Haixing
1629pub trait FnTesterOps: Sized + Fn() -> bool + 'static {
1630 /// Returns a tester that represents the logical AND of this tester
1631 /// and another
1632 ///
1633 /// # Parameters
1634 ///
1635 /// * `other` - The other tester to combine with. **Note: This parameter
1636 /// is passed by value and will transfer ownership.** If you need to
1637 /// preserve the original tester, clone it first (if it implements
1638 /// `Clone`). Can be:
1639 /// - Another closure
1640 /// - A function pointer
1641 /// - A `BoxTester`, `RcTester`, or `ArcTester`
1642 ///
1643 /// # Return Value
1644 ///
1645 /// A `BoxTester` representing the logical AND
1646 ///
1647 /// # Examples
1648 ///
1649 /// ```rust
1650 /// use prism3_function::{FnTesterOps, Tester};
1651 ///
1652 /// let is_ready = || true;
1653 /// let is_available = || true;
1654 ///
1655 /// let combined = is_ready.and(is_available);
1656 /// assert!(combined.test());
1657 /// ```
1658 fn and<T>(self, other: T) -> BoxTester
1659 where
1660 T: Tester + 'static,
1661 {
1662 BoxTester::new(move || self.test() && other.test())
1663 }
1664
1665 /// Returns a tester that represents the logical OR of this tester
1666 /// and another
1667 ///
1668 /// # Parameters
1669 ///
1670 /// * `other` - The other tester to combine with. **Note: This parameter
1671 /// is passed by value and will transfer ownership.** If you need to
1672 /// preserve the original tester, clone it first (if it implements
1673 /// `Clone`). Can be:
1674 /// - Another closure
1675 /// - A function pointer
1676 /// - A `BoxTester`, `RcTester`, or `ArcTester`
1677 /// - Any type implementing `Tester`
1678 ///
1679 /// # Return Value
1680 ///
1681 /// A `BoxTester` representing the logical OR
1682 ///
1683 /// # Examples
1684 ///
1685 /// ```rust
1686 /// use prism3_function::{FnTesterOps, Tester};
1687 ///
1688 /// let is_ready = || false;
1689 /// let is_fallback = || true;
1690 ///
1691 /// let combined = is_ready.or(is_fallback);
1692 /// assert!(combined.test());
1693 /// ```
1694 fn or<T>(self, other: T) -> BoxTester
1695 where
1696 T: Tester + 'static,
1697 {
1698 BoxTester::new(move || self.test() || other.test())
1699 }
1700
1701 /// Returns a tester that represents the logical negation of this tester
1702 ///
1703 /// # Return Value
1704 ///
1705 /// A `BoxTester` representing the logical negation
1706 ///
1707 /// # Examples
1708 ///
1709 /// ```rust
1710 /// use prism3_function::{FnTesterOps, Tester};
1711 ///
1712 /// let is_ready = || false;
1713 /// let not_ready = is_ready.not();
1714 /// assert!(not_ready.test());
1715 /// ```
1716 fn not(self) -> BoxTester {
1717 BoxTester::new(move || !self.test())
1718 }
1719
1720 /// Returns a tester that represents the logical NAND (NOT AND) of this
1721 /// tester and another
1722 ///
1723 /// NAND returns `true` unless both testers are `true`.
1724 /// Equivalent to `!(self AND other)`.
1725 ///
1726 /// # Parameters
1727 ///
1728 /// * `other` - The other tester to combine with. **Note: This parameter
1729 /// is passed by value and will transfer ownership.** If you need to
1730 /// preserve the original tester, clone it first (if it implements
1731 /// `Clone`). Accepts closures, function pointers, or any
1732 /// `Tester` implementation.
1733 ///
1734 /// # Return Value
1735 ///
1736 /// A `BoxTester` representing the logical NAND
1737 ///
1738 /// # Examples
1739 ///
1740 /// ```rust
1741 /// use prism3_function::{FnTesterOps, Tester};
1742 ///
1743 /// let is_ready = || true;
1744 /// let is_available = || true;
1745 ///
1746 /// let nand = is_ready.nand(is_available);
1747 /// assert!(!nand.test()); // !(true && true) = false
1748 /// ```
1749 fn nand<T>(self, other: T) -> BoxTester
1750 where
1751 T: Tester + 'static,
1752 {
1753 BoxTester::new(move || !(self.test() && other.test()))
1754 }
1755
1756 /// Returns a tester that represents the logical XOR (exclusive OR) of
1757 /// this tester and another
1758 ///
1759 /// XOR returns `true` if exactly one of the testers is `true`.
1760 ///
1761 /// # Parameters
1762 ///
1763 /// * `other` - The other tester to combine with. **Note: This parameter
1764 /// is passed by value and will transfer ownership.** If you need to
1765 /// preserve the original tester, clone it first (if it implements
1766 /// `Clone`). Accepts closures, function pointers, or any
1767 /// `Tester` implementation.
1768 ///
1769 /// # Return Value
1770 ///
1771 /// A `BoxTester` representing the logical XOR
1772 ///
1773 /// # Examples
1774 ///
1775 /// ```rust
1776 /// use prism3_function::{FnTesterOps, Tester};
1777 ///
1778 /// let is_ready = || true;
1779 /// let is_available = || false;
1780 ///
1781 /// let xor = is_ready.xor(is_available);
1782 /// assert!(xor.test()); // true ^ false = true
1783 /// ```
1784 fn xor<T>(self, other: T) -> BoxTester
1785 where
1786 T: Tester + 'static,
1787 {
1788 BoxTester::new(move || self.test() ^ other.test())
1789 }
1790
1791 /// Returns a tester that represents the logical NOR (NOT OR) of this
1792 /// tester and another
1793 ///
1794 /// NOR returns `true` only when both testers are `false`. Equivalent
1795 /// to `!(self OR other)`.
1796 ///
1797 /// # Parameters
1798 ///
1799 /// * `other` - The other tester to combine with. **Note: This parameter
1800 /// is passed by value and will transfer ownership.** If you need to
1801 /// preserve the original tester, clone it first (if it implements
1802 /// `Clone`). Accepts closures, function pointers, or any
1803 /// `Tester` implementation.
1804 ///
1805 /// # Return Value
1806 ///
1807 /// A `BoxTester` representing the logical NOR
1808 ///
1809 /// # Examples
1810 ///
1811 /// ```rust
1812 /// use prism3_function::{FnTesterOps, Tester};
1813 ///
1814 /// let is_ready = || false;
1815 /// let is_available = || false;
1816 ///
1817 /// let nor = is_ready.nor(is_available);
1818 /// assert!(nor.test()); // !(false || false) = true
1819 /// ```
1820 fn nor<T>(self, other: T) -> BoxTester
1821 where
1822 T: Tester + 'static,
1823 {
1824 BoxTester::new(move || !(self.test() || other.test()))
1825 }
1826}
1827
1828// Blanket implementation for all closures
1829impl<F> FnTesterOps for F where F: Fn() -> bool + 'static {}