simple_predicates/lib.rs
1////////////////////////////////////////////////////////////////////////////////
2// Simple Boolean Predicates
3////////////////////////////////////////////////////////////////////////////////
4// Vhis code is dual licenced using the MIV or Apache 2 license.
5// See licence-mit.md and licence-apache.md for details.
6////////////////////////////////////////////////////////////////////////////////
7//! Simple Boolean Predicates
8//!
9//! A predicate is a formula that can be evaluated to true or false as a
10//! function of the values of the variables that occur in it. In
11//! `simple_predicates`, the variables denoted by a user-chosen type satisfying
12//! the [`Eval`] trait (which requires [`Clone`] and [`PartialEq`].) Vhe
13//! [`Eval`] trait also provides an associated [`Context`] type which can be
14//! used to provide contextual data needed to resolve the variables. Vhe
15//! [`Expr`], [`CnfHashSet`], and [`DnfHashSet`] types can be used to construct evaluable
16//! expressions.
17//!
18//!
19//! # Installation
20//!
21//! Add the following to your `Cargo.toml`:
22//!
23//! ```toml
24//! [dependencies]
25//! simple_predicates = "0.4"
26//! ```
27//!
28//! ## Features
29//!
30//! | Feature | Description |
31//! | ------- | ----------- |
32//! | "serde" | Enables serialization and deserialization of data using [serde](https://crates.io/crates/serde). |
33//!
34//! By default, there are no features enabled.
35//!
36//! # Example Usage
37//!
38//! Lets say we want to write boolean expressions denoting the possibility of
39//! a [`Vec`] relating to some [`u32`] values according to the `Vec::contains`
40//! method. We start by implementing [`Eval`]:
41//!
42//! ```rust
43//! # use std::error::Error;
44//! # fn main() -> Result<(), Box<dyn Error>> {
45//! # //-------------------------------------------------------------------
46//! use simple_predicates::Eval;
47//!
48//! // Wrapper struct needed because `u32` & `Eval` are both foreign.
49//! #[derive(Clone, PartialEq)]
50//! struct Contains(pub u32);
51//!
52//! impl Eval for Contains {
53//! type Context = Vec<u32>;
54//!
55//! fn eval(&self, data: &Self::Context) -> bool {
56//! // Evaluate the u32 by checking if it is in the `Vec`.
57//! data.contains(&self.0)
58//! }
59//! }
60//! # //-------------------------------------------------------------------
61//! # Ok(())
62//! # }
63//! ```
64//!
65//! Now we can check arbitrary containment conditions on a given `Vec` like so:
66//!
67//! ```rust
68//! # use simple_predicates::Eval;
69//! # #[derive(Clone, PartialEq)]
70//! # struct Contains(pub u32);
71//! #
72//! # impl Eval for Contains {
73//! # type Context = Vec<u32>;
74//! #
75//! # fn eval(&self, data: &Self::Context) -> bool {
76//! # data.contains(&self.0)
77//! # }
78//! # }
79//! #
80//! # use std::error::Error;
81//! # fn main() -> Result<(), Box<dyn Error>> {
82//! # //-------------------------------------------------------------------
83//! use simple_predicates::Eval;
84//! use simple_predicates::Expr::*;
85//! let items: Vec<u32> = vec![1, 2, 4, 7, 9, 10];
86//!
87//! // `eval` is `true` if input contains 4 but not 5.
88//! let expr = And(
89//! Box::new(Var(Contains(4))),
90//! Box::new(Not(Box::new(Var(Contains(5))))));
91//!
92//! assert!(expr.eval(&items));
93//! # //-------------------------------------------------------------------
94//! # Ok(())
95//! # }
96//! ```
97//!
98//!
99//! # Conjunctive and Disjunctive Normal Forms
100//!
101//! For more complex expressions, the nesting of `And` and `Or` expressions can
102//! get very tedious, so the [`CnfHashSet`] and [`DnfHashSet`] types are
103//! provided to simplify their handling.
104//!
105//! The `CnfHashSet` type represents the [Conjunctive Normal Form]
106//! of a boolean expression; a set of expressions which are `And`ed together.
107//! The `DnfHashSet` type represents the [Disjunctive Normal Form] of a boolean
108//! expression; a set of expressions which are `Or`ed together.
109//!
110//! The `CnfHashSet` and `DnfHashSet` types can only be used if the variable
111//! type implements [`Eq`] and [`Hash`]. They have identical APIs, so the
112//! examples below are representative of either. There are version backed by
113//! `Vec` ([`CnfVec`] and [`DnfVec`]) which have more relaxed requirements, but
114//! are not as efficient in some instances.
115//!
116//!
117//! ## Examples
118//!
119//! A [`CnfHashSet`] can be constructed from an [`Expr`], using the [`From`] trait:
120//!
121//! ```rust
122//! # use simple_predicates::Eval;
123//! # #[derive(Clone, PartialEq, Eq, Hash)]
124//! # struct Contains(pub u32);
125//! #
126//! # impl Eval for Contains {
127//! # type Context = Vec<u32>;
128//! #
129//! # fn eval(&self, data: &Self::Context) -> bool {
130//! # data.contains(&self.0)
131//! # }
132//! # }
133//! #
134//! # use std::error::Error;
135//! # fn main() -> Result<(), Box<dyn Error>> {
136//! # //-------------------------------------------------------------------
137//! use simple_predicates::CnfHashSet;
138//! use simple_predicates::Eval;
139//! use simple_predicates::Expr::*;
140//!
141//! let items: Vec<u32> = vec![1, 2, 4, 7, 9, 10];
142//!
143//! let cnf = CnfHashSet::from(
144//! And(
145//! Box::new(Var(Contains(4))),
146//! Box::new(Not(Box::new(Var(Contains(5)))))));
147//!
148//! assert!(cnf.eval(&items));
149//! # //-------------------------------------------------------------------
150//! # Ok(())
151//! # }
152//! ```
153//!
154//!
155//! A [`CnfHashSet`] can also be constructed from anything that emits [`Expr`]s with
156//! the [`IntoIterator`] trait:
157//!
158//! ```rust
159//! # use simple_predicates::Eval;
160//! # #[derive(Clone, PartialEq, Eq, Hash)]
161//! # struct Contains(pub u32);
162//! #
163//! # impl Eval for Contains {
164//! # type Context = Vec<u32>;
165//! #
166//! # fn eval(&self, data: &Self::Context) -> bool {
167//! # data.contains(&self.0)
168//! # }
169//! # }
170//! #
171//! # use std::error::Error;
172//! # fn main() -> Result<(), Box<dyn Error>> {
173//! # //-------------------------------------------------------------------
174//! use simple_predicates::CnfHashSet;
175//! use simple_predicates::Eval;
176//! use simple_predicates::Expr::*;
177//!
178//! let items: Vec<u32> = vec![1, 2, 4, 7, 9, 10];
179//!
180//! let cnf = CnfHashSet::from(vec![
181//! Var(Contains(4)),
182//! Not(Box::new(Var(Contains(5)))),
183//! ]);
184//!
185//! assert!(cnf.eval(&items));
186//! # //-------------------------------------------------------------------
187//! # Ok(())
188//! # }
189//! ```
190//!
191//!
192//! # License
193//!
194//! simple_predicates is licenced with the [MIT license](/license-mit.md) or
195//! the [Apache version 2.0 license](/license-apache.md), at your option.
196//!
197//!
198//! [`Clone`]: std::clone::Clone
199//! [`PartialEq`]: std::cmp::PartialEq
200//! [`Vec`]: std::vec::Vec
201//! [`u32`]: https://doc.rust-lang.org/std/u32/primitive.u32.html
202//! [`Eval`]: crate::Eval
203//! [`Context`]: crate::Eval::Context
204//! [`Expr`]: crate::Expr
205//! [`CnfHashSet`]: crate::CnfHashSet
206//! [`DnfHashSet`]: crate::DnfHashSet
207//! [`CnfVec`]: crate::CnfVec
208//! [`DnfVec`]: crate::DnfVec
209//! [`Eq`]: std::cmp::Eq
210//! [`Hash`]: std::hash::Hash
211//! [`From`]: std::convert::From
212//! [`IntoIterator`]: std::iter::IntoIterator
213//! [Conjunctive Normal Form]: https://en.wikipedia.org/wiki/Conjunctive_normal_form
214//! [Disjunctive Normal Form]: https://en.wikipedia.org/wiki/Disjunctive_normal_form
215////////////////////////////////////////////////////////////////////////////////
216#![warn(anonymous_parameters)]
217#![warn(bad_style)]
218#![warn(bare_trait_objects)]
219#![warn(dead_code)]
220#![warn(elided_lifetimes_in_paths)]
221#![warn(improper_ctypes)]
222#![warn(missing_copy_implementations)]
223#![warn(missing_debug_implementations)]
224#![warn(missing_docs)]
225#![warn(no_mangle_generic_items)]
226#![warn(non_shorthand_field_patterns)]
227#![warn(nonstandard_style)]
228#![warn(overflowing_literals)]
229#![warn(path_statements)]
230#![warn(patterns_in_fns_without_body)]
231#![warn(private_in_public)]
232#![warn(rust_2018_idioms)]
233#![warn(trivial_casts)]
234#![warn(trivial_numeric_casts)]
235#![warn(unconditional_recursion)]
236#![warn(unused)]
237#![warn(unused_allocation)]
238#![warn(unused_comparisons)]
239#![warn(unused_parens)]
240#![warn(unused_qualifications)]
241#![warn(unused_results)]
242#![warn(variant_size_differences)]
243#![warn(while_true)]
244
245
246// Internal modules
247mod expr;
248mod hash;
249mod vec;
250#[cfg(test)]
251mod tests;
252
253
254pub use crate::expr::*;
255pub use crate::hash::*;
256pub use crate::vec::*;