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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
use crate::push_index_if_explain; #[derive(PartialEq, Clone, Copy)] pub enum EffectKind { Allow = 0, Indeterminate = 1, Deny = 2, } pub trait Effector: Send + Sync { fn new_stream(&self, expr: &str, cap: usize) -> Box<dyn EffectorStream>; } pub trait EffectorStream: Send + Sync { fn next(&self) -> bool; #[cfg(feature = "explain")] fn explain(&self) -> Option<Vec<usize>>; fn push_effect(&mut self, eft: EffectKind) -> bool; } #[derive(Clone)] pub struct DefaultEffectStream { done: bool, res: bool, expr: String, idx: usize, cap: usize, #[cfg(feature = "explain")] explain: Vec<usize>, } #[derive(Default)] pub struct DefaultEffector; impl Effector for DefaultEffector { fn new_stream(&self, expr: &str, cap: usize) -> Box<dyn EffectorStream> { assert!(cap > 0); let res = match &*expr { "some(where (p_eft == allow))" | "some(where (p_eft == allow)) && !some(where (p_eft == deny))" | "priority(p_eft) || deny" => false, "!some(where (p_eft == deny))" => true, _ => panic!("unsupported effect: `{}`", expr), }; Box::new(DefaultEffectStream { done: false, res, expr: expr.to_owned(), cap, idx: 0, #[cfg(feature = "explain")] explain: Vec::with_capacity(10), }) } } impl EffectorStream for DefaultEffectStream { #[inline] fn next(&self) -> bool { assert!(self.done); self.res } #[cfg(feature = "explain")] #[inline] fn explain(&self) -> Option<Vec<usize>> { assert!(self.done); if self.explain.is_empty() { None } else { Some(self.explain.clone()) } } fn push_effect(&mut self, eft: EffectKind) -> bool { if self.expr == "some(where (p_eft == allow))" { if eft == EffectKind::Allow { self.done = true; self.res = true; push_index_if_explain!(self); } } else if self.expr == "some(where (p_eft == allow)) && !some(where (p_eft == deny))" { if eft == EffectKind::Allow { self.res = true; push_index_if_explain!(self) } else if eft == EffectKind::Deny { self.done = true; self.res = false; push_index_if_explain!(self) } } else if self.expr == "!some(where (p_eft == deny))" { if eft == EffectKind::Deny { self.done = true; self.res = false; push_index_if_explain!(self) } } else if self.expr == "priority(p_eft) || deny" && eft != EffectKind::Indeterminate { if eft == EffectKind::Allow { self.res = true; } else { self.res = false; } self.done = true; } if self.idx + 1 == self.cap { self.done = true; self.idx = self.cap; } else { self.idx += 1; } self.done } }