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
11use std::borrow;
12use std::fmt;
13use std::slice;
14
15/// Introspect the state of a `Predicate`.
16pub 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/// ```
38pub struct Parameter<'a>(&'a str, &'a dyn fmt::Display);
39
40impl<'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
57impl<'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
63impl<'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.
70pub struct Child<'a>(&'a str, &'a dyn PredicateReflection);
71
72impl<'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
89impl<'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
95impl<'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.
102pub struct Case<'a> {
103 predicate: Option<&'a dyn PredicateReflection>,
104 result: bool,
105 products: Vec<Product>,
106 children: Vec<Case<'a>>,
107}
108
109impl<'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
153impl<'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)]
171pub struct CaseProducts<'a>(slice::Iter<'a, Product>);
172
173impl<'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)]
191pub struct CaseChildren<'a>(slice::Iter<'a, Case<'a>>);
192
193impl<'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/// ```
219pub struct Product(borrow::Cow<'static, str>, Box<dyn fmt::Display>);
220
221impl 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
242impl fmt::Display for Product {
243 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244 write!(f, "{}: {}", self.0, self.1)
245 }
246}
247
248impl fmt::Debug for Product {
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 write!(f, "({:?}, {})", self.0, self.1)
251 }
252}
253