predicates_core/
reflection.rs

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 { 0: key, 1: 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 { 0: key, 1: 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 {
145            0: self.products.iter(),
146        }
147    }
148
149    /// Access the sub-cases.
150    pub fn children(&self) -> CaseChildren<'_> {
151        CaseChildren {
152            0: self.children.iter(),
153        }
154    }
155}
156
157impl<'a> fmt::Debug for Case<'a> {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        let predicate = if let Some(ref predicate) = self.predicate {
160            format!("Some({})", predicate)
161        } else {
162            "None".to_owned()
163        };
164        f.debug_struct("Case")
165            .field("predicate", &predicate)
166            .field("result", &self.result)
167            .field("products", &self.products)
168            .field("children", &self.children)
169            .finish()
170    }
171}
172
173/// Iterator over a `Case`s by-products.
174#[derive(Debug, Clone)]
175pub struct CaseProducts<'a>(slice::Iter<'a, Product>);
176
177impl<'a> Iterator for CaseProducts<'a> {
178    type Item = &'a Product;
179
180    fn next(&mut self) -> Option<&'a Product> {
181        self.0.next()
182    }
183
184    fn size_hint(&self) -> (usize, Option<usize>) {
185        self.0.size_hint()
186    }
187
188    fn count(self) -> usize {
189        self.0.count()
190    }
191}
192
193/// Iterator over a `Case`s sub-cases.
194#[derive(Debug, Clone)]
195pub struct CaseChildren<'a>(slice::Iter<'a, Case<'a>>);
196
197impl<'a> Iterator for CaseChildren<'a> {
198    type Item = &'a Case<'a>;
199
200    fn next(&mut self) -> Option<&'a Case<'a>> {
201        self.0.next()
202    }
203
204    fn size_hint(&self) -> (usize, Option<usize>) {
205        self.0.size_hint()
206    }
207
208    fn count(self) -> usize {
209        self.0.count()
210    }
211}
212
213/// A by-product of a predicate evaluation.
214///
215/// ```rust
216/// use predicates_core;
217///
218/// let product = predicates_core::reflection::Product::new("key", "value");
219/// println!("{}", product);
220/// let product = predicates_core::reflection::Product::new(format!("key-{}", 5), 30);
221/// println!("{}", product);
222/// ```
223pub struct Product(borrow::Cow<'static, str>, Box<dyn fmt::Display>);
224
225impl Product {
226    /// Create a new `Product`.
227    pub fn new<S, D>(key: S, value: D) -> Self
228    where
229        S: Into<borrow::Cow<'static, str>>,
230        D: fmt::Display + 'static,
231    {
232        Self {
233            0: key.into(),
234            1: Box::new(value),
235        }
236    }
237
238    /// Access the `Product` name.
239    pub fn name(&self) -> &str {
240        self.0.as_ref()
241    }
242
243    /// Access the `Product` value.
244    pub fn value(&self) -> &dyn fmt::Display {
245        &self.1
246    }
247}
248
249impl<'a> fmt::Display for Product {
250    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251        write!(f, "{}: {}", self.0, self.1)
252    }
253}
254
255impl<'a> fmt::Debug for Product {
256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257        write!(f, "({:?}, {})", self.0, self.1)
258    }
259}