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/licenses/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 | //! Introspect into the state of a `Predicate`. |
10 | |
11 | use std::borrow; |
12 | use std::fmt; |
13 | use std::slice; |
14 | |
15 | /// Introspect the state of a `Predicate`. |
16 | pub trait PredicateReflection: fmt::Display { |
17 | /// Parameters of the current `Predicate`. |
18 | fn parameters<'a>(&'a self) -> Box<dyn Iterator<Item = Parameter<'a>> + 'a> { |
19 | let params = vec![]; |
20 | Box::new(params.into_iter()) |
21 | } |
22 | |
23 | /// Nested `Predicate`s of the current `Predicate`. |
24 | fn children<'a>(&'a self) -> Box<dyn Iterator<Item = Child<'a>> + 'a> { |
25 | let params = vec![]; |
26 | Box::new(params.into_iter()) |
27 | } |
28 | } |
29 | |
30 | /// A view of a `Predicate` parameter, provided by reflection. |
31 | /// |
32 | /// ```rust |
33 | /// use predicates_core; |
34 | /// |
35 | /// let param = predicates_core::reflection::Parameter::new("key" , &10); |
36 | /// println!("{}" , param); |
37 | /// ``` |
38 | pub struct Parameter<'a>(&'a str, &'a dyn fmt::Display); |
39 | |
40 | impl<'a> Parameter<'a> { |
41 | /// Create a new `Parameter`. |
42 | pub fn new(key: &'a str, value: &'a dyn fmt::Display) -> Self { |
43 | Self(key, value) |
44 | } |
45 | |
46 | /// Access the `Parameter` name. |
47 | pub fn name(&self) -> &str { |
48 | self.0 |
49 | } |
50 | |
51 | /// Access the `Parameter` value. |
52 | pub fn value(&self) -> &dyn fmt::Display { |
53 | self.1 |
54 | } |
55 | } |
56 | |
57 | impl<'a> fmt::Display for Parameter<'a> { |
58 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
59 | write!(f, "{}: {}" , self.0, self.1) |
60 | } |
61 | } |
62 | |
63 | impl<'a> fmt::Debug for Parameter<'a> { |
64 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
65 | write!(f, "({:?}, {})" , self.0, self.1) |
66 | } |
67 | } |
68 | |
69 | /// A view of a `Predicate` child, provided by reflection. |
70 | pub struct Child<'a>(&'a str, &'a dyn PredicateReflection); |
71 | |
72 | impl<'a> Child<'a> { |
73 | /// Create a new `Predicate` child. |
74 | pub fn new(key: &'a str, value: &'a dyn PredicateReflection) -> Self { |
75 | Self(key, value) |
76 | } |
77 | |
78 | /// Access the `Child`'s name. |
79 | pub fn name(&self) -> &str { |
80 | self.0 |
81 | } |
82 | |
83 | /// Access the `Child` `Predicate`. |
84 | pub fn value(&self) -> &dyn PredicateReflection { |
85 | self.1 |
86 | } |
87 | } |
88 | |
89 | impl<'a> fmt::Display for Child<'a> { |
90 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
91 | write!(f, "{}: {}" , self.0, self.1) |
92 | } |
93 | } |
94 | |
95 | impl<'a> fmt::Debug for Child<'a> { |
96 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
97 | write!(f, "({:?}, {})" , self.0, self.1) |
98 | } |
99 | } |
100 | |
101 | /// A descriptive explanation for why a predicate failed. |
102 | pub struct Case<'a> { |
103 | predicate: Option<&'a dyn PredicateReflection>, |
104 | result: bool, |
105 | products: Vec<Product>, |
106 | children: Vec<Case<'a>>, |
107 | } |
108 | |
109 | impl<'a> Case<'a> { |
110 | /// Create a new `Case` describing the result of a `Predicate`. |
111 | pub fn new(predicate: Option<&'a dyn PredicateReflection>, result: bool) -> Self { |
112 | Self { |
113 | predicate, |
114 | result, |
115 | products: Default::default(), |
116 | children: Default::default(), |
117 | } |
118 | } |
119 | |
120 | /// Add an additional by product to a `Case`. |
121 | pub fn add_product(mut self, product: Product) -> Self { |
122 | self.products.push(product); |
123 | self |
124 | } |
125 | |
126 | /// Add an additional by product to a `Case`. |
127 | pub fn add_child(mut self, child: Case<'a>) -> Self { |
128 | self.children.push(child); |
129 | self |
130 | } |
131 | |
132 | /// The `Predicate` that produced this case. |
133 | pub fn predicate(&self) -> Option<&dyn PredicateReflection> { |
134 | self.predicate |
135 | } |
136 | |
137 | /// The result of this case. |
138 | pub fn result(&self) -> bool { |
139 | self.result |
140 | } |
141 | |
142 | /// Access the by-products from determining this case. |
143 | pub fn products(&self) -> CaseProducts<'_> { |
144 | CaseProducts(self.products.iter()) |
145 | } |
146 | |
147 | /// Access the sub-cases. |
148 | pub fn children(&self) -> CaseChildren<'_> { |
149 | CaseChildren(self.children.iter()) |
150 | } |
151 | } |
152 | |
153 | impl<'a> fmt::Debug for Case<'a> { |
154 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
155 | let predicate = if let Some(ref predicate) = self.predicate { |
156 | format!("Some({})" , predicate) |
157 | } else { |
158 | "None" .to_owned() |
159 | }; |
160 | f.debug_struct("Case" ) |
161 | .field("predicate" , &predicate) |
162 | .field("result" , &self.result) |
163 | .field("products" , &self.products) |
164 | .field("children" , &self.children) |
165 | .finish() |
166 | } |
167 | } |
168 | |
169 | /// Iterator over a `Case`s by-products. |
170 | #[derive(Debug, Clone)] |
171 | pub struct CaseProducts<'a>(slice::Iter<'a, Product>); |
172 | |
173 | impl<'a> Iterator for CaseProducts<'a> { |
174 | type Item = &'a Product; |
175 | |
176 | fn next(&mut self) -> Option<&'a Product> { |
177 | self.0.next() |
178 | } |
179 | |
180 | fn size_hint(&self) -> (usize, Option<usize>) { |
181 | self.0.size_hint() |
182 | } |
183 | |
184 | fn count(self) -> usize { |
185 | self.0.count() |
186 | } |
187 | } |
188 | |
189 | /// Iterator over a `Case`s sub-cases. |
190 | #[derive(Debug, Clone)] |
191 | pub struct CaseChildren<'a>(slice::Iter<'a, Case<'a>>); |
192 | |
193 | impl<'a> Iterator for CaseChildren<'a> { |
194 | type Item = &'a Case<'a>; |
195 | |
196 | fn next(&mut self) -> Option<&'a Case<'a>> { |
197 | self.0.next() |
198 | } |
199 | |
200 | fn size_hint(&self) -> (usize, Option<usize>) { |
201 | self.0.size_hint() |
202 | } |
203 | |
204 | fn count(self) -> usize { |
205 | self.0.count() |
206 | } |
207 | } |
208 | |
209 | /// A by-product of a predicate evaluation. |
210 | /// |
211 | /// ```rust |
212 | /// use predicates_core; |
213 | /// |
214 | /// let product = predicates_core::reflection::Product::new("key" , "value" ); |
215 | /// println!("{}" , product); |
216 | /// let product = predicates_core::reflection::Product::new(format!("key-{}" , 5), 30); |
217 | /// println!("{}" , product); |
218 | /// ``` |
219 | pub struct Product(borrow::Cow<'static, str>, Box<dyn fmt::Display>); |
220 | |
221 | impl Product { |
222 | /// Create a new `Product`. |
223 | pub fn new<S, D>(key: S, value: D) -> Self |
224 | where |
225 | S: Into<borrow::Cow<'static, str>>, |
226 | D: fmt::Display + 'static, |
227 | { |
228 | Self(key.into(), Box::new(value)) |
229 | } |
230 | |
231 | /// Access the `Product` name. |
232 | pub fn name(&self) -> &str { |
233 | self.0.as_ref() |
234 | } |
235 | |
236 | /// Access the `Product` value. |
237 | pub fn value(&self) -> &dyn fmt::Display { |
238 | &self.1 |
239 | } |
240 | } |
241 | |
242 | impl fmt::Display for Product { |
243 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
244 | write!(f, "{}: {}" , self.0, self.1) |
245 | } |
246 | } |
247 | |
248 | impl fmt::Debug for Product { |
249 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
250 | write!(f, "({:?}, {})" , self.0, self.1) |
251 | } |
252 | } |
253 | |