1use std::fmt::Debug;
10
11use bytemuck::{Pod, Zeroable};
12use rkyv::{Archive, Deserialize, Serialize};
13
14pub use crate::{pool::XaeroEvent, vector_clock::VectorClock};
15
16pub static EVENT_HEADER: &[u8; 4] = b"XAER";
19
20pub const CREATE_EVENT_TYPE_BASE: u32 = 1008;
22pub const UPDATE_EVENT_TYPE_BASE: u32 = 2008;
23pub const TOMBSTONE_EVENT_TYPE_BASE: u32 = 3008;
24
25pub enum OperationKind {
26 Create,
27 Update,
28 Tombstone,
29}
30pub const META_BASE: u8 = 128;
32
33pub const CRDT_BASE: u8 = 30;
35
36pub const CRDT_SET_ADD: u8 = 30;
38pub const CRDT_SET_REMOVE: u8 = 31;
39pub const CRDT_SET_STATE: u8 = 32;
40
41pub const CRDT_COUNTER_INCREMENT: u8 = 33;
43pub const CRDT_COUNTER_DECREMENT: u8 = 34;
44pub const CRDT_COUNTER_STATE: u8 = 35;
45
46pub const CRDT_TEXT_INSERT: u8 = 36;
48pub const CRDT_TEXT_DELETE: u8 = 37;
49pub const CRDT_TEXT_STATE: u8 = 38;
50
51pub const CRDT_TREE_ADD_NODE: u8 = 39;
53pub const CRDT_TREE_REMOVE_NODE: u8 = 40;
54pub const CRDT_TREE_MOVE_NODE: u8 = 41;
55pub const CRDT_TREE_STATE: u8 = 42;
56
57pub const CRDT_REGISTER_WRITE: u8 = 43;
59pub const CRDT_REGISTER_STATE: u8 = 44;
60
61pub const NETWORK_BASE: u8 = 60;
65
66pub const MMR_PEAKS_EXCHANGE: u8 = 60;
68pub const MMR_DIFF: u8 = 61;
69pub const EVENTS_REQUEST: u8 = 62;
70pub const EVENTS_RESPONSE: u8 = 63;
71
72pub const PEER_CONNECTED: u8 = 64;
74pub const PEER_DISCONNECTED: u8 = 65;
75pub const FILE_TRANSFER_START: u8 = 66;
76pub const FILE_TRANSFER_COMPLETE: u8 = 67;
77pub const AUDIO_CALL_START: u8 = 68;
78pub const AUDIO_CALL_END: u8 = 69;
79pub const VIDEO_CALL_START: u8 = 70;
80pub const VIDEO_CALL_END: u8 = 71;
81
82pub const PIN_FLAG: u32 = 0x8000_0000; pub fn is_pinned_event(event_type: u32) -> bool {
88 (event_type & PIN_FLAG) != 0
89}
90
91pub fn make_pinned(event_type: u32) -> u32 {
92 event_type | PIN_FLAG
93}
94
95pub fn get_base_event_type(event_type: u32) -> u32 {
96 event_type & !PIN_FLAG }
98
99pub fn is_create_event(event_type: u32) -> bool {
100 let base_event_type = get_base_event_type(event_type);
101 match base_event_type {
102 1008..2008 => true,
103 _ => false,
104 }
105}
106
107pub fn is_update_event(event_type: u32) -> bool {
108 let base_event_type = get_base_event_type(event_type);
109 match base_event_type {
110 2008..3008 => true,
111 _ => false,
112 }
113}
114
115pub fn is_tombstone_event(event_type: u32) -> bool {
116 let base_event_type = get_base_event_type(event_type);
117 match base_event_type {
118 3008..4008 => true,
119 _ => false,
120 }
121}
122#[repr(C)]
123#[derive(Debug, Clone, Archive, Serialize, Deserialize, PartialEq, Eq)]
127#[rkyv(derive(Debug))]
128pub enum EventType {
129 ApplicationEvent(u8),
131 SystemEvent(SystemEventKind),
133 MetaEvent(u8),
135 NetworkEvent(u8),
137}
138
139impl Default for EventType {
140 fn default() -> Self {
141 EventType::ApplicationEvent(0)
142 }
143}
144
145#[repr(C)]
146#[derive(Debug, Clone, Archive, Serialize, Deserialize, PartialEq, Eq)]
150#[rkyv(derive(Debug))]
151pub enum SystemEventKind {
152 Start,
154 Stop,
156 Pause,
158 Resume,
160 Shutdown,
162 Restart,
164}
165
166impl EventType {
167 pub fn from_u8(value: u8) -> Self {
168 if value >= META_BASE {
170 return EventType::MetaEvent(value - META_BASE);
171 }
172
173 match value {
174 0 => EventType::ApplicationEvent(0),
175
176 1 => EventType::SystemEvent(SystemEventKind::Start),
178 2 => EventType::SystemEvent(SystemEventKind::Stop),
179 3 => EventType::SystemEvent(SystemEventKind::Pause),
180 4 => EventType::SystemEvent(SystemEventKind::Resume),
181 5 => EventType::SystemEvent(SystemEventKind::Shutdown),
182 6 => EventType::SystemEvent(SystemEventKind::Restart),
183
184 CRDT_SET_ADD => EventType::ApplicationEvent(CRDT_SET_ADD),
188 CRDT_SET_REMOVE => EventType::ApplicationEvent(CRDT_SET_REMOVE),
189 CRDT_SET_STATE => EventType::ApplicationEvent(CRDT_SET_STATE),
190 CRDT_COUNTER_INCREMENT => EventType::ApplicationEvent(CRDT_COUNTER_INCREMENT),
191 CRDT_COUNTER_DECREMENT => EventType::ApplicationEvent(CRDT_COUNTER_DECREMENT),
192 CRDT_COUNTER_STATE => EventType::ApplicationEvent(CRDT_COUNTER_STATE),
193 CRDT_TEXT_INSERT => EventType::ApplicationEvent(CRDT_TEXT_INSERT),
194 CRDT_TEXT_DELETE => EventType::ApplicationEvent(CRDT_TEXT_DELETE),
195 CRDT_TEXT_STATE => EventType::ApplicationEvent(CRDT_TEXT_STATE),
196 CRDT_TREE_ADD_NODE => EventType::ApplicationEvent(CRDT_TREE_ADD_NODE),
197 CRDT_TREE_REMOVE_NODE => EventType::ApplicationEvent(CRDT_TREE_REMOVE_NODE),
198 CRDT_TREE_MOVE_NODE => EventType::ApplicationEvent(CRDT_TREE_MOVE_NODE),
199 CRDT_TREE_STATE => EventType::ApplicationEvent(CRDT_TREE_STATE),
200 CRDT_REGISTER_WRITE => EventType::ApplicationEvent(CRDT_REGISTER_WRITE),
201 CRDT_REGISTER_STATE => EventType::ApplicationEvent(CRDT_REGISTER_STATE),
202
203 v if (NETWORK_BASE..META_BASE).contains(&v) => EventType::NetworkEvent(v),
207
208 _ => panic!("Invalid event type: {}", value),
209 }
210 }
211
212 pub fn to_u8(&self) -> u8 {
213 match self {
214 EventType::ApplicationEvent(v) => *v,
215
216 EventType::SystemEvent(SystemEventKind::Start) => 1,
218 EventType::SystemEvent(SystemEventKind::Stop) => 2,
219 EventType::SystemEvent(SystemEventKind::Pause) => 3,
220 EventType::SystemEvent(SystemEventKind::Resume) => 4,
221 EventType::SystemEvent(SystemEventKind::Shutdown) => 5,
222 EventType::SystemEvent(SystemEventKind::Restart) => 6,
223
224 EventType::NetworkEvent(v) => *v,
225 EventType::MetaEvent(v) => META_BASE + *v,
226 }
227 }
228
229 pub fn is_xsp_sync_event(&self) -> bool {
231 matches!(self, EventType::NetworkEvent(v) if (MMR_PEAKS_EXCHANGE..=EVENTS_RESPONSE).contains(v))
232 }
233
234 pub fn is_media_event(&self) -> bool {
236 matches!(self, EventType::NetworkEvent(v) if (AUDIO_CALL_START..=VIDEO_CALL_END).contains(v))
237 }
238
239 pub fn is_file_transfer_event(&self) -> bool {
241 matches!(self, EventType::NetworkEvent(v) if (FILE_TRANSFER_START..=FILE_TRANSFER_COMPLETE).contains(v))
242 }
243}
244
245#[repr(u16)]
246#[derive(Debug, Clone, Copy, PartialEq, Eq)]
247pub enum SystemErrorCode {
248 DbWrite = 1,
249 SegmentRoll = 2,
250 PageFlush = 3,
251 MmrAppend = 4,
252 SecondaryIndex = 5,
253 Unknown = 0xFFFF,
254}
255
256#[repr(C)]
257#[derive(Clone, Copy, Debug)]
258pub struct ScanWindow {
259 pub start: u64,
260 pub end: u64,
261}
262
263unsafe impl Pod for ScanWindow {}
264unsafe impl Zeroable for ScanWindow {}
265
266impl EventType {
268 pub fn mmr_peaks_exchange() -> Self {
270 EventType::NetworkEvent(MMR_PEAKS_EXCHANGE)
271 }
272
273 pub fn mmr_diff() -> Self {
275 EventType::NetworkEvent(MMR_DIFF)
276 }
277
278 pub fn events_request() -> Self {
280 EventType::NetworkEvent(EVENTS_REQUEST)
281 }
282
283 pub fn events_response() -> Self {
285 EventType::NetworkEvent(EVENTS_RESPONSE)
286 }
287
288 pub fn peer_connected() -> Self {
290 EventType::NetworkEvent(PEER_CONNECTED)
291 }
292
293 pub fn peer_disconnected() -> Self {
295 EventType::NetworkEvent(PEER_DISCONNECTED)
296 }
297}
298
299#[cfg(test)]
300mod tests {
301 use super::*;
302
303 #[test]
304 fn test_xsp_event_constants() {
305 assert_eq!(MMR_PEAKS_EXCHANGE, 60);
306 assert_eq!(MMR_DIFF, 61);
307 assert_eq!(EVENTS_REQUEST, 62);
308 assert_eq!(EVENTS_RESPONSE, 63);
309 }
310
311 #[test]
312 fn test_event_type_conversions() {
313 let event = EventType::mmr_peaks_exchange();
314 assert_eq!(event.to_u8(), MMR_PEAKS_EXCHANGE);
315 assert_eq!(EventType::from_u8(MMR_PEAKS_EXCHANGE), event);
316 }
317
318 #[test]
319 fn test_xsp_sync_detection() {
320 assert!(EventType::mmr_peaks_exchange().is_xsp_sync_event());
321 assert!(EventType::mmr_diff().is_xsp_sync_event());
322 assert!(EventType::events_request().is_xsp_sync_event());
323 assert!(EventType::events_response().is_xsp_sync_event());
324
325 assert!(!EventType::peer_connected().is_xsp_sync_event());
326 assert!(!EventType::ApplicationEvent(CRDT_SET_ADD).is_xsp_sync_event());
327 }
328
329 #[test]
330 fn test_media_event_detection() {
331 let audio_start = EventType::NetworkEvent(AUDIO_CALL_START);
332 let video_end = EventType::NetworkEvent(VIDEO_CALL_END);
333
334 assert!(audio_start.is_media_event());
335 assert!(video_end.is_media_event());
336 assert!(!EventType::mmr_peaks_exchange().is_media_event());
337 }
338
339 #[test]
340 fn test_file_transfer_detection() {
341 let file_start = EventType::NetworkEvent(FILE_TRANSFER_START);
342 let file_complete = EventType::NetworkEvent(FILE_TRANSFER_COMPLETE);
343
344 assert!(file_start.is_file_transfer_event());
345 assert!(file_complete.is_file_transfer_event());
346 assert!(!EventType::mmr_peaks_exchange().is_file_transfer_event());
347 }
348}