diff --git a/src/boolean.rs b/src/boolean.rs index 6b35ca8..9ab6a1e 100644 --- a/src/boolean.rs +++ b/src/boolean.rs @@ -11,6 +11,7 @@ use std::fmt; use std::marker::PhantomData; +use reflection; use Predicate; /// Predicate that combines two `Predicate`s, returning the AND of the results. @@ -55,6 +56,21 @@ where } } +impl reflection::PredicateReflection for AndPredicate +where + M1: Predicate, + M2: Predicate, + Item: ?Sized, +{ + fn children<'a>(&'a self) -> Box> + 'a> { + let params = vec![ + reflection::Child::new("left", &self.a), + reflection::Child::new("right", &self.b), + ]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for AndPredicate where M1: Predicate, @@ -108,6 +124,21 @@ where } } +impl reflection::PredicateReflection for OrPredicate +where + M1: Predicate, + M2: Predicate, + Item: ?Sized, +{ + fn children<'a>(&'a self) -> Box> + 'a> { + let params = vec![ + reflection::Child::new("left", &self.a), + reflection::Child::new("right", &self.b), + ]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for OrPredicate where M1: Predicate, @@ -156,6 +187,17 @@ where } } +impl reflection::PredicateReflection for NotPredicate +where + M: Predicate, + Item: ?Sized, +{ + fn children<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Child::new("predicate", &self.inner)]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for NotPredicate where M: Predicate, diff --git a/src/boxed.rs b/src/boxed.rs index 5113b54..de57174 100644 --- a/src/boxed.rs +++ b/src/boxed.rs @@ -11,6 +11,7 @@ use std::fmt; +use reflection; use Predicate; /// `Predicate` that wraps another `Predicate` as a trait object, allowing @@ -40,6 +41,19 @@ where } } +impl reflection::PredicateReflection for BoxPredicate +where + Item: ?Sized, +{ + fn parameters<'a>(&'a self) -> Box> + 'a> { + self.0.parameters() + } + + fn children<'a>(&'a self) -> Box> + 'a> { + self.0.children() + } +} + impl fmt::Display for BoxPredicate where Item: ?Sized, diff --git a/src/constant.rs b/src/constant.rs index f902f8f..29b64ec 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -11,6 +11,7 @@ use std::fmt; use std::marker::PhantomData; +use reflection; use Predicate; /// Predicate that always returns a constant (boolean) result. @@ -28,6 +29,13 @@ impl Predicate for BooleanPredicate { } } +impl reflection::PredicateReflection for BooleanPredicate { + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("value", &self.retval)]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for BooleanPredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.retval) diff --git a/src/core.rs b/src/core.rs index dd48e0b..3f60d18 100644 --- a/src/core.rs +++ b/src/core.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt; +use reflection; /// Trait for generically evaluating a type against a dynamically created /// predicate function. @@ -15,7 +15,7 @@ use std::fmt; /// mean that the evaluated item is in some sort of pre-defined set. This is /// different from `Ord` and `Eq` in that an `item` will almost never be the /// same type as the implementing `Predicate` type. -pub trait Predicate: fmt::Display { +pub trait Predicate: reflection::PredicateReflection { /// Execute this `Predicate` against `variable`, returning the resulting /// boolean. fn eval(&self, variable: &Item) -> bool; diff --git a/src/float/close.rs b/src/float/close.rs index da6e7f3..43ff284 100644 --- a/src/float/close.rs +++ b/src/float/close.rs @@ -11,6 +11,7 @@ use std::fmt; use float_cmp::ApproxEq; use float_cmp::Ulps; +use reflection; use Predicate; /// Predicate that ensures two numbers are "close" enough, understanding that rounding errors @@ -86,13 +87,19 @@ impl Predicate for IsClosePredicate { } } +impl reflection::PredicateReflection for IsClosePredicate { + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![ + reflection::Parameter::new("epsilon", &self.epsilon), + reflection::Parameter::new("ulps", &self.ulps), + ]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for IsClosePredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "var ~= {} +/- {} ({})", - self.target, self.epsilon, self.ulps - ) + write!(f, "var ~= {}", self.target) } } diff --git a/src/function.rs b/src/function.rs index c9f80f4..d0ab922 100644 --- a/src/function.rs +++ b/src/function.rs @@ -11,6 +11,7 @@ use std::fmt; use std::marker::PhantomData; +use reflection; use Predicate; /// Predicate that wraps a function over a reference that returns a `bool`. @@ -60,6 +61,12 @@ where } } +impl reflection::PredicateReflection for FnPredicate +where + F: Fn(&T) -> bool, +{ +} + impl fmt::Display for FnPredicate where F: Fn(&T) -> bool, diff --git a/src/iter.rs b/src/iter.rs index 7df8007..9284244 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -13,6 +13,7 @@ use std::fmt; use std::hash::Hash; use std::iter::FromIterator; +use reflection; use Predicate; /// Predicate that returns `true` if `variable` is a member of the pre-defined @@ -29,7 +30,7 @@ pub struct InPredicate where T: PartialEq + fmt::Debug, { - inner: Vec, + inner: reflection::DebugAdapter>, } impl InPredicate @@ -60,9 +61,11 @@ where /// assert_eq!(true, predicate_fn.eval("c")); /// ``` pub fn sort(self) -> OrdInPredicate { - let mut items = self.inner; + let mut items = self.inner.debug; items.sort(); - OrdInPredicate { inner: items } + OrdInPredicate { + inner: reflection::DebugAdapter::new(items), + } } } @@ -71,7 +74,7 @@ where T: PartialEq + fmt::Debug, { fn eval(&self, variable: &T) -> bool { - self.inner.contains(variable) + self.inner.debug.contains(variable) } } @@ -80,7 +83,17 @@ where T: PartialEq + fmt::Debug + ?Sized, { fn eval(&self, variable: &T) -> bool { - self.inner.contains(&variable) + self.inner.debug.contains(&variable) + } +} + +impl reflection::PredicateReflection for InPredicate +where + T: PartialEq + fmt::Debug, +{ + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("values", &self.inner)]; + Box::new(params.into_iter()) } } @@ -89,7 +102,7 @@ where T: PartialEq + fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "var in {:?}", self.inner) + write!(f, "var in values") } } @@ -128,7 +141,7 @@ where I: IntoIterator, { InPredicate { - inner: Vec::from_iter(iter), + inner: reflection::DebugAdapter::new(Vec::from_iter(iter)), } } @@ -146,7 +159,7 @@ pub struct OrdInPredicate where T: Ord + fmt::Debug, { - inner: Vec, + inner: reflection::DebugAdapter>, } impl Predicate for OrdInPredicate @@ -154,7 +167,7 @@ where T: Ord + fmt::Debug, { fn eval(&self, variable: &T) -> bool { - self.inner.binary_search(variable).is_ok() + self.inner.debug.binary_search(variable).is_ok() } } @@ -163,7 +176,17 @@ where T: Ord + fmt::Debug + ?Sized, { fn eval(&self, variable: &T) -> bool { - self.inner.binary_search(&variable).is_ok() + self.inner.debug.binary_search(&variable).is_ok() + } +} + +impl reflection::PredicateReflection for OrdInPredicate +where + T: Ord + fmt::Debug, +{ + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("values", &self.inner)]; + Box::new(params.into_iter()) } } @@ -172,7 +195,7 @@ where T: Ord + fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "var in {:?}", self.inner) + write!(f, "var in values") } } @@ -190,7 +213,7 @@ pub struct HashableInPredicate where T: Hash + Eq + fmt::Debug, { - inner: HashSet, + inner: reflection::DebugAdapter>, } impl Predicate for HashableInPredicate @@ -198,7 +221,7 @@ where T: Hash + Eq + fmt::Debug, { fn eval(&self, variable: &T) -> bool { - self.inner.contains(variable) + self.inner.debug.contains(variable) } } @@ -207,7 +230,17 @@ where T: Hash + Eq + fmt::Debug + ?Sized, { fn eval(&self, variable: &T) -> bool { - self.inner.contains(&variable) + self.inner.debug.contains(&variable) + } +} + +impl reflection::PredicateReflection for HashableInPredicate +where + T: Hash + Eq + fmt::Debug, +{ + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("values", &self.inner)]; + Box::new(params.into_iter()) } } @@ -216,7 +249,7 @@ where T: Hash + Eq + fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "var in {:?}", self.inner) + write!(f, "var in values") } } @@ -249,6 +282,6 @@ where I: IntoIterator, { HashableInPredicate { - inner: HashSet::from_iter(iter), + inner: reflection::DebugAdapter::new(HashSet::from_iter(iter)), } } diff --git a/src/lib.rs b/src/lib.rs index d0a55b7..130f782 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,6 +69,7 @@ //! *variable == 42 //! } //! } +//! impl predicates::reflection::PredicateReflection for IsTheAnswer {} //! impl fmt::Display for IsTheAnswer { //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //! write!(f, "var.is_the_answer()") @@ -101,9 +102,10 @@ extern crate regex; pub mod prelude; mod core; -pub use core::Predicate; +pub use core::*; mod boxed; -pub use boxed::BoxPredicate; +pub use boxed::*; +pub mod reflection; // core predicates pub mod constant; diff --git a/src/name.rs b/src/name.rs index 2d1159c..92f53b8 100644 --- a/src/name.rs +++ b/src/name.rs @@ -11,6 +11,7 @@ use std::fmt; use std::marker::PhantomData; +use reflection; use Predicate; /// Augment an existing predicate with a name. @@ -37,6 +38,17 @@ where } } +impl reflection::PredicateReflection for NamePredicate +where + M: Predicate, + Item: ?Sized, +{ + fn children<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Child::new(self.name, &self.inner)]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for NamePredicate where M: Predicate, diff --git a/src/ord.rs b/src/ord.rs index 1ee560e..2dc809d 100644 --- a/src/ord.rs +++ b/src/ord.rs @@ -10,6 +10,7 @@ use std::fmt; +use reflection; use Predicate; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -65,6 +66,12 @@ where } } +impl reflection::PredicateReflection for EqPredicate +where + T: fmt::Debug + PartialEq, +{ +} + impl fmt::Display for EqPredicate where T: fmt::Debug + PartialEq, @@ -183,6 +190,12 @@ where } } +impl reflection::PredicateReflection for OrdPredicate +where + T: fmt::Debug + PartialOrd, +{ +} + impl fmt::Display for OrdPredicate where T: fmt::Debug + PartialOrd, diff --git a/src/path/existence.rs b/src/path/existence.rs index e99c351..073d56b 100644 --- a/src/path/existence.rs +++ b/src/path/existence.rs @@ -9,6 +9,7 @@ use std::fmt; use std::path; +use reflection; use Predicate; /// Predicate that checks if a file is present @@ -25,6 +26,8 @@ impl Predicate for ExistencePredicate { } } +impl reflection::PredicateReflection for ExistencePredicate {} + impl fmt::Display for ExistencePredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}(var)", if self.exists { "exists" } else { "missing" }) diff --git a/src/path/fc.rs b/src/path/fc.rs index 7234bcd..65acef8 100644 --- a/src/path/fc.rs +++ b/src/path/fc.rs @@ -11,6 +11,7 @@ use std::fs; use std::io::{self, Read}; use std::path; +use reflection; use Predicate; fn read_file(path: &path::Path) -> io::Result> { @@ -40,6 +41,16 @@ where } } +impl

reflection::PredicateReflection for FileContentPredicate

+where + P: Predicate<[u8]>, +{ + fn children<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Child::new("predicate", &self.p)]; + Box::new(params.into_iter()) + } +} + impl

fmt::Display for FileContentPredicate

where P: Predicate<[u8]>, diff --git a/src/path/fs.rs b/src/path/fs.rs index 8ae2160..0c01ab2 100644 --- a/src/path/fs.rs +++ b/src/path/fs.rs @@ -11,6 +11,7 @@ use std::fs; use std::io::{self, Read}; use std::path; +use reflection; use Predicate; fn read_file(path: &path::Path) -> io::Result> { @@ -23,13 +24,13 @@ fn read_file(path: &path::Path) -> io::Result> { #[derive(Debug, Clone, PartialEq, Eq)] pub struct BinaryFilePredicate { path: path::PathBuf, - content: Vec, + content: reflection::DebugAdapter>, } impl BinaryFilePredicate { fn eval(&self, path: &path::Path) -> io::Result { let content = read_file(path)?; - Ok(self.content == content) + Ok(self.content.debug == content) } /// Creates a new `Predicate` that ensures complete equality @@ -49,7 +50,7 @@ impl BinaryFilePredicate { /// ``` pub fn utf8(self) -> Option { let path = self.path; - let content = String::from_utf8(self.content).ok()?; + let content = String::from_utf8(self.content.debug).ok()?; Some(StrFilePredicate { path, content }) } } @@ -62,7 +63,14 @@ impl Predicate for BinaryFilePredicate { impl Predicate<[u8]> for BinaryFilePredicate { fn eval(&self, actual: &[u8]) -> bool { - self.content == actual + self.content.debug == actual + } +} + +impl reflection::PredicateReflection for BinaryFilePredicate { + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("content", &self.content)]; + Box::new(params.into_iter()) } } @@ -86,7 +94,7 @@ impl fmt::Display for BinaryFilePredicate { /// assert_eq!(false, predicate_file.eval(Path::new("Cargo.lock"))); /// ``` pub fn eq_file(path: &path::Path) -> BinaryFilePredicate { - let content = read_file(path).unwrap(); + let content = reflection::DebugAdapter::new(read_file(path).unwrap()); BinaryFilePredicate { path: path.to_path_buf(), content, @@ -120,6 +128,13 @@ impl Predicate for StrFilePredicate { } } +impl reflection::PredicateReflection for StrFilePredicate { + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("content", &self.content)]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for StrFilePredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "var is {}", self.path.display()) diff --git a/src/path/ft.rs b/src/path/ft.rs index 1f2dd33..7d829a6 100644 --- a/src/path/ft.rs +++ b/src/path/ft.rs @@ -11,6 +11,7 @@ use std::fs; use std::io; use std::path; +use reflection; use Predicate; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -94,6 +95,13 @@ impl Predicate for FileTypePredicate { } } +impl reflection::PredicateReflection for FileTypePredicate { + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("follow", &self.follow)]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for FileTypePredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "var is {}", self.ft) diff --git a/src/reflection.rs b/src/reflection.rs new file mode 100644 index 0000000..395b970 --- /dev/null +++ b/src/reflection.rs @@ -0,0 +1,132 @@ +// Copyright (c) 2018 The predicates-rs Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Introspect into the state of a `Predicate`. + +use std::fmt; + +/// Introspect the state of a `Predicate`. +pub trait PredicateReflection: fmt::Display { + /// Parameters of the current `Predicate`. + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![]; + Box::new(params.into_iter()) + } + + /// Nested `Predicate`s of the current `Predicate`. + fn children<'a>(&'a self) -> Box> + 'a> { + let params = vec![]; + Box::new(params.into_iter()) + } +} + +/// A view of a `Predicate` parameter, provided by reflection. +/// +/// ```rust +/// use predicates; +/// +/// let param = predicates::reflection::Parameter::new("key", &10); +/// println!("{}", param); +/// ``` +pub struct Parameter<'a>(&'a str, &'a fmt::Display); + +impl<'a> Parameter<'a> { + /// Create a new `Parameter`. + pub fn new(key: &'a str, value: &'a fmt::Display) -> Self { + Self { 0: key, 1: value } + } + + /// Access the `Parameter` name. + pub fn name(&self) -> &str { + self.0 + } + + /// Access the `Parameter` value. + pub fn value(&self) -> &fmt::Display { + self.1 + } +} + +impl<'a> fmt::Display for Parameter<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}: {}", self.0, self.1) + } +} + +impl<'a> fmt::Debug for Parameter<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({:?}, {})", self.0, self.1) + } +} + +/// A view of a `Predicate` child, provided by reflection. +pub struct Child<'a>(&'a str, &'a PredicateReflection); + +impl<'a> Child<'a> { + /// Create a new `Predicate` child. + pub fn new(key: &'a str, value: &'a PredicateReflection) -> Self { + Self { 0: key, 1: value } + } + + /// Access the `Child`'s name. + pub fn name(&self) -> &str { + self.0 + } + + /// Access the `Child` `Predicate`. + pub fn value(&self) -> &PredicateReflection { + self.1 + } +} + +impl<'a> fmt::Display for Child<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}: {}", self.0, self.1) + } +} + +impl<'a> fmt::Debug for Child<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({:?}, {})", self.0, self.1) + } +} + +#[derive(Clone, PartialEq, Eq)] +pub(crate) struct DebugAdapter +where + T: fmt::Debug, +{ + pub(crate) debug: T, +} + +impl DebugAdapter +where + T: fmt::Debug, +{ + pub fn new(debug: T) -> Self { + Self { debug } + } +} + +impl fmt::Display for DebugAdapter +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#?}", self.debug) + } +} + +impl fmt::Debug for DebugAdapter +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.debug.fmt(f) + } +} diff --git a/src/str/adapters.rs b/src/str/adapters.rs index d57af32..7c188bb 100644 --- a/src/str/adapters.rs +++ b/src/str/adapters.rs @@ -2,6 +2,7 @@ use std::ffi; use std::fmt; use std::str; +use reflection; use Predicate; /// Predicate adaper that trims the variable being tested. @@ -24,6 +25,16 @@ where } } +impl

reflection::PredicateReflection for TrimPredicate

+where + P: Predicate, +{ + fn children<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Child::new("predicate", &self.p)]; + Box::new(params.into_iter()) + } +} + impl

fmt::Display for TrimPredicate

where P: Predicate, @@ -64,6 +75,16 @@ where } } +impl

reflection::PredicateReflection for Utf8Predicate

+where + P: Predicate, +{ + fn children<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Child::new("predicate", &self.p)]; + Box::new(params.into_iter()) + } +} + impl

fmt::Display for Utf8Predicate

where P: Predicate, diff --git a/src/str/basics.rs b/src/str/basics.rs index 5a31647..493bd8d 100644 --- a/src/str/basics.rs +++ b/src/str/basics.rs @@ -8,6 +8,7 @@ use std::fmt; +use reflection; use Predicate; /// Predicate that checks for empty strings. @@ -22,6 +23,8 @@ impl Predicate for IsEmptyPredicate { } } +impl reflection::PredicateReflection for IsEmptyPredicate {} + impl fmt::Display for IsEmptyPredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "var.is_empty()") @@ -57,6 +60,8 @@ impl Predicate for StartsWithPredicate { } } +impl reflection::PredicateReflection for StartsWithPredicate {} + impl fmt::Display for StartsWithPredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "var.starts_with({:?})", self.pattern) @@ -97,6 +102,8 @@ impl Predicate for EndsWithPredicate { } } +impl reflection::PredicateReflection for EndsWithPredicate {} + impl fmt::Display for EndsWithPredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "var.ends_with({:?})", self.pattern) @@ -157,6 +164,8 @@ impl Predicate for ContainsPredicate { } } +impl reflection::PredicateReflection for ContainsPredicate {} + impl fmt::Display for ContainsPredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "var.contains({:?})", self.pattern) @@ -178,9 +187,16 @@ impl Predicate for MatchesPredicate { } } +impl reflection::PredicateReflection for MatchesPredicate { + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("count", &self.count)]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for MatchesPredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "var.contains({:?}, {})", self.pattern, self.count) + write!(f, "var.contains({})", self.pattern) } } diff --git a/src/str/difference.rs b/src/str/difference.rs index 24047f0..e0ff91b 100644 --- a/src/str/difference.rs +++ b/src/str/difference.rs @@ -11,6 +11,7 @@ use std::fmt; use difference; +use reflection; use Predicate; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -92,11 +93,18 @@ impl Predicate for DifferencePredicate { } } +impl reflection::PredicateReflection for DifferencePredicate { + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("original", &self.orig)]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for DifferencePredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.op { - DistanceOp::Similar => write!(f, "var - {:?} <= {}", self.orig, self.distance), - DistanceOp::Different => write!(f, "{} < var - {:?}", self.distance, self.orig), + DistanceOp::Similar => write!(f, "var - original <= {}", self.distance), + DistanceOp::Different => write!(f, "{} < var - original", self.distance), } } } diff --git a/src/str/regex.rs b/src/str/regex.rs index f5c1a8e..3462337 100644 --- a/src/str/regex.rs +++ b/src/str/regex.rs @@ -10,6 +10,7 @@ use std::fmt; use regex; +use reflection; use Predicate; /// An error that occurred during parsing or compiling a regular expression. @@ -46,6 +47,8 @@ impl Predicate for RegexPredicate { } } +impl reflection::PredicateReflection for RegexPredicate {} + impl fmt::Display for RegexPredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "var.is_match({})", self.re) @@ -67,9 +70,16 @@ impl Predicate for RegexMatchesPredicate { } } +impl reflection::PredicateReflection for RegexMatchesPredicate { + fn parameters<'a>(&'a self) -> Box> + 'a> { + let params = vec![reflection::Parameter::new("count", &self.count)]; + Box::new(params.into_iter()) + } +} + impl fmt::Display for RegexMatchesPredicate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "var.is_match({}).count({})", self.re, self.count) + write!(f, "var.is_match({})", self.re) } }