Skip to main content

xaeroflux_core/
event.rs

1//! Core event definitions for xaeroflux-core.
2//!
3//! This module provides:
4//! - `Event<T>`: generic event envelope with type, version, timestamp, and payload.
5//! - `EventType` and `SystemEventKind`: enums categorizing different event classes.
6//! - Serialization support via `rkyv` for zero-copy archiving.
7//! - `EVENT_HEADER` magic and `META_BASE` offset for metadata event encoding.
8
9use std::fmt::Debug;
10
11use bytemuck::{Pod, Zeroable};
12use rkyv::{Archive, Deserialize, Serialize};
13
14pub use crate::{pool::XaeroEvent, vector_clock::VectorClock};
15
16/// Magic bytes prefix for event headers in paged segments.
17/// Used to identify and slice raw event bytes from storage pages.
18pub static EVENT_HEADER: &[u8; 4] = b"XAER";
19
20/// CREATE event types must be starting from 1008 + any applications may wish
21pub 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}
30/// Base value offset for encoding `MetaEvent` variants in the event type byte.
31pub const META_BASE: u8 = 128;
32
33// CRDT Application Event Constants (Base 30+)
34pub const CRDT_BASE: u8 = 30;
35
36// OR-Set CRDT Events
37pub const CRDT_SET_ADD: u8 = 30;
38pub const CRDT_SET_REMOVE: u8 = 31;
39pub const CRDT_SET_STATE: u8 = 32;
40
41// Counter CRDT Events
42pub const CRDT_COUNTER_INCREMENT: u8 = 33;
43pub const CRDT_COUNTER_DECREMENT: u8 = 34;
44pub const CRDT_COUNTER_STATE: u8 = 35;
45
46// RGA Text CRDT Events
47pub const CRDT_TEXT_INSERT: u8 = 36;
48pub const CRDT_TEXT_DELETE: u8 = 37;
49pub const CRDT_TEXT_STATE: u8 = 38;
50
51// Tree CRDT Events
52pub 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
57// LWW Register CRDT Events
58pub const CRDT_REGISTER_WRITE: u8 = 43;
59pub const CRDT_REGISTER_STATE: u8 = 44;
60
61// Reserve 45-59 for future CRDT types
62
63// Network Event Constants (Base 60+)
64pub const NETWORK_BASE: u8 = 60;
65
66// XSP (XaeroProtocol) Sync Events
67pub 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
72// Additional Network Events
73pub 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
82// Reserve 72-127 for future network events
83
84pub const PIN_FLAG: u32 = 0x8000_0000; // High bit = pinned
85
86// Helper functions
87pub 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 // Remove pin flag to get original type
97}
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/// Discriminant for different categories of events.
124///
125/// Encodes application, system, metadata, and network events.
126#[derive(Debug, Clone, Archive, Serialize, Deserialize, PartialEq, Eq)]
127#[rkyv(derive(Debug))]
128pub enum EventType {
129    /// Application-level event carrying a user-defined subtype.
130    ApplicationEvent(u8),
131    /// Built-in system control events (start/stop/pause/etc.).
132    SystemEvent(SystemEventKind),
133    /// Metadata events offset by `META_BASE` for internal operations.
134    MetaEvent(u8),
135    /// Networking-level events, e.g., peer discovery or connection state.
136    NetworkEvent(u8),
137}
138
139impl Default for EventType {
140    fn default() -> Self {
141        EventType::ApplicationEvent(0)
142    }
143}
144
145#[repr(C)]
146/// Specific kinds of system events controlling actor lifecycle and system operations.
147///
148/// Includes basic lifecycle events for actor control.
149#[derive(Debug, Clone, Archive, Serialize, Deserialize, PartialEq, Eq)]
150#[rkyv(derive(Debug))]
151pub enum SystemEventKind {
152    /// Indicates the system or actor should start processing.
153    Start,
154    /// Indicates the system or actor should stop processing.
155    Stop,
156    /// Indicates the system or actor should pause processing temporarily.
157    Pause,
158    /// Indicates the system or actor should resume processing after a pause.
159    Resume,
160    /// Indicates the system or actor should shutdown gracefully.
161    Shutdown,
162    /// Indicates the system or actor should restart.
163    Restart,
164}
165
166impl EventType {
167    pub fn from_u8(value: u8) -> Self {
168        // If it's ≥ META_BASE, interpret as MetaEvent(inner)
169        if value >= META_BASE {
170            return EventType::MetaEvent(value - META_BASE);
171        }
172
173        match value {
174            0 => EventType::ApplicationEvent(0),
175
176            // SystemEventKind variants (map numbers → enum)
177            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            // Reserve 7-29 for future system events
185
186            // CRDT Application Events (30-44)
187            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            // Reserve 45-59 for future CRDT types
204
205            // Network events (60-127)
206            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            // System events
217            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    /// Check if this is an XSP sync event
230    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    /// Check if this is a media stream event
235    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    /// Check if this is a file transfer event
240    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
266// Helper functions for XSP events
267impl EventType {
268    /// Create MMR peaks exchange event
269    pub fn mmr_peaks_exchange() -> Self {
270        EventType::NetworkEvent(MMR_PEAKS_EXCHANGE)
271    }
272
273    /// Create MMR diff event
274    pub fn mmr_diff() -> Self {
275        EventType::NetworkEvent(MMR_DIFF)
276    }
277
278    /// Create events request event
279    pub fn events_request() -> Self {
280        EventType::NetworkEvent(EVENTS_REQUEST)
281    }
282
283    /// Create events response event
284    pub fn events_response() -> Self {
285        EventType::NetworkEvent(EVENTS_RESPONSE)
286    }
287
288    /// Create peer connected event
289    pub fn peer_connected() -> Self {
290        EventType::NetworkEvent(PEER_CONNECTED)
291    }
292
293    /// Create peer disconnected event
294    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}