1use buggy::Bug;
7use rend::u64_le;
8
9use crate::{
10 Address,
11 command::{CmdId, Command},
12 storage::{FactPerspective, Perspective},
13};
14
15#[derive(Debug, thiserror::Error)]
17#[non_exhaustive]
18pub enum PolicyError {
19 #[error("read error")]
20 Read,
21 #[error("write error")]
22 Write,
23 #[error("check error")]
24 Check,
25 #[error("panic")]
26 Panic,
27 #[error("internal error")]
28 InternalError,
29 #[error(transparent)]
30 Bug(#[from] Bug),
31}
32
33impl From<core::convert::Infallible> for PolicyError {
34 fn from(error: core::convert::Infallible) -> Self {
35 match error {}
36 }
37}
38
39#[derive(
40 Copy,
41 Clone,
42 Debug,
43 Ord,
44 PartialOrd,
45 Eq,
46 PartialEq,
47 serde::Serialize,
48 serde::Deserialize,
49 rkyv::Archive,
50 rkyv::Serialize,
51 rkyv::Deserialize,
52 rkyv::Portable,
53 rkyv::bytecheck::CheckBytes,
54)]
55#[rkyv(as = Self)]
56#[bytecheck(crate = rkyv::bytecheck)]
57#[serde(transparent)]
58#[repr(transparent)]
59pub struct PolicyId(#[serde(with = "crate::util::u64_le_serde")] u64_le);
60
61impl PolicyId {
62 pub fn new(id: u64) -> Self {
63 Self(id.into())
64 }
65}
66
67pub trait PolicyStore {
69 type Policy: Policy<Effect = Self::Effect>;
70
71 type Effect;
72
73 fn add_policy(&mut self, policy: &[u8]) -> Result<PolicyId, PolicyError>;
79
80 fn get_policy(&self, id: PolicyId) -> Result<&Self::Policy, PolicyError>;
86}
87
88pub trait Sink<Eff> {
90 fn begin(&mut self);
91 fn consume(&mut self, effect: Eff);
92 fn rollback(&mut self);
93 fn commit(&mut self);
94}
95
96pub struct NullSink;
97
98impl<Eff> Sink<Eff> for NullSink {
99 fn begin(&mut self) {}
100
101 fn consume(&mut self, _effect: Eff) {}
102
103 fn rollback(&mut self) {}
104
105 fn commit(&mut self) {}
106}
107
108pub struct MergeIds {
110 left: Address,
112 right: Address,
113}
114
115impl MergeIds {
116 pub fn new(a: Address, b: Address) -> Option<Self> {
118 use core::cmp::Ordering;
119 match a.id.cmp(&b.id) {
120 Ordering::Less => Some(Self { left: a, right: b }),
121 Ordering::Equal => None,
122 Ordering::Greater => Some(Self { left: b, right: a }),
123 }
124 }
125}
126
127impl From<MergeIds> for (CmdId, CmdId) {
128 fn from(value: MergeIds) -> Self {
130 (value.left.id, value.right.id)
131 }
132}
133
134impl From<MergeIds> for (Address, Address) {
135 fn from(value: MergeIds) -> Self {
137 (value.left, value.right)
138 }
139}
140
141pub trait Policy {
144 type Action<'a>;
145 type Effect;
146 type Command<'a>: Command;
147
148 fn serial(&self) -> u32;
151
152 fn call_rule(
156 &self,
157 command: &impl Command,
158 facts: &mut impl FactPerspective,
159 sink: &mut impl Sink<Self::Effect>,
160 placement: CommandPlacement,
161 ) -> Result<(), PolicyError>;
162
163 fn call_action(
167 &self,
168 action: Self::Action<'_>,
169 facts: &mut impl Perspective,
170 sink: &mut impl Sink<Self::Effect>,
171 placement: ActionPlacement,
172 ) -> Result<(), PolicyError>;
173
174 fn merge<'a>(
177 &self,
178 target: &'a mut [u8],
179 ids: MergeIds,
180 ) -> Result<Self::Command<'a>, PolicyError>;
181}
182
183#[derive(Copy, Clone, Debug)]
185pub enum ActionPlacement {
186 OnGraph,
188 OffGraph,
190}
191
192#[derive(Copy, Clone, Debug)]
193pub enum CommandPlacement {
195 OnGraphAtOrigin,
197 OnGraphInBraid,
199 OffGraph,
201}
202
203mod impls {
204 use alloc::boxed::Box;
205
206 use super::{PolicyError, PolicyId, PolicyStore, Sink};
207
208 impl<PS: PolicyStore> PolicyStore for &mut PS {
209 type Policy = PS::Policy;
210 type Effect = PS::Effect;
211
212 fn add_policy(&mut self, policy: &[u8]) -> Result<PolicyId, PolicyError> {
213 PS::add_policy(self, policy)
214 }
215
216 fn get_policy(&self, id: PolicyId) -> Result<&Self::Policy, PolicyError> {
217 PS::get_policy(self, id)
218 }
219 }
220
221 impl<PS: PolicyStore> PolicyStore for Box<PS> {
222 type Policy = PS::Policy;
223 type Effect = PS::Effect;
224
225 fn add_policy(&mut self, policy: &[u8]) -> Result<PolicyId, PolicyError> {
226 PS::add_policy(self, policy)
227 }
228
229 fn get_policy(&self, id: PolicyId) -> Result<&Self::Policy, PolicyError> {
230 PS::get_policy(self, id)
231 }
232 }
233
234 impl<S: Sink<Eff>, Eff> Sink<Eff> for &mut S {
235 fn begin(&mut self) {
236 S::begin(self);
237 }
238
239 fn consume(&mut self, effect: Eff) {
240 S::consume(self, effect);
241 }
242
243 fn rollback(&mut self) {
244 S::rollback(self);
245 }
246
247 fn commit(&mut self) {
248 S::commit(self);
249 }
250 }
251
252 impl<S: Sink<Eff>, Eff> Sink<Eff> for Box<S> {
253 fn begin(&mut self) {
254 S::begin(self);
255 }
256
257 fn consume(&mut self, effect: Eff) {
258 S::consume(self, effect);
259 }
260
261 fn rollback(&mut self) {
262 S::rollback(self);
263 }
264
265 fn commit(&mut self) {
266 S::commit(self);
267 }
268 }
269}