Skip to content

Commit

Permalink
chore: Make find_case object safe
Browse files Browse the repository at this point in the history
Apparently, a provided function can't downcast `&self` but I can if I
spread the implementation around.

Overall, trying to meet the goal of making it simple to write a
Predicate.  Anyone besides us will need to copy `default_find_case` if
they want the reference.  Not sure what would be a good way to make that
good enough for being stable.
  • Loading branch information
epage committed Jul 21, 2018
1 parent 5d6f8da commit 7d2afb9
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 5 deletions.
5 changes: 5 additions & 0 deletions src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use std::fmt;

use core;
use reflection;
use Predicate;

Expand Down Expand Up @@ -70,6 +71,10 @@ where
fn eval(&self, variable: &Item) -> bool {
self.0.eval(variable)
}

fn find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

/// `Predicate` extension for boxing a `Predicate`.
Expand Down
5 changes: 5 additions & 0 deletions src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use std::fmt;
use std::marker::PhantomData;

use core;
use reflection;
use Predicate;

Expand All @@ -27,6 +28,10 @@ impl<Item> Predicate<Item> for BooleanPredicate<Item> {
fn eval(&self, _variable: &Item) -> bool {
self.retval
}

fn find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl<Item> reflection::PredicateReflection for BooleanPredicate<Item> {
Expand Down
24 changes: 19 additions & 5 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,29 @@ pub trait Predicate<Item: ?Sized>: reflection::PredicateReflection {
fn eval(&self, variable: &Item) -> bool;

/// Find a case that proves this predicate as `expected` when run against `variable`.
fn find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>>
where
Self: Sized,
{
fn find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>> {
let actual = self.eval(variable);
if expected == actual {
Some(reflection::Case::new(Some(self), actual))
Some(reflection::Case::new(None, actual))
} else {
None
}
}
}

pub(crate) fn default_find_case<'a, P, Item>(
pred: &'a P,
expected: bool,
variable: &Item,
) -> Option<reflection::Case<'a>>
where
P: Predicate<Item>,
Item: ?Sized,
{
let actual = pred.eval(variable);
if expected == actual {
Some(reflection::Case::new(Some(pred), actual))
} else {
None
}
}
5 changes: 5 additions & 0 deletions src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use std::fmt;
use std::marker::PhantomData;

use core;
use reflection;
use Predicate;

Expand Down Expand Up @@ -59,6 +60,10 @@ where
fn eval(&self, variable: &T) -> bool {
(self.function)(variable)
}

fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl<F, T> reflection::PredicateReflection for FnPredicate<F, T>
Expand Down
25 changes: 25 additions & 0 deletions src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::fmt;
use std::hash::Hash;
use std::iter::FromIterator;

use core;
use reflection;
use Predicate;

Expand Down Expand Up @@ -76,6 +77,10 @@ where
fn eval(&self, variable: &T) -> bool {
self.inner.debug.contains(variable)
}

fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl<'a, T> Predicate<T> for InPredicate<&'a T>
Expand All @@ -85,6 +90,10 @@ where
fn eval(&self, variable: &T) -> bool {
self.inner.debug.contains(&variable)
}

fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
core::default_find_case(self, expected, variable)
}
}

impl<T> reflection::PredicateReflection for InPredicate<T>
Expand Down Expand Up @@ -169,6 +178,10 @@ where
fn eval(&self, variable: &T) -> bool {
self.inner.debug.binary_search(variable).is_ok()
}

fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl<'a, T> Predicate<T> for OrdInPredicate<&'a T>
Expand All @@ -178,6 +191,10 @@ where
fn eval(&self, variable: &T) -> bool {
self.inner.debug.binary_search(&variable).is_ok()
}

fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
core::default_find_case(self, expected, variable)
}
}

impl<T> reflection::PredicateReflection for OrdInPredicate<T>
Expand Down Expand Up @@ -223,6 +240,10 @@ where
fn eval(&self, variable: &T) -> bool {
self.inner.debug.contains(variable)
}

fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl<'a, T> Predicate<T> for HashableInPredicate<&'a T>
Expand All @@ -232,6 +253,10 @@ where
fn eval(&self, variable: &T) -> bool {
self.inner.debug.contains(&variable)
}

fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
core::default_find_case(self, expected, variable)
}
}

impl<T> reflection::PredicateReflection for HashableInPredicate<T>
Expand Down
17 changes: 17 additions & 0 deletions src/ord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use std::fmt;

use core;
use reflection;
use Predicate;

Expand Down Expand Up @@ -52,6 +53,10 @@ where
EqOps::NotEqual => variable.ne(&self.constant),
}
}

fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl<'a, T> Predicate<T> for EqPredicate<&'a T>
Expand All @@ -64,6 +69,10 @@ where
EqOps::NotEqual => variable.ne(self.constant),
}
}

fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
core::default_find_case(self, expected, variable)
}
}

impl<T> reflection::PredicateReflection for EqPredicate<T>
Expand Down Expand Up @@ -174,6 +183,10 @@ where
OrdOps::GreaterThan => variable.gt(&self.constant),
}
}

fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl<'a, T> Predicate<T> for OrdPredicate<&'a T>
Expand All @@ -188,6 +201,10 @@ where
OrdOps::GreaterThan => variable.gt(self.constant),
}
}

fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
core::default_find_case(self, expected, variable)
}
}

impl<T> reflection::PredicateReflection for OrdPredicate<T>
Expand Down
9 changes: 9 additions & 0 deletions src/path/existence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use std::fmt;
use std::path;

use core;
use reflection;
use Predicate;

Expand All @@ -24,6 +25,14 @@ impl Predicate<path::Path> for ExistencePredicate {
fn eval(&self, path: &path::Path) -> bool {
path.exists() == self.exists
}

fn find_case<'a>(
&'a self,
expected: bool,
variable: &path::Path,
) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl reflection::PredicateReflection for ExistencePredicate {}
Expand Down
25 changes: 25 additions & 0 deletions src/path/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::fs;
use std::io::{self, Read};
use std::path;

use core;
use reflection;
use Predicate;

Expand Down Expand Up @@ -59,12 +60,24 @@ impl Predicate<path::Path> for BinaryFilePredicate {
fn eval(&self, path: &path::Path) -> bool {
self.eval(path).unwrap_or(false)
}

fn find_case<'a>(
&'a self,
expected: bool,
variable: &path::Path,
) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl Predicate<[u8]> for BinaryFilePredicate {
fn eval(&self, actual: &[u8]) -> bool {
self.content.debug == actual
}

fn find_case<'a>(&'a self, expected: bool, variable: &[u8]) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl reflection::PredicateReflection for BinaryFilePredicate {
Expand Down Expand Up @@ -120,12 +133,24 @@ impl Predicate<path::Path> for StrFilePredicate {
fn eval(&self, path: &path::Path) -> bool {
self.eval(path).unwrap_or(false)
}

fn find_case<'a>(
&'a self,
expected: bool,
variable: &path::Path,
) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl Predicate<str> for StrFilePredicate {
fn eval(&self, actual: &str) -> bool {
self.content == actual
}

fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl reflection::PredicateReflection for StrFilePredicate {
Expand Down
17 changes: 17 additions & 0 deletions src/str/basics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use std::fmt;

use core;
use reflection;
use Predicate;

Expand All @@ -21,6 +22,10 @@ impl Predicate<str> for IsEmptyPredicate {
fn eval(&self, variable: &str) -> bool {
variable.is_empty()
}

fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl reflection::PredicateReflection for IsEmptyPredicate {}
Expand Down Expand Up @@ -58,6 +63,10 @@ impl Predicate<str> for StartsWithPredicate {
fn eval(&self, variable: &str) -> bool {
variable.starts_with(&self.pattern)
}

fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl reflection::PredicateReflection for StartsWithPredicate {}
Expand Down Expand Up @@ -100,6 +109,10 @@ impl Predicate<str> for EndsWithPredicate {
fn eval(&self, variable: &str) -> bool {
variable.ends_with(&self.pattern)
}

fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl reflection::PredicateReflection for EndsWithPredicate {}
Expand Down Expand Up @@ -162,6 +175,10 @@ impl Predicate<str> for ContainsPredicate {
fn eval(&self, variable: &str) -> bool {
variable.contains(&self.pattern)
}

fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl reflection::PredicateReflection for ContainsPredicate {}
Expand Down
5 changes: 5 additions & 0 deletions src/str/regex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::fmt;

use regex;

use core;
use reflection;
use Predicate;

Expand Down Expand Up @@ -45,6 +46,10 @@ impl Predicate<str> for RegexPredicate {
fn eval(&self, variable: &str) -> bool {
self.re.is_match(variable)
}

fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
core::default_find_case(self, expected, variable)
}
}

impl reflection::PredicateReflection for RegexPredicate {}
Expand Down

0 comments on commit 7d2afb9

Please sign in to comment.