1use buggy::Bug;
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 command::{Command, CommandId},
11 storage::{FactPerspective, Perspective},
12 Address,
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
32#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)]
33pub struct PolicyId(usize);
34
35impl PolicyId {
36 pub fn new(id: usize) -> Self {
37 PolicyId(id)
38 }
39}
40
41pub trait Engine {
43 type Policy: Policy<Effect = Self::Effect>;
44
45 type Effect;
46
47 fn add_policy(&mut self, policy: &[u8]) -> Result<PolicyId, EngineError>;
53
54 fn get_policy(&self, id: PolicyId) -> Result<&Self::Policy, EngineError>;
60}
61
62pub trait Sink<E> {
64 fn begin(&mut self);
65 fn consume(&mut self, effect: E);
66 fn rollback(&mut self);
67 fn commit(&mut self);
68}
69
70pub struct NullSink;
71
72impl<E> Sink<E> for NullSink {
73 fn begin(&mut self) {}
74
75 fn consume(&mut self, _effect: E) {}
76
77 fn rollback(&mut self) {}
78
79 fn commit(&mut self) {}
80}
81
82pub struct MergeIds {
84 left: Address,
86 right: Address,
87}
88
89impl MergeIds {
90 pub fn new(a: Address, b: Address) -> Option<Self> {
92 use core::cmp::Ordering;
93 match a.id.cmp(&b.id) {
94 Ordering::Less => Some(Self { left: a, right: b }),
95 Ordering::Equal => None,
96 Ordering::Greater => Some(Self { left: b, right: a }),
97 }
98 }
99}
100
101impl From<MergeIds> for (CommandId, CommandId) {
102 fn from(value: MergeIds) -> Self {
104 (value.left.id, value.right.id)
105 }
106}
107
108impl From<MergeIds> for (Address, Address) {
109 fn from(value: MergeIds) -> Self {
111 (value.left, value.right)
112 }
113}
114
115pub enum CommandRecall {
117 None,
119 OnCheck,
121}
122
123pub trait Policy {
126 type Action<'a>;
127 type Effect;
128 type Command<'a>: Command;
129
130 fn serial(&self) -> u32;
133
134 fn call_rule(
138 &self,
139 command: &impl Command,
140 facts: &mut impl FactPerspective,
141 sink: &mut impl Sink<Self::Effect>,
142 recall: CommandRecall,
143 ) -> Result<(), EngineError>;
144
145 fn call_action(
149 &self,
150 action: Self::Action<'_>,
151 facts: &mut impl Perspective,
152 sink: &mut impl Sink<Self::Effect>,
153 ) -> Result<(), EngineError>;
154
155 fn merge<'a>(
158 &self,
159 target: &'a mut [u8],
160 ids: MergeIds,
161 ) -> Result<Self::Command<'a>, EngineError>;
162}