use execution_context::ExecutionContext;
use failure::Fail;
use scheme::Scheme;
#[derive(Debug, PartialEq, Fail)]
#[fail(display = "execution context doesn't match the scheme with which filter was parsed")]
pub struct SchemeMismatchError;
pub(crate) struct CompiledExpr<'s>(Box<dyn 's + Fn(&ExecutionContext<'s>) -> bool>);
impl<'s> CompiledExpr<'s> {
pub(crate) fn new(closure: impl 's + Fn(&ExecutionContext<'s>) -> bool) -> Self {
CompiledExpr(Box::new(closure))
}
pub fn execute(&self, ctx: &ExecutionContext<'s>) -> bool {
self.0(ctx)
}
}
pub struct Filter<'s> {
root_expr: CompiledExpr<'s>,
scheme: &'s Scheme,
}
impl<'s> Filter<'s> {
pub(crate) fn new(root_expr: CompiledExpr<'s>, scheme: &'s Scheme) -> Self {
Filter { root_expr, scheme }
}
pub fn execute(&self, ctx: &ExecutionContext<'s>) -> Result<bool, SchemeMismatchError> {
if self.scheme == ctx.scheme() {
Ok(self.root_expr.execute(ctx))
} else {
Err(SchemeMismatchError)
}
}
}
#[cfg(test)]
mod tests {
use super::SchemeMismatchError;
use execution_context::ExecutionContext;
#[test]
fn test_scheme_mismatch() {
let scheme1 = Scheme! { foo: Int };
let scheme2 = Scheme! { foo: Int, bar: Int };
let filter = scheme1.parse("foo == 42").unwrap().compile();
let ctx = ExecutionContext::new(&scheme2);
assert_eq!(filter.execute(&ctx), Err(SchemeMismatchError));
}
}