1// Copyright (c) 2018 The predicates-rs Project Developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/license/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Composable first-order predicate functions.
10//!
11//! This library implements an interface to "predicates" - boolean-valued
12//! functions of one argument. This allows combinatorial logic to be created and
13//! assembled at runtime and then used one or more times for evaluating values.
14//! This sort of object is really useful when creating filters and checks that
15//! can be changed at runtime with user interaction - it allows a clean
16//! separation of concerns where the configuration code can be used to build up
17//! a predicate, and then that predicate can be given to the code that does the
18//! actual filtering without the filtering code knowing anything about user
19//! configuration. See the examples for how this can work.
20//!
21//! ## Installation
22//!
23//! Add this to your `Cargo.toml`:
24//!
25//! ```toml
26//! [dependencies]
27//! predicates = "2.1.5"
28//! ```
29//!
30//! A [prelude] is available to bring in all extension traits as well as providing
31//! `prelude::predicate` which focuses on the 90% case of the API.
32//! ```rust
33//! use predicates::prelude::*;
34//! ```
35//!
36//! ## Examples
37//!
38//! The simplest predicates are [`predicate::always`] and [`predicate::never`], which always
39//! returns `true` and always returns `false`, respectively. The values are simply ignored when
40//! evaluating against these predicates:
41//! ```rust
42//! use predicates::prelude::*;
43//!
44//! let always_true = predicate::always();
45//! assert_eq!(true, always_true.eval(&5));
46//! let always_false = predicate::never();
47//! assert_eq!(false, always_false.eval(&5));
48//! ```
49//!
50//! Pre-made predicates are available for types that implement the `PartialOrd` and
51//! `PartialEq` traits. The following example uses `lt`, but `eq`, `ne`, `le`, `gt`,
52//! `ge` are also available.
53//! ```rust
54//! use predicates::prelude::*;
55//!
56//! let less_than_ten = predicate::lt(10);
57//! assert_eq!(true, less_than_ten.eval(&9));
58//! assert_eq!(false, less_than_ten.eval(&11));
59//! ```
60//!
61//! Any function over a reference to the desired `Item` that returns `bool`
62//! can easily be made into a `Predicate` using the [`predicate::function`]
63//! function.
64//! ```rust
65//! use predicates::prelude::*;
66//!
67//! let bound = 5;
68//! let predicate_fn = predicate::function(|&x| x >= bound);
69//! let between_5_and_10 = predicate_fn.and(predicate::le(10));
70//! assert_eq!(true, between_5_and_10.eval(&7));
71//! assert_eq!(false, between_5_and_10.eval(&3));
72//! ```
73//!
74//! The `Predicate` type is actually a trait, and that trait implements a
75//! number of useful combinator functions. For example, evaluating for a value
76//! between two other values can be accomplished as follows:
77//! ```rust
78//! use predicates::prelude::*;
79//!
80//! let between_5_and_10 = predicate::ge(5).and(predicate::le(10));
81//! assert_eq!(true, between_5_and_10.eval(&7));
82//! assert_eq!(false, between_5_and_10.eval(&11));
83//! assert_eq!(false, between_5_and_10.eval(&4));
84//! ```
85//!
86//! The `Predicate` trait is pretty simple, the core of it is an
87//! implementation of a `eval` function that takes a single argument and
88//! returns a `bool`. Implementing a custom `Predicate` still allows all the
89//! usual combinators of the `Predicate` trait to work!
90//! ```rust
91//! use std::fmt;
92//!
93//! use predicates::prelude::*;
94//!
95//! struct IsTheAnswer;
96//! impl Predicate<i32> for IsTheAnswer {
97//! fn eval(&self, variable: &i32) -> bool {
98//! *variable == 42
99//! }
100//! }
101//! impl predicates::reflection::PredicateReflection for IsTheAnswer {}
102//! impl fmt::Display for IsTheAnswer {
103//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104//! write!(f, "var.is_the_answer()")
105//! }
106//! }
107//!
108//! assert_eq!(true, IsTheAnswer.eval(&42));
109//! let almost_the_answer = IsTheAnswer.or(predicate::in_iter(vec![41, 43]));
110//! assert_eq!(true, almost_the_answer.eval(&41));
111//! ```
112//!
113//! ## Choosing a Predicate
114//!
115//! General predicates
116//! - [`predicate::always`]
117//! - [`predicate::never`]
118//! - [`predicate::function`]
119//! - [`predicate::in_iter`]: Specified value must be in the `Iterator`.
120//! - [`predicate::in_iter(...).sort`]: Optimization for repeatedly called predicates.
121//! - [`predicate::in_hash`]: Optimization for repeatedly called predicates.
122//! - [`predicate::eq`]
123//! - [`predicate::float::is_close`]: Use this instead of `eq` for floating point values.
124//! - [`predicate::ne`]
125//! - [`predicate::ge`]
126//! - [`predicate::gt`]
127//! - [`predicate::le`]
128//! - [`predicate::lt`]
129//! - [`predicate::name`]: Improve readability of failure reporting by providing a meaningful name.
130//!
131//! Combinators
132//! - [`pred_a.and(pred_b)`]: Both predicates must succeed.
133//! - [`pred_a.or(pred_b)`]: One or both predicates must succeed.
134//! - [`pred_a.not()`]: The predicate must fail.
135//!
136//! `String` predicates
137//! - [`predicate::str::is_empty`]: Specified string must be empty
138//! - [`str_pred = predicate::path::eq_file(...).utf8`]: Specified string must equal the contents
139//! of the given file.
140//! - [`predicate::str::diff`]: Same as `eq` except report a diff. See [`DifferencePredicate`]
141//! for more features.
142//! - [`predicate::str::starts_with`]: Specified string must start with the given needle.
143//! - [`predicate::str::ends_with`]: Specified string must end with the given needle.
144//! - [`predicate::str::contains`]: Specified string must contain the given needle.
145//! - [`predicate::str::contains(...).count`]: Required number of times the needle must show up.
146//! - [`predicate::str::is_match`]: Specified string must match the given regex.
147//! - [`predicate::str::is_match(...).count`]: Required number of times the match must show up.
148//! - [`str_pred.trim`]: Trim whitespace before passing it to `str_pred`.
149//! - [`str_pred.normalize`]: Normalize the line endings before passing it to `str_pred`.
150//! - [`bytes_pred = str_pred.from_utf8()`]: Reuse string predicates in other contexts, like the
151//! file system.
152//!
153//! File system predicates
154//! - [`predicate::path::exists`]: Specified path must exist on disk.
155//! - [`predicate::path::missing`]: Specified path must not exist on disk.
156//! - [`predicate::path::is_dir`]: Specified path is a directory.
157//! - [`predicate::path::is_file`]: Specified path is a file.
158//! - [`predicate::path::is_symlink`]: Specified path is a symlink.
159//! - [`path_pred = predicate::path::eq_file`]: Specified path's contents must equal the contents of the given
160//! file.
161//! - [`path_pred = bytes_pred.from_file_path`]: Specified path's contents must equal the `bytes_pred`.
162//!
163//! [`DifferencePredicate`]: crate::str::DifferencePredicate
164//! [`bytes_pred = str_pred.from_utf8()`]: prelude::PredicateStrExt::from_utf8()
165//! [`path_pred = bytes_pred.from_file_path`]: prelude::PredicateFileContentExt::from_file_path()
166//! [`path_pred = predicate::path::eq_file`]: prelude::predicate::path::eq_file()
167//! [`pred_a.and(pred_b)`]: boolean::PredicateBooleanExt::and()
168//! [`pred_a.not()`]: boolean::PredicateBooleanExt::not()
169//! [`pred_a.or(pred_b)`]: boolean::PredicateBooleanExt::or()
170//! [`predicate::always`]: constant::always()
171//! [`predicate::eq`]: ord::eq()
172//! [`predicate::float::is_close`]: prelude::predicate::float::is_close()
173//! [`predicate::function`]: function::function()
174//! [`predicate::ge`]: ord::ge()
175//! [`predicate::gt`]: ord::gt()
176//! [`predicate::in_hash`]: iter::in_hash()
177//! [`predicate::in_iter(...).sort`]: iter::InPredicate::sort()
178//! [`predicate::in_iter`]: iter::in_iter()
179//! [`predicate::le`]: ord::le()
180//! [`predicate::lt`]: ord::lt()
181//! [`predicate::name`]: name::PredicateNameExt::name()
182//! [`predicate::ne`]: ord::ne()
183//! [`predicate::never`]: constant::never()
184//! [`predicate::path::exists`]: prelude::predicate::path::exists()
185//! [`predicate::path::is_dir`]: prelude::predicate::path::is_dir()
186//! [`predicate::path::is_file`]: prelude::predicate::path::is_file()
187//! [`predicate::path::is_symlink`]: prelude::predicate::path::is_symlink()
188//! [`predicate::path::missing`]: prelude::predicate::path::missing()
189//! [`predicate::str::contains(...).count`]: str::ContainsPredicate::count()
190//! [`predicate::str::contains`]: prelude::predicate::str::contains()
191//! [`predicate::str::diff`]: prelude::predicate::str::diff()
192//! [`predicate::str::ends_with`]: prelude::predicate::str::ends_with()
193//! [`predicate::str::is_empty`]: prelude::predicate::str::is_empty()
194//! [`predicate::str::is_match(...).count`]: str::RegexPredicate::count()
195//! [`predicate::str::is_match`]: prelude::predicate::str::is_match()
196//! [`predicate::str::starts_with`]: prelude::predicate::str::starts_with()
197//! [`str_pred = predicate::path::eq_file(...).utf8`]: path::BinaryFilePredicate::utf8()
198//! [`str_pred.normalize`]: prelude::PredicateStrExt::normalize()
199//! [`str_pred.trim`]: prelude::PredicateStrExt::trim()
200
201#![warn(missing_docs, missing_debug_implementations)]
202
203pub mod prelude;
204
205pub use predicates_core::*;
206mod boxed;
207pub use crate::boxed::*;
208
209// core predicates
210pub mod constant;
211pub mod function;
212pub mod iter;
213pub mod name;
214pub mod ord;
215
216// combinators
217pub mod boolean;
218
219// specialized primitive `Predicate` types
220pub mod float;
221pub mod path;
222pub mod str;
223
224mod color;
225use color::Palette;
226mod utils;
227