1use buggy::Bug;
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 Address,
11 command::{CmdId, Command},
12 storage::{FactPerspective, Perspective},
13};
14
15#[derive(Debug, PartialEq, Eq, thiserror::Error)]
17pub enum EngineError {
18 #[error("read error")]
19 Read,
20 #[error("write error")]
21 Write,
22 #[error("check error")]
23 Check,
24 #[error("panic")]
25 Panic,
26 #[error("internal error")]
27 InternalError,
28 #[error(transparent)]
29 Bug(#[from] Bug),
30}
31
32impl From<core::convert::Infallible> for EngineError {
33 fn from(error: core::convert::Infallible) -> Self {
34 match error {}
35 }
36}
37
38#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)]
39pub struct PolicyId(usize);
40
41impl PolicyId {
42 pub fn new(id: usize) -> Self {
43 Self(id)
44 }
45}
46
47pub trait Engine {
49 type Policy: Policy<Effect = Self::Effect>;
50
51 type Effect;
52
53 fn add_policy(&mut self, policy: &[u8]) -> Result<PolicyId, EngineError>;
59
60 fn get_policy(&self, id: PolicyId) -> Result<&Self::Policy, EngineError>;
66}
67
68pub trait Sink<E> {
70 fn begin(&mut self);
71 fn consume(&mut self, effect: E);
72 fn rollback(&mut self);
73 fn commit(&mut self);
74}
75
76pub struct NullSink;
77
78impl<E> Sink<E> for NullSink {
79 fn begin(&mut self) {}
80
81 fn consume(&mut self, _effect: E) {}
82
83 fn rollback(&mut self) {}
84
85 fn commit(&mut self) {}
86}
87
88pub struct MergeIds {
90 left: Address,
92 right: Address,
93}
94
95impl MergeIds {
96 pub fn new(a: Address, b: Address) -> Option<Self> {
98 use core::cmp::Ordering;
99 match a.id.cmp(&b.id) {
100 Ordering::Less => Some(Self { left: a, right: b }),
101 Ordering::Equal => None,
102 Ordering::Greater => Some(Self { left: b, right: a }),
103 }
104 }
105}
106
107impl From<MergeIds> for (CmdId, CmdId) {
108 fn from(value: MergeIds) -> Self {
110 (value.left.id, value.right.id)
111 }
112}
113
114impl From<MergeIds> for (Address, Address) {
115 fn from(value: MergeIds) -> Self {
117 (value.left, value.right)
118 }
119}
120
121pub trait Policy {
124 type Action<'a>;
125 type Effect;
126 type Command<'a>: Command;
127
128 fn serial(&self) -> u32;
131
132 fn call_rule(
136 &self,
137 command: &impl Command,
138 facts: &mut impl FactPerspective,
139 sink: &mut impl Sink<Self::Effect>,
140 placement: CommandPlacement,
141 ) -> Result<(), EngineError>;
142
143 fn call_action(
147 &self,
148 action: Self::Action<'_>,
149 facts: &mut impl Perspective,
150 sink: &mut impl Sink<Self::Effect>,
151 placement: ActionPlacement,
152 ) -> Result<(), EngineError>;
153
154 fn merge<'a>(
157 &self,
158 target: &'a mut [u8],
159 ids: MergeIds,
160 ) -> Result<Self::Command<'a>, EngineError>;
161}
162
163#[derive(Copy, Clone, Debug)]
165pub enum ActionPlacement {
166 OnGraph,
168 OffGraph,
170}
171
172#[derive(Copy, Clone, Debug)]
173pub enum CommandPlacement {
175 OnGraphAtOrigin,
177 OnGraphInBraid,
179 OffGraph,
181}