casbin/
effector.rs

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}