1use sim_kernel::{ContentId, Datum, NumberLiteral, Symbol};
2
3use crate::JournalError;
4
5#[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 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 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}