use buggy::Bug;
use serde::{Deserialize, Serialize};
use crate::{
Address,
command::{CmdId, Command},
storage::{FactPerspective, Perspective},
};
#[derive(Debug, PartialEq, Eq, thiserror::Error)]
pub enum PolicyError {
#[error("read error")]
Read,
#[error("write error")]
Write,
#[error("check error")]
Check,
#[error("panic")]
Panic,
#[error("internal error")]
InternalError,
#[error(transparent)]
Bug(#[from] Bug),
}
impl From<core::convert::Infallible> for PolicyError {
fn from(error: core::convert::Infallible) -> Self {
match error {}
}
}
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Serialize, Deserialize)]
pub struct PolicyId(usize);
impl PolicyId {
pub fn new(id: usize) -> Self {
Self(id)
}
}
pub trait PolicyStore {
type Policy: Policy<Effect = Self::Effect>;
type Effect;
fn add_policy(&mut self, policy: &[u8]) -> Result<PolicyId, PolicyError>;
fn get_policy(&self, id: PolicyId) -> Result<&Self::Policy, PolicyError>;
}
pub trait Sink<Eff> {
fn begin(&mut self);
fn consume(&mut self, effect: Eff);
fn rollback(&mut self);
fn commit(&mut self);
}
pub struct NullSink;
impl<Eff> Sink<Eff> for NullSink {
fn begin(&mut self) {}
fn consume(&mut self, _effect: Eff) {}
fn rollback(&mut self) {}
fn commit(&mut self) {}
}
pub struct MergeIds {
left: Address,
right: Address,
}
impl MergeIds {
pub fn new(a: Address, b: Address) -> Option<Self> {
use core::cmp::Ordering;
match a.id.cmp(&b.id) {
Ordering::Less => Some(Self { left: a, right: b }),
Ordering::Equal => None,
Ordering::Greater => Some(Self { left: b, right: a }),
}
}
}
impl From<MergeIds> for (CmdId, CmdId) {
fn from(value: MergeIds) -> Self {
(value.left.id, value.right.id)
}
}
impl From<MergeIds> for (Address, Address) {
fn from(value: MergeIds) -> Self {
(value.left, value.right)
}
}
pub trait Policy {
type Action<'a>;
type Effect;
type Command<'a>: Command;
fn serial(&self) -> u32;
fn call_rule(
&self,
command: &impl Command,
facts: &mut impl FactPerspective,
sink: &mut impl Sink<Self::Effect>,
placement: CommandPlacement,
) -> Result<(), PolicyError>;
fn call_action(
&self,
action: Self::Action<'_>,
facts: &mut impl Perspective,
sink: &mut impl Sink<Self::Effect>,
placement: ActionPlacement,
) -> Result<(), PolicyError>;
fn merge<'a>(
&self,
target: &'a mut [u8],
ids: MergeIds,
) -> Result<Self::Command<'a>, PolicyError>;
}
#[derive(Copy, Clone, Debug)]
pub enum ActionPlacement {
OnGraph,
OffGraph,
}
#[derive(Copy, Clone, Debug)]
pub enum CommandPlacement {
OnGraphAtOrigin,
OnGraphInBraid,
OffGraph,
}