Skip to main content

sim_lib_journal/
entry.rs

1use sim_kernel::{ContentId, Datum, NumberLiteral, Symbol};
2
3use crate::JournalError;
4
5/// One immutable journal fact whose identity is the canonical semantic Datum.
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct JournalEntry {
8    pub id: ContentId,
9    pub sequence: u64,
10    pub previous: Option<ContentId>,
11    pub kind: Symbol,
12    pub payloads: Vec<ContentId>,
13}
14
15impl JournalEntry {
16    /// Constructs a canonical `journal/entry-v2` value.
17    pub fn new(
18        sequence: u64,
19        previous: Option<ContentId>,
20        kind: Symbol,
21        payloads: Vec<ContentId>,
22    ) -> Self {
23        let mut value = Self {
24            id: ContentId::from_bytes(Symbol::new("unset"), [0; 32]),
25            sequence,
26            previous,
27            kind,
28            payloads,
29        };
30        value.id = value
31            .canonical_datum()
32            .content_id()
33            .expect("journal entry construction is canonical");
34        value
35    }
36
37    /// Returns the exact semantic value whose content id is this entry's id.
38    pub fn canonical_datum(&self) -> Datum {
39        Datum::Node {
40            tag: Symbol::qualified("journal", "entry-v2"),
41            fields: vec![
42                (
43                    Symbol::new("sequence"),
44                    Datum::Number(NumberLiteral {
45                        domain: Symbol::qualified("numbers", "u64"),
46                        canonical: self.sequence.to_string(),
47                    }),
48                ),
49                (
50                    Symbol::new("previous"),
51                    self.previous.as_ref().map_or(Datum::Nil, id_datum),
52                ),
53                (Symbol::new("kind"), Datum::Symbol(self.kind.clone())),
54                (
55                    Symbol::new("payloads"),
56                    Datum::Vector(self.payloads.iter().map(id_datum).collect()),
57                ),
58            ],
59        }
60    }
61
62    pub(crate) fn canonical_id(&self) -> Result<ContentId, JournalError> {
63        self.canonical_datum()
64            .content_id()
65            .map_err(|_| JournalError::CorruptEntry)
66    }
67}
68
69pub(crate) fn id_datum(id: &ContentId) -> Datum {
70    Datum::Node {
71        tag: Symbol::qualified("journal", "content-id-v1"),
72        fields: vec![
73            (
74                Symbol::new("algorithm"),
75                Datum::Symbol(id.algorithm.clone()),
76            ),
77            (Symbol::new("digest"), Datum::Bytes(id.bytes.to_vec())),
78        ],
79    }
80}