1use crate::push_index_if_explain;
2
3#[derive(PartialEq, Eq, Clone, Copy)]
4pub enum EffectKind {
5 Allow = 0,
6 Indeterminate = 1,
7 Deny = 2,
8}
9
10pub trait Effector: Send + Sync {
11 fn new_stream(&self, expr: &str, cap: usize) -> Box<dyn EffectorStream>;
12}
13
14pub trait EffectorStream: Send + Sync {
15 fn next(&self) -> bool;
16 #[cfg(feature = "explain")]
17 fn explain(&self) -> Option<Vec<usize>>;
18 fn push_effect(&mut self, eft: EffectKind) -> bool;
19}
20
21#[derive(Clone)]
22pub struct DefaultEffectStream {
23 done: bool,
24 res: bool,
25 expr: String,
26 idx: usize,
27 cap: usize,
28 #[cfg(feature = "explain")]
29 expl: Vec<usize>,
30}
31
32#[derive(Default)]
33pub struct DefaultEffector;
34
35impl Effector for DefaultEffector {
36 fn new_stream(&self, expr: &str, cap: usize) -> Box<dyn EffectorStream> {
37 assert!(cap > 0);
38
39 let res = match expr {
40 "some(where (p_eft == allow))"
41 | "some(where (p_eft == allow)) && !some(where (p_eft == deny))"
42 | "priority(p_eft) || deny" => false,
43 "!some(where (p_eft == deny))" => true,
44 _ => panic!("unsupported effect: `{}`", expr),
45 };
46
47 Box::new(DefaultEffectStream {
48 done: false,
49 res,
50 expr: expr.to_owned(),
51 cap,
52 idx: 0,
53 #[cfg(feature = "explain")]
54 expl: Vec::with_capacity(10),
55 })
56 }
57}
58
59impl EffectorStream for DefaultEffectStream {
60 #[inline]
61 fn next(&self) -> bool {
62 assert!(self.done);
63 self.res
64 }
65
66 #[cfg(feature = "explain")]
67 #[inline]
68 fn explain(&self) -> Option<Vec<usize>> {
69 assert!(self.done);
70 if self.expl.is_empty() {
71 None
72 } else {
73 Some(self.expl.clone())
74 }
75 }
76
77 fn push_effect(&mut self, eft: EffectKind) -> bool {
78 if self.expr == "some(where (p_eft == allow))" {
79 if eft == EffectKind::Allow {
80 self.done = true;
81 self.res = true;
82
83 push_index_if_explain!(self);
84 }
85 } else if self.expr
86 == "some(where (p_eft == allow)) && !some(where (p_eft == deny))"
87 {
88 if eft == EffectKind::Allow {
89 self.res = true;
90
91 push_index_if_explain!(self)
92 } else if eft == EffectKind::Deny {
93 self.done = true;
94 self.res = false;
95
96 push_index_if_explain!(self)
97 }
98 } else if self.expr == "!some(where (p_eft == deny))" {
99 if eft == EffectKind::Deny {
100 self.done = true;
101 self.res = false;
102
103 push_index_if_explain!(self)
104 }
105 } else if self.expr == "priority(p_eft) || deny"
106 && eft != EffectKind::Indeterminate
107 {
108 self.res = eft == EffectKind::Allow;
109
110 self.done = true;
111
112 push_index_if_explain!(self)
113 }
114
115 if self.idx + 1 == self.cap {
116 self.done = true;
117 self.idx = self.cap;
118 } else {
119 self.idx += 1;
120 }
121
122 self.done
123 }
124}