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 = "3.0.4"
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 #![cfg_attr(docsrs, feature(doc_auto_cfg))]
203 
204 pub mod prelude;
205 
206 pub use predicates_core::*;
207 mod boxed;
208 pub use crate::boxed::*;
209 
210 // core predicates
211 pub mod constant;
212 pub mod function;
213 pub mod iter;
214 pub mod name;
215 pub mod ord;
216 
217 // combinators
218 pub mod boolean;
219 
220 // specialized primitive `Predicate` types
221 pub mod float;
222 pub mod path;
223 pub mod str;
224 
225 mod color;
226 use color::Palette;
227 mod utils;
228