1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! Reference [`Sink`] implementations. Requires the `alloc` feature.
use Vec;
use crateSinkError;
use crateOwnedRecord;
use crateRecord;
use crateSink;
/// In-memory [`Sink`]: appends every record into a `Vec<OwnedRecord>`.
///
/// Intended for tests, prototypes, and short-lived buffering. Holds the
/// entire chain in memory, so it is not suitable for long-running
/// production workloads — use a file-backed or streaming sink instead.
///
/// # Example
///
/// ```
/// use audit_trail::{
/// Action, Actor, Chain, Clock, Digest, Hasher, MemorySink, Outcome, Record, RecordId,
/// SinkError, Target, Timestamp, HASH_LEN,
/// };
///
/// // Minimal hasher / clock for the example.
/// struct XorHasher([u8; HASH_LEN], usize);
/// impl Hasher for XorHasher {
/// fn reset(&mut self) { self.0 = [0u8; HASH_LEN]; self.1 = 0; }
/// fn update(&mut self, bytes: &[u8]) {
/// for b in bytes { self.0[self.1 % HASH_LEN] ^= *b; self.1 = self.1.wrapping_add(1); }
/// }
/// fn finalize(&mut self, out: &mut Digest) { *out = Digest::from_bytes(self.0); }
/// }
/// struct Tick(core::cell::Cell<u64>);
/// impl Clock for Tick {
/// fn now(&self) -> Timestamp {
/// let v = self.0.get(); self.0.set(v + 1); Timestamp::from_nanos(v)
/// }
/// }
///
/// let mut chain = Chain::new(
/// XorHasher([0u8; HASH_LEN], 0),
/// MemorySink::new(),
/// Tick(core::cell::Cell::new(1)),
/// );
/// chain.append(Actor::new("a"), Action::new("x"), Target::new("t"), Outcome::Success).unwrap();
///
/// assert_eq!(chain.sink().len(), 1);
/// ```