BoxTester

Struct BoxTester 

Source
pub struct BoxTester { /* private fields */ }
Expand description

Single ownership Tester implemented using Box

BoxTester wraps a closure in Box<dyn Fn() -> bool>, providing single ownership semantics with no additional allocation overhead beyond the initial boxing.

§Characteristics

  • Single ownership: Cannot be cloned
  • Zero overhead: Single heap allocation
  • Consuming combination: and()/or()/not() consume self
  • Type flexibility: Accepts any Tester implementation

§Use Cases

  • One-time testing scenarios
  • Builder patterns requiring ownership transfer
  • Simple state checking without sharing
  • Chained calls with ownership transfer

§Examples

use prism3_function::{BoxTester, Tester};
use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};

// State managed externally
let count = Arc::new(AtomicUsize::new(0));
let count_clone = Arc::clone(&count);

let tester = BoxTester::new(move || {
    count_clone.load(Ordering::Relaxed) < 3
});

assert!(tester.test());
count.fetch_add(1, Ordering::Relaxed);
assert!(tester.test());
count.fetch_add(1, Ordering::Relaxed);
assert!(tester.test());
count.fetch_add(1, Ordering::Relaxed);
assert!(!tester.test());

// Logical combination
let combined = BoxTester::new(|| true)
    .and(|| false)
    .or(|| true);
assert!(combined.test());

§Author

Hu Haixing

Implementations§

Source§

impl BoxTester

Source

pub fn new<F>(f: F) -> Self
where F: Fn() -> bool + 'static,

Creates a new BoxTester from a closure

§Type Parameters
  • F - Closure type implementing Fn() -> bool
§Parameters
  • f - The closure to wrap
§Return Value

A new BoxTester instance

§Examples
use prism3_function::BoxTester;

let tester = BoxTester::new(|| true);
Source

pub fn and<T>(self, next: T) -> BoxTester
where T: Tester + 'static,

Combines this tester with another tester using logical AND

Returns a new BoxTester that returns true only when both tests pass. Short-circuit evaluation: if the first test fails, the second will not be executed.

§Type Parameters
  • T - Type implementing Tester
§Parameters
  • next - The tester to combine with
§Return Value

A new BoxTester representing logical AND

§Examples
use prism3_function::{BoxTester, Tester};
use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering}};

// Simulate service status
let request_count = Arc::new(AtomicUsize::new(0));
let is_available = Arc::new(AtomicBool::new(true));
let max_requests = 1000;

let count_clone = Arc::clone(&request_count);
let available_clone = Arc::clone(&is_available);

// Service available and request count not exceeded
let service_ok = BoxTester::new(move || {
    available_clone.load(Ordering::Relaxed)
})
.and(move || {
    count_clone.load(Ordering::Relaxed) < max_requests
});

// Initial state: available and request count 0
assert!(service_ok.test());

// Simulate request increase
request_count.store(500, Ordering::Relaxed);
assert!(service_ok.test());

// Request count exceeded
request_count.store(1500, Ordering::Relaxed);
assert!(!service_ok.test());

// Service unavailable
is_available.store(false, Ordering::Relaxed);
assert!(!service_ok.test());
Source

pub fn or<T>(self, next: T) -> BoxTester
where T: Tester + 'static,

Combines this tester with another tester using logical OR

Returns a new BoxTester that returns true if either test passes. Short-circuit evaluation: if the first test passes, the second will not be executed.

§Type Parameters
  • T - Type implementing Tester
§Parameters
  • next - The tester to combine with
§Return Value

A new BoxTester representing logical OR

§Examples
use prism3_function::{BoxTester, Tester};
use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering}};

// Simulate service status
let request_count = Arc::new(AtomicUsize::new(0));
let is_healthy = Arc::new(AtomicBool::new(true));
let max_requests = 100;

let count_clone = Arc::clone(&request_count);
let health_clone = Arc::clone(&is_healthy);

// Service healthy or low request count
let can_serve = BoxTester::new(move || {
    health_clone.load(Ordering::Relaxed)
})
.or(move || {
    count_clone.load(Ordering::Relaxed) < max_requests
});

// Initial state: healthy and request count 0
assert!(can_serve.test());

// Request count increased but within limit
request_count.store(50, Ordering::Relaxed);
assert!(can_serve.test());

// Request count exceeded but service healthy
request_count.store(150, Ordering::Relaxed);
assert!(can_serve.test()); // still healthy

// Service unhealthy but low request count
is_healthy.store(false, Ordering::Relaxed);
request_count.store(50, Ordering::Relaxed);
assert!(can_serve.test()); // low request count

// Unhealthy and high request count
request_count.store(150, Ordering::Relaxed);
assert!(!can_serve.test());
Source

pub fn not(self) -> BoxTester

Negates the result of this tester

Returns a new BoxTester that returns the opposite value of the original test result.

§Return Value

A new BoxTester representing logical NOT

§Examples
use prism3_function::{BoxTester, Tester};
use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};

// Simulate resource usage
let memory_usage = Arc::new(AtomicUsize::new(0));
let max_memory = 1024; // MB

let memory_clone = Arc::clone(&memory_usage);

// Memory usage not exceeded
let memory_ok = BoxTester::new(move || {
    memory_clone.load(Ordering::Relaxed) <= max_memory
});

// Initial state: normal memory usage
memory_usage.store(512, Ordering::Relaxed);
assert!(memory_ok.test());

// Memory usage exceeded (negated)
let memory_critical = memory_ok.not();
assert!(!memory_critical.test());

// Memory usage exceeded
memory_usage.store(2048, Ordering::Relaxed);
assert!(memory_critical.test());
Source

pub fn nand<T>(self, next: T) -> BoxTester
where T: Tester + 'static,

Combines this tester with another tester using logical NAND

Returns a new BoxTester that returns true unless both tests pass. Equivalent to !(self AND other).

§Type Parameters
  • T - Type implementing Tester
§Parameters
  • next - The tester to combine with
§Return Value

A new BoxTester representing logical NAND

§Examples
use prism3_function::{BoxTester, Tester};
use std::sync::{Arc, atomic::{AtomicBool, Ordering}};

let flag1 = Arc::new(AtomicBool::new(true));
let flag2 = Arc::new(AtomicBool::new(true));

let flag1_clone = Arc::clone(&flag1);
let flag2_clone = Arc::clone(&flag2);

let nand = BoxTester::new(move || {
    flag1_clone.load(Ordering::Relaxed)
})
.nand(move || {
    flag2_clone.load(Ordering::Relaxed)
});

// Both true returns false
assert!(!nand.test());

// At least one false returns true
flag1.store(false, Ordering::Relaxed);
assert!(nand.test());
Source

pub fn xor<T>(self, next: T) -> BoxTester
where T: Tester + 'static,

Combines this tester with another tester using logical XOR

Returns a new BoxTester that returns true if exactly one test passes.

§Type Parameters
  • T - Type implementing Tester
§Parameters
  • next - The tester to combine with
§Return Value

A new BoxTester representing logical XOR

§Examples
use prism3_function::{BoxTester, Tester};
use std::sync::{Arc, atomic::{AtomicBool, Ordering}};

let flag1 = Arc::new(AtomicBool::new(true));
let flag2 = Arc::new(AtomicBool::new(false));

let flag1_clone1 = Arc::clone(&flag1);
let flag2_clone1 = Arc::clone(&flag2);

let xor = BoxTester::new(move || {
    flag1_clone1.load(Ordering::Relaxed)
})
.xor(move || {
    flag2_clone1.load(Ordering::Relaxed)
});

// One true one false returns true
assert!(xor.test());

// Both true returns false
flag2.store(true, Ordering::Relaxed);
assert!(!xor.test());

// Both false returns false
flag1.store(false, Ordering::Relaxed);
flag2.store(false, Ordering::Relaxed);
assert!(!xor.test());
Source

pub fn nor<T>(self, next: T) -> BoxTester
where T: Tester + 'static,

Combines this tester with another tester using logical NOR

Returns a new BoxTester that returns true only when both tests fail. Equivalent to !(self OR other).

§Type Parameters
  • T - Type implementing Tester
§Parameters
  • next - The tester to combine with
§Return Value

A new BoxTester representing logical NOR

§Examples
use prism3_function::{BoxTester, Tester};
use std::sync::{Arc, atomic::{AtomicBool, Ordering}};

let flag1 = Arc::new(AtomicBool::new(false));
let flag2 = Arc::new(AtomicBool::new(false));

let flag1_clone = Arc::clone(&flag1);
let flag2_clone = Arc::clone(&flag2);

let nor = BoxTester::new(move || {
    flag1_clone.load(Ordering::Relaxed)
})
.nor(move || {
    flag2_clone.load(Ordering::Relaxed)
});

// Both false returns true
assert!(nor.test());

// At least one true returns false
flag1.store(true, Ordering::Relaxed);
assert!(!nor.test());

Trait Implementations§

Source§

impl Tester for BoxTester

Source§

fn test(&self) -> bool

Executes the test and returns the test result Read more
Source§

fn into_box(self) -> BoxTester

Converts this tester to BoxTester Read more
Source§

fn into_rc(self) -> RcTester

Converts this tester to RcTester Read more
Source§

fn into_fn(self) -> impl Fn() -> bool

Converts this tester to a boxed function pointer Read more
Source§

fn into_arc(self) -> ArcTester
where Self: Sized + Send + Sync + 'static,

Converts this tester to ArcTester Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.