1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
use crate::CompilationError; use crate::path::Path; use crate::schemas::path; use crate::step::BoolCollector; use crate::step::Node; use crate::step::StepMaker; use preserves::value::IOValue; use std::rc::Rc; pub trait Predicate: std::fmt::Debug { fn test(&mut self, path: Rc<Path>, value: &IOValue) -> bool; } #[derive(Debug)] pub enum CompiledPredicate { Selector(Node), Not(Box<CompiledPredicate>), Or(Vec<CompiledPredicate>), And(Vec<CompiledPredicate>), } impl path::Predicate { pub fn compile(&self) -> Result<CompiledPredicate, CompilationError> { match self { path::Predicate::Selector(b) => Ok(CompiledPredicate::Selector((&**b).connect(BoolCollector::new())?)), path::Predicate::Not { pred } => Ok(CompiledPredicate::Not(Box::new((&**pred).compile()?))), path::Predicate::Or { preds } => Ok(CompiledPredicate::Or(preds.iter().map(Self::compile).collect::<Result<_,_>>()?)), path::Predicate::And { preds } => Ok(CompiledPredicate::And(preds.iter().map(Self::compile).collect::<Result<_,_>>()?)), } } pub fn exec(&self, value: &IOValue) -> Result<bool, CompilationError> { Ok(self.compile()?.test(Path::root(), value)) } } impl Predicate for CompiledPredicate { fn test(&mut self, path: Rc<Path>, value: &IOValue) -> bool { match self { CompiledPredicate::Selector(n) => n.test(path, value), CompiledPredicate::Not(p) => !p.test(path, value), CompiledPredicate::Or(ps) => { for p in ps.iter_mut() { if p.test(Rc::clone(&path), value) { return true; } } return false; }, CompiledPredicate::And(ps) => { for p in ps.iter_mut() { if !p.test(Rc::clone(&path), value) { return false; } } return true; }, } } }