This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / knot2 / crates / knot-cob / src / object.rs
2.5 kB 102 lines
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}