Skip to content

Commit

Permalink
feat: Implement reflection for predicates
Browse files Browse the repository at this point in the history
This also saw an audit of predicates to ensure their `Display` would
most likely remain as one line of text.  Anything in a `Display` that
seemed likely to overflow was moved to a `Parameter`.
  • Loading branch information
epage committed Jul 20, 2018
1 parent fc099fb commit 8759f14
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 38 deletions.
18 changes: 18 additions & 0 deletions src/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ where
M2: Predicate<Item>,
Item: ?Sized,
{
fn children<'a>(&'a self) -> Box<Iterator<Item = reflection::Child<'a>> + 'a> {
let params = vec![
reflection::Child::new("left", &self.a),
reflection::Child::new("right", &self.b),
];
Box::new(params.into_iter())
}
}

impl<M1, M2, Item> fmt::Display for AndPredicate<M1, M2, Item>
Expand Down Expand Up @@ -123,6 +130,13 @@ where
M2: Predicate<Item>,
Item: ?Sized,
{
fn children<'a>(&'a self) -> Box<Iterator<Item = reflection::Child<'a>> + 'a> {
let params = vec![
reflection::Child::new("left", &self.a),
reflection::Child::new("right", &self.b),
];
Box::new(params.into_iter())
}
}

impl<M1, M2, Item> fmt::Display for OrPredicate<M1, M2, Item>
Expand Down Expand Up @@ -178,6 +192,10 @@ where
M: Predicate<Item>,
Item: ?Sized,
{
fn children<'a>(&'a self) -> Box<Iterator<Item = reflection::Child<'a>> + 'a> {
let params = vec![reflection::Child::new("predicate", &self.inner)];
Box::new(params.into_iter())
}
}

impl<M, Item> fmt::Display for NotPredicate<M, Item>
Expand Down
7 changes: 7 additions & 0 deletions src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ impl<Item> reflection::PredicateReflection for BoxPredicate<Item>
where
Item: ?Sized,
{
fn parameters<'a>(&'a self) -> Box<Iterator<Item = reflection::Parameter<'a>> + 'a> {
self.0.parameters()
}

fn children<'a>(&'a self) -> Box<Iterator<Item = reflection::Child<'a>> + 'a> {
self.0.children()
}
}

impl<Item> fmt::Display for BoxPredicate<Item>
Expand Down
7 changes: 6 additions & 1 deletion src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ impl<Item> Predicate<Item> for BooleanPredicate<Item> {
}
}

impl<Item> reflection::PredicateReflection for BooleanPredicate<Item> {}
impl<Item> reflection::PredicateReflection for BooleanPredicate<Item> {
fn parameters<'a>(&'a self) -> Box<Iterator<Item = reflection::Parameter<'a>> + 'a> {
let params = vec![reflection::Parameter::new("value", &self.retval)];
Box::new(params.into_iter())
}
}

impl<Item> fmt::Display for BooleanPredicate<Item> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down
16 changes: 10 additions & 6 deletions src/float/close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,19 @@ impl Predicate<f64> for IsClosePredicate {
}
}

impl reflection::PredicateReflection for IsClosePredicate {}
impl reflection::PredicateReflection for IsClosePredicate {
fn parameters<'a>(&'a self) -> Box<Iterator<Item = reflection::Parameter<'a>> + '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)
}
}

Expand Down
46 changes: 30 additions & 16 deletions src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub struct InPredicate<T>
where
T: PartialEq + fmt::Debug,
{
inner: Vec<T>,
inner: reflection::DebugAdapter<Vec<T>>,
}

impl<T> InPredicate<T>
Expand Down Expand Up @@ -61,9 +61,11 @@ where
/// assert_eq!(true, predicate_fn.eval("c"));
/// ```
pub fn sort(self) -> OrdInPredicate<T> {
let mut items = self.inner;
let mut items = self.inner.debug;
items.sort();
OrdInPredicate { inner: items }
OrdInPredicate {
inner: reflection::DebugAdapter::new(items),
}
}
}

Expand All @@ -72,7 +74,7 @@ where
T: PartialEq + fmt::Debug,
{
fn eval(&self, variable: &T) -> bool {
self.inner.contains(variable)
self.inner.debug.contains(variable)
}
}

Expand All @@ -81,22 +83,26 @@ where
T: PartialEq + fmt::Debug + ?Sized,
{
fn eval(&self, variable: &T) -> bool {
self.inner.contains(&variable)
self.inner.debug.contains(&variable)
}
}

impl<T> reflection::PredicateReflection for InPredicate<T>
where
T: PartialEq + fmt::Debug,
{
fn parameters<'a>(&'a self) -> Box<Iterator<Item = reflection::Parameter<'a>> + 'a> {
let params = vec![reflection::Parameter::new("values", &self.inner)];
Box::new(params.into_iter())
}
}

impl<T> fmt::Display for InPredicate<T>
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")
}
}

Expand Down Expand Up @@ -135,7 +141,7 @@ where
I: IntoIterator<Item = T>,
{
InPredicate {
inner: Vec::from_iter(iter),
inner: reflection::DebugAdapter::new(Vec::from_iter(iter)),
}
}

Expand All @@ -153,15 +159,15 @@ pub struct OrdInPredicate<T>
where
T: Ord + fmt::Debug,
{
inner: Vec<T>,
inner: reflection::DebugAdapter<Vec<T>>,
}

impl<T> Predicate<T> for OrdInPredicate<T>
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()
}
}

Expand All @@ -170,22 +176,26 @@ 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<T> reflection::PredicateReflection for OrdInPredicate<T>
where
T: Ord + fmt::Debug,
{
fn parameters<'a>(&'a self) -> Box<Iterator<Item = reflection::Parameter<'a>> + 'a> {
let params = vec![reflection::Parameter::new("values", &self.inner)];
Box::new(params.into_iter())
}
}

impl<T> fmt::Display for OrdInPredicate<T>
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")
}
}

Expand All @@ -203,15 +213,15 @@ pub struct HashableInPredicate<T>
where
T: Hash + Eq + fmt::Debug,
{
inner: HashSet<T>,
inner: reflection::DebugAdapter<HashSet<T>>,
}

impl<T> Predicate<T> for HashableInPredicate<T>
where
T: Hash + Eq + fmt::Debug,
{
fn eval(&self, variable: &T) -> bool {
self.inner.contains(variable)
self.inner.debug.contains(variable)
}
}

Expand All @@ -220,22 +230,26 @@ where
T: Hash + Eq + fmt::Debug + ?Sized,
{
fn eval(&self, variable: &T) -> bool {
self.inner.contains(&variable)
self.inner.debug.contains(&variable)
}
}

impl<T> reflection::PredicateReflection for HashableInPredicate<T>
where
T: Hash + Eq + fmt::Debug,
{
fn parameters<'a>(&'a self) -> Box<Iterator<Item = reflection::Parameter<'a>> + 'a> {
let params = vec![reflection::Parameter::new("values", &self.inner)];
Box::new(params.into_iter())
}
}

impl<T> fmt::Display for HashableInPredicate<T>
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")
}
}

Expand Down Expand Up @@ -268,6 +282,6 @@ where
I: IntoIterator<Item = T>,
{
HashableInPredicate {
inner: HashSet::from_iter(iter),
inner: reflection::DebugAdapter::new(HashSet::from_iter(iter)),
}
}
4 changes: 4 additions & 0 deletions src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ where
M: Predicate<Item>,
Item: ?Sized,
{
fn children<'a>(&'a self) -> Box<Iterator<Item = reflection::Child<'a>> + 'a> {
let params = vec![reflection::Child::new(self.name, &self.inner)];
Box::new(params.into_iter())
}
}

impl<M, Item> fmt::Display for NamePredicate<M, Item>
Expand Down
4 changes: 4 additions & 0 deletions src/path/fc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ impl<P> reflection::PredicateReflection for FileContentPredicate<P>
where
P: Predicate<[u8]>,
{
fn children<'a>(&'a self) -> Box<Iterator<Item = reflection::Child<'a>> + 'a> {
let params = vec![reflection::Child::new("predicate", &self.p)];
Box::new(params.into_iter())
}
}

impl<P> fmt::Display for FileContentPredicate<P>
Expand Down
24 changes: 17 additions & 7 deletions src/path/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ fn read_file(path: &path::Path) -> io::Result<Vec<u8>> {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BinaryFilePredicate {
path: path::PathBuf,
content: Vec<u8>,
content: reflection::DebugAdapter<Vec<u8>>,
}

impl BinaryFilePredicate {
fn eval(&self, path: &path::Path) -> io::Result<bool> {
let content = read_file(path)?;
Ok(self.content == content)
Ok(self.content.debug == content)
}

/// Creates a new `Predicate` that ensures complete equality
Expand All @@ -50,7 +50,7 @@ impl BinaryFilePredicate {
/// ```
pub fn utf8(self) -> Option<StrFilePredicate> {
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 })
}
}
Expand All @@ -63,11 +63,16 @@ impl Predicate<path::Path> 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 {}
impl reflection::PredicateReflection for BinaryFilePredicate {
fn parameters<'a>(&'a self) -> Box<Iterator<Item = reflection::Parameter<'a>> + 'a> {
let params = vec![reflection::Parameter::new("content", &self.content)];
Box::new(params.into_iter())
}
}

impl fmt::Display for BinaryFilePredicate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand All @@ -89,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,
Expand Down Expand Up @@ -123,7 +128,12 @@ impl Predicate<str> for StrFilePredicate {
}
}

impl reflection::PredicateReflection for StrFilePredicate {}
impl reflection::PredicateReflection for StrFilePredicate {
fn parameters<'a>(&'a self) -> Box<Iterator<Item = reflection::Parameter<'a>> + '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 {
Expand Down
7 changes: 6 additions & 1 deletion src/path/ft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ impl Predicate<path::Path> for FileTypePredicate {
}
}

impl reflection::PredicateReflection for FileTypePredicate {}
impl reflection::PredicateReflection for FileTypePredicate {
fn parameters<'a>(&'a self) -> Box<Iterator<Item = reflection::Parameter<'a>> + '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 {
Expand Down
Loading

0 comments on commit 8759f14

Please sign in to comment.