1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4use sha2::{Digest, Sha256};
5
6use crate::{auth::Attested, clock::Clock, collection::CollectionId, id::EntityId, AttestationSet, DecodeError};
7
8#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
9pub struct EventId([u8; 32]);
10
11impl std::fmt::Debug for EventId {
12 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "EventId({})", self.to_base64()) }
13}
14
15impl EventId {
16 pub fn from_parts(entity_id: &EntityId, operations: &OperationSet, parent: &Clock) -> Self {
19 let mut hasher = Sha256::new();
20 hasher.update(bincode::serialize(&entity_id).unwrap());
21 hasher.update(bincode::serialize(&operations).unwrap());
22 hasher.update(bincode::serialize(&parent).unwrap());
23 Self(hasher.finalize().into())
24 }
25 pub fn to_base64(&self) -> String {
26 use base64::{engine::general_purpose, Engine as _};
27 general_purpose::URL_SAFE_NO_PAD.encode(self.0)
28 }
29 pub fn to_base64_short(&self) -> String {
30 let value = self.to_base64();
32 value[value.len() - 6..].to_string()
33 }
34 pub fn from_base64<T: AsRef<[u8]>>(input: T) -> Result<Self, DecodeError> {
35 use base64::{engine::general_purpose, Engine as _};
36 let decoded = general_purpose::URL_SAFE_NO_PAD.decode(input)?;
37 let v: [u8; 32] = decoded.try_into().map_err(|_| DecodeError::InvalidLength)?;
38
39 Ok(Self(v))
40 }
41 pub fn to_bytes(self) -> [u8; 32] { self.0 }
42 pub fn from_bytes(bytes: [u8; 32]) -> Self { Self(bytes) }
43 pub fn as_bytes(&self) -> &[u8] { &self.0 }
44}
45
46impl std::fmt::Display for EventId {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 if f.alternate() {
49 write!(f, "{}", self.to_base64_short())
50 } else {
51 write!(f, "{}", self.to_base64())
52 }
53 }
54}
55
56impl TryFrom<String> for EventId {
57 type Error = DecodeError;
58
59 fn try_from(s: String) -> Result<Self, Self::Error> { Self::from_base64(&s) }
60}
61
62impl From<[u8; 32]> for EventId {
63 fn from(bytes: [u8; 32]) -> Self { Self(bytes) }
64}
65impl TryFrom<Vec<u8>> for EventId {
66 type Error = DecodeError;
67
68 fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
69 let v: [u8; 32] = bytes.try_into().map_err(|_| DecodeError::InvalidLength)?;
70 Ok(Self(v))
71 }
72}
73
74impl Serialize for EventId {
75 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
76 where S: serde::Serializer {
77 if serializer.is_human_readable() {
78 serializer.serialize_str(&self.to_base64())
80 } else {
81 self.0.serialize(serializer)
83 }
84 }
85}
86
87impl<'de> Deserialize<'de> for EventId {
88 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
89 where D: serde::Deserializer<'de> {
90 if deserializer.is_human_readable() {
91 let s = String::deserialize(deserializer)?;
93 EventId::from_base64(s).map_err(serde::de::Error::custom)
94 } else {
95 let bytes = <[u8; 32]>::deserialize(deserializer)?;
97 Ok(EventId::from_bytes(bytes))
98 }
99 }
100}
101
102#[derive(Debug, Serialize, Deserialize, Clone)]
103pub struct Event {
104 pub collection: CollectionId,
105 pub entity_id: EntityId,
106 pub operations: OperationSet,
107 pub parent: Clock,
109}
110
111impl Event {
112 pub fn is_entity_create(&self) -> bool { self.parent.is_empty() }
114}
115
116#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
117pub struct EventFragment {
118 pub operations: OperationSet,
119 pub parent: Clock,
120 pub attestations: AttestationSet,
121}
122
123impl From<Attested<Event>> for EventFragment {
124 fn from(attested: Attested<Event>) -> Self {
125 Self { operations: attested.payload.operations, parent: attested.payload.parent, attestations: attested.attestations }
126 }
127}
128
129impl From<(EntityId, CollectionId, EventFragment)> for Attested<Event> {
130 fn from(value: (EntityId, CollectionId, EventFragment)) -> Self {
131 let event = Event { entity_id: value.0, collection: value.1, operations: value.2.operations, parent: value.2.parent };
132 Attested { payload: event, attestations: value.2.attestations }
133 }
134}
135
136#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
137pub struct StateFragment {
138 pub state: State,
139 pub attestations: AttestationSet,
140}
141
142impl From<Attested<EntityState>> for StateFragment {
143 fn from(attested: Attested<EntityState>) -> Self { Self { state: attested.payload.state, attestations: attested.attestations } }
144}
145impl From<(EntityId, CollectionId, StateFragment)> for Attested<EntityState> {
146 fn from(value: (EntityId, CollectionId, StateFragment)) -> Self {
147 let entity_state = EntityState { entity_id: value.0, collection: value.1, state: value.2.state };
148 Attested { payload: entity_state, attestations: value.2.attestations }
149 }
150}
151
152impl Event {
153 pub fn id(&self) -> EventId { EventId::from_parts(&self.entity_id, &self.operations, &self.parent) }
154}
155
156#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
157pub struct OperationSet(pub BTreeMap<String, Vec<Operation>>);
158
159impl std::fmt::Display for OperationSet {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 write!(
162 f,
163 "OperationSet({})",
164 self.0
165 .iter()
166 .map(|(backend, ops)| format!("{} => {}b", backend, ops.iter().map(|op| op.diff.len()).sum::<usize>()))
167 .collect::<Vec<_>>()
168 .join(" ")
169 )
170 }
171}
172
173impl std::ops::Deref for OperationSet {
174 type Target = BTreeMap<String, Vec<Operation>>;
175 fn deref(&self) -> &Self::Target { &self.0 }
176}
177
178#[derive(Debug, Serialize, Deserialize, Clone, Hash, Eq, PartialEq)]
179pub struct Operation {
180 pub diff: Vec<u8>,
181}
182
183#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
184pub struct EntityState {
185 pub entity_id: EntityId,
186 pub collection: CollectionId,
187 pub state: State,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
191pub struct State {
192 pub state_buffers: StateBuffers,
194 pub head: Clock,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
199pub struct StateBuffers(pub BTreeMap<String, Vec<u8>>);
200
201impl std::ops::Deref for StateBuffers {
202 type Target = BTreeMap<String, Vec<u8>>;
203 fn deref(&self) -> &Self::Target { &self.0 }
204}
205
206impl std::fmt::Display for Event {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 write!(
209 f,
210 "Event({} {}/{} {}{} {})",
211 self.id().to_base64_short(),
212 self.collection,
213 self.entity_id.to_base64_short(),
214 if self.is_entity_create() { "(create) " } else { "" },
215 self.parent.to_base64_short(),
216 self.operations
217 .iter()
218 .map(|(backend, ops)| format!("{} => {}b", backend, ops.iter().map(|op| op.diff.len()).sum::<usize>()))
219 .collect::<Vec<_>>()
220 .join(" ")
221 )
222 }
223}
224
225impl std::fmt::Display for EventFragment {
226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227 write!(f, "EventFragment(parent {} operations {})", self.parent, self.operations)
228 }
229}
230
231impl std::fmt::Display for State {
232 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
233 write!(
234 f,
235 "State({:#} buffers {})",
236 self.head,
237 self.state_buffers.iter().map(|(backend, buf)| format!("{} => {}b", backend, buf.len())).collect::<Vec<_>>().join(" ")
238 )
239 }
240}
241
242impl std::fmt::Display for StateFragment {
243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244 write!(f, "StateFragment(state {} attestations: {})", self.state, self.attestations.len())
245 }
246}
247
248impl std::fmt::Display for EntityState {
249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250 write!(f, "EntityState({} {})", self.entity_id.to_base64_short(), self.state)
251 }
252}
253
254impl Attested<Event> {
255 pub fn collection(&self) -> &CollectionId { &self.payload.collection }
256}
257
258impl From<Event> for Attested<Event> {
259 fn from(val: Event) -> Self { Attested { payload: val, attestations: AttestationSet::default() } }
260}
261
262impl From<EntityState> for Attested<EntityState> {
263 fn from(val: EntityState) -> Self { Attested { payload: val, attestations: AttestationSet::default() } }
264}
265
266impl Attested<EntityState> {
267 pub fn to_parts(self) -> (EntityId, CollectionId, StateFragment) {
268 (self.payload.entity_id, self.payload.collection, StateFragment { state: self.payload.state, attestations: self.attestations })
269 }
270 pub fn from_parts(entity_id: EntityId, collection: CollectionId, fragment: StateFragment) -> Self {
271 Self { payload: EntityState { entity_id, collection, state: fragment.state }, attestations: fragment.attestations }
272 }
273}
274
275impl Attested<Event> {
276 pub fn from_parts(entity_id: EntityId, collection: CollectionId, frag: EventFragment) -> Self {
277 Self { payload: Event { entity_id, collection, operations: frag.operations, parent: frag.parent }, attestations: frag.attestations }
278 }
279}
280
281#[cfg(test)]
282mod tests {
283 use super::*;
284
285 #[test]
286 fn test_event_id_json_serialization() {
287 let id = EventId::from_bytes([
288 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,
289 ]);
290 let json = serde_json::to_string(&id).unwrap();
291 assert_eq!(json, "\"AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA\"");
292 assert_eq!(id, serde_json::from_str(&json).unwrap());
293 }
294
295 #[test]
296 fn test_event_id_bincode_serialization() {
297 let id = EventId::from_bytes([
298 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,
299 ]);
300 let bytes = bincode::serialize(&id).unwrap();
301 assert_eq!(
302 bytes,
303 [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]
304 );
305 assert_eq!(id, bincode::deserialize(&bytes).unwrap());
306 }
307}