This repository has no description
1use knot_types::{ActorId, ChangeId, CobId, TypeName};
2
3use crate::change::{Change, ChangePayload};
4use crate::error::CobError;
5use crate::graph::{ChangeGraph, History};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum HistoryModel {
9 Linear,
10 Convergent,
11}
12
13pub trait Evaluate {
14 type State;
15 type Change: ChangePayload;
16
17 const HISTORY: HistoryModel;
18
19 fn initial() -> Self::State;
20 fn apply(state: Self::State, change: Self::Change, author: &ActorId) -> Self::State;
21}
22
23knot_types::scalar_newtype! {
24 pub struct SnapshotStride(usize);
25 pub struct StateSize(usize);
26}
27
28pub trait Checkpoint: Evaluate {
29 const SNAPSHOT_STRIDE: SnapshotStride;
30 fn checkpoint_size(state: &Self::State) -> StateSize;
31}
32
33pub(crate) fn fold_changes<E: Evaluate>(
34 state: E::State,
35 changes: &[Change],
36 expected: &TypeName,
37) -> Result<E::State, CobError> {
38 changes.iter().try_fold(state, |state, change| {
39 if change.type_name != *expected {
40 return Err(CobError::UnexpectedChangeType {
41 change: change.id,
42 expected: expected.clone(),
43 found: change.type_name.clone(),
44 });
45 }
46 let payload =
47 E::Change::decode(change.payload()).map_err(|error| CobError::UndecodableChange {
48 change: change.id,
49 reason: error.to_string(),
50 })?;
51 Ok(E::apply(state, payload, &change.author))
52 })
53}
54
55pub(crate) fn evaluate<E: Evaluate>(
56 graph: ChangeGraph,
57 expected: &TypeName,
58) -> Result<(E::State, History), CobError> {
59 let root = ChangeId::new(graph.root().oid());
60 let ordered = graph.into_ordered();
61 let state = fold_changes::<E>(E::initial(), &ordered, expected)?;
62 Ok((state, History::new(root, ordered)))
63}
64
65#[derive(Debug)]
66pub struct Object<S> {
67 id: CobId,
68 type_name: TypeName,
69 state: S,
70 history: History,
71}
72
73impl<S> Object<S> {
74 pub(crate) fn new(id: CobId, type_name: TypeName, state: S, history: History) -> Self {
75 Self {
76 id,
77 type_name,
78 state,
79 history,
80 }
81 }
82
83 pub fn id(&self) -> CobId {
84 self.id
85 }
86
87 pub fn type_name(&self) -> &TypeName {
88 &self.type_name
89 }
90
91 pub fn state(&self) -> &S {
92 &self.state
93 }
94
95 pub fn into_state(self) -> S {
96 self.state
97 }
98
99 pub fn history(&self) -> &History {
100 &self.history
101 }
102}