Now let's take a silly one
1use serde::Serialize;
2
3const FNV_OFFSET: u64 = 0xcbf2_9ce4_8422_2325;
4const FNV_PRIME: u64 = 0x0000_0100_0000_01b3;
5
6pub(crate) fn fnv1a(bytes: &[u8]) -> u64 {
7 bytes.iter().fold(FNV_OFFSET, |hash, byte| {
8 (hash ^ u64::from(*byte)).wrapping_mul(FNV_PRIME)
9 })
10}
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
13#[serde(tag = "kind", rename_all = "snake_case")]
14pub enum Outcome {
15 Answered { status: u16, body: u64 },
16 Killed,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
20pub struct Step {
21 pub round: u32,
22 pub index: u32,
23 pub op: &'static str,
24 pub actor: String,
25 pub fault: &'static str,
26 pub outcome: Outcome,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
30pub struct RepoCollaborators {
31 pub repo: String,
32 pub subjects: Vec<String>,
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
36pub struct Projection {
37 pub members: Vec<String>,
38 pub blocked: Vec<String>,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
42pub struct Snapshot {
43 pub round: u32,
44 pub clock_micros: u64,
45 pub members: Vec<String>,
46 pub blocked: Vec<String>,
47 pub repos: Vec<String>,
48 pub collaborators: Vec<RepoCollaborators>,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
52pub struct Trace {
53 pub seed: u64,
54 pub steps: Vec<Step>,
55 pub snapshots: Vec<Snapshot>,
56}
57
58impl Trace {
59 pub fn digest(&self) -> u64 {
60 fnv1a(&serde_json::to_vec(self).expect("trace is always serializable"))
61 }
62}