|
8 | 8 |
|
9 | 9 | //! Introspect into the state of a `Predicate`.
|
10 | 10 |
|
| 11 | +use std::borrow; |
11 | 12 | use std::fmt;
|
| 13 | +use std::slice; |
12 | 14 |
|
13 | 15 | /// Introspect the state of a `Predicate`.
|
14 | 16 | pub trait PredicateReflection: fmt::Display {
|
@@ -96,6 +98,166 @@ impl<'a> fmt::Debug for Child<'a> {
|
96 | 98 | }
|
97 | 99 | }
|
98 | 100 |
|
| 101 | +/// A descriptive explanation for why a predicate failed. |
| 102 | +pub struct Case<'a> { |
| 103 | + predicate: Option<&'a 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 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<&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 | + |
| 157 | +impl<'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)] |
| 175 | +pub struct CaseProducts<'a>(slice::Iter<'a, Product>); |
| 176 | + |
| 177 | +impl<'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)] |
| 195 | +pub struct CaseChildren<'a>(slice::Iter<'a, Case<'a>>); |
| 196 | + |
| 197 | +impl<'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; |
| 217 | +/// |
| 218 | +/// let product = predicates::reflection::Product::new("key", "value"); |
| 219 | +/// println!("{}", product); |
| 220 | +/// let product = predicates::reflection::Product::new(format!("key-{}", 5), 30); |
| 221 | +/// println!("{}", product); |
| 222 | +/// ``` |
| 223 | +pub struct Product(borrow::Cow<'static, str>, Box<fmt::Display>); |
| 224 | + |
| 225 | +impl 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) -> &fmt::Display { |
| 245 | + &self.1 |
| 246 | + } |
| 247 | +} |
| 248 | + |
| 249 | +impl<'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 | + |
| 255 | +impl<'a> fmt::Debug for Product { |
| 256 | + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 257 | + write!(f, "({:?}, {})", self.0, self.1) |
| 258 | + } |
| 259 | +} |
| 260 | + |
99 | 261 | #[derive(Clone, PartialEq, Eq)]
|
100 | 262 | pub(crate) struct DebugAdapter<T>
|
101 | 263 | where
|
|
0 commit comments