Overview of predicates-tree
masterpredicates-tree crate is used to render the results of boolean-valued predicate functions as a tree structure. This is useful for visualizing the evaluation logic or the outcome of complex predicate compositions.repository·master·Indexed 42 days ago
https://github.com/assert-rs/predicates-rsA Rust implementation of boolean-valued predicate functions providing a toolkit for building and composing complex logical conditions. Version 3.1.4 includes the predicates-core crate for foundational traits and the predicates-tree crate for visualizing evaluation logic as a tree structure. It features a composable first-order predicate trait, support for type erasure via BoxPredicate, and specialized predicates for floating-point proximity, membership checks, and custom function wrapping.
predicates-tree crate is used to render the results of boolean-valued predicate functions as a tree structure. This is useful for visualizing the evaluation logic or the outcome of complex predicate compositions.predicates-core crate provides a set of traits designed for working with boolean-valued predicate functions in Rust. It serves as the foundational layer for defining and composing logic that evaluates whether a given input satisfies specific conditions.To use predicates in your Rust project, add it to your Cargo.toml dependencies file.
[dependencies]
predicates = "3.1.4"After adding the dependency, import the library and its prelude to access the predicate functions. The prelude provides common traits and functions for building boolean-valued predicates.
extern crate predicates;
use predicates::prelude::*;A Predicate is a boolean-valued function of one argument. The core of the library is the Predicate<T> trait, which requires an eval method that takes a reference to an item of type T and returns a bool.
Predicates are highly composable. You can create them using pre-made functions, wrap existing functions, or implement the Predicate trait yourself. Once created, you can combine them using logical combinators like and, or, and not.
To implement a custom predicate, implement the Predicate<T> trait. For better integration (like failure reporting), it is also recommended to implement PredicateReflection and fmt::Display.
use std::fmt;
use predicates::prelude::*;
struct IsTheAnswer;
impl Predicate<i32> for IsTheAnswer {
fn eval(&self, variable: &i32) -> bool {
*variable == 42
}
}
impl predicates::reflection::PredicateReflection for IsTheAnswer {}
impl fmt::Display for IsTheAnswer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "var.is_the_answer()")
}
}
// Usage
assert_eq!(true, IsTheAnswer.eval(&42));use std::fmt;
use predicates::prelude::*;
struct IsTheAnswer;
impl Predicate<i32> for IsTheAnswer {
fn eval(&self, variable: &i32) -> bool {
*variable == 42
}
}
impl predicates::reflection::PredicateReflection for IsTheAnswer {}
impl fmt::Display for IsTheAnswer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "var.is_the_answer()")
}
}
assert_eq!(true, IsTheAnswer.eval(&42));
let almost_the_answer = IsTheAnswer.or(predicate::in_iter(vec![41, 43]));
assert_eq!(true, almost_the_answer.eval(&41));The FileContentPredicate<P> is an adapter that allows a predicate P (where P: Predicate<[u8]>) to be evaluated against a std::path::Path.
When eval is called on a FileContentPredicate:
P against that buffer.false (it does not panic, but swallows the I/O error during eval).This adapter is typically instantiated via the from_file_path() method on any predicate that implements Predicate<[u8]>.
The Predicate trait provides methods to combine multiple predicates into a single logical expression:
pred_a.and(pred_b): Returns true if both predicates succeed.pred_a.or(pred_b): Returns true if one or both predicates succeed.pred_a.not(): Returns true if the predicate fails.A predicate is a boolean-valued function of one argument. The predicates-rs library provides a composable first-order predicate trait that allows you to create and assemble combinatorial logic at runtime.
This is particularly useful for building dynamic filters and checks that can be modified via user interaction. By using predicates, you can separate the configuration logic (which builds the predicate) from the execution logic (which uses the predicate to filter or evaluate values), ensuring the execution code remains agnostic of the specific configuration.
The prelude module provides access to all extension traits and the predicate module, which covers the majority of common use cases. Importing the prelude is the recommended way to start using the library.
use predicates::prelude::*;The BinaryFilePredicate struct provides a .utf8() method that attempts to transform the predicate into a StrFilePredicate.
Option<StrFilePredicate>Some(StrFilePredicate). If the content is not valid UTF-8, it returns None.// Example of converting a binary predicate to a string predicate
let predicate_file = predicate::path::eq_file(Path::new("Cargo.toml")).utf8().unwrap();You can adapt a predicate that operates on byte slices ([u8]) to operate on file contents by using the from_file_path() extension method. This creates a FileContentPredicate which reads the file at a given path and applies the underlying predicate to the resulting byte buffer.
To use this, ensure your predicate chain ends with a predicate compatible with [u8] (like predicate::str::is_empty() after a UTF-8 conversion) and then call .from_file_path().
use predicates::prelude::*;
use std::path::Path;
// Create a predicate that checks if file content is NOT empty
let predicate_fn = predicate::str::is_empty().not().from_utf8().from_file_path();
// Evaluate against a file path
assert_eq!(true, predicate_fn.eval(Path::new("./tests/hello_world")));
assert_eq!(false, predicate_fn.eval(Path::new("./tests/empty_file")));Use the .boxed() method (provided by the PredicateBoxExt trait) to wrap a predicate in a BoxPredicate. This converts the predicate into a trait object, which is useful for:
BoxPredicate remains constant even if the underlying predicate logic changes (e.g., adding or removing steps).Vec<BoxPredicate<T>>.BoxPredicate automatically implements Debug and Display.Note: The predicate must implement Send, Sync, and 'static to be boxed.
use predicates::prelude::*;
let predicates = vec![
predicate::always().boxed(),
predicate::never().boxed(),
];
assert_eq!(true, predicates[0].eval(&4));
assert_eq!(false, predicates[1].eval(&4));