Skip to main content

bones_sim/
agent.rs

1use std::collections::BTreeSet;
2
3use serde::{Deserialize, Serialize};
4
5/// Stable identifier for a simulated agent.
6pub type AgentId = usize;
7
8/// Immutable snapshot of an agent's local state.
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10pub struct AgentState {
11    /// Agent identity.
12    pub id: AgentId,
13    /// Event IDs the agent has observed (including its own emitted events).
14    pub known_events: BTreeSet<u64>,
15}
16
17/// Event emitted by an agent during simulation.
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
19pub struct EmittedEvent {
20    /// Emitting agent.
21    pub source: AgentId,
22    /// Per-agent monotonic sequence.
23    pub seq: u64,
24    /// Global event identifier used in network delivery.
25    pub event_id: u64,
26}
27
28/// Minimal CRDT model for simulation: each agent tracks a grow-only set of event IDs.
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct SimulatedAgent {
31    id: AgentId,
32    next_seq: u64,
33    known_events: BTreeSet<u64>,
34}
35
36impl SimulatedAgent {
37    /// Create a new simulated agent with empty state.
38    #[must_use]
39    pub const fn new(id: AgentId) -> Self {
40        Self {
41            id,
42            next_seq: 0,
43            known_events: BTreeSet::new(),
44        }
45    }
46
47    /// Return this agent's ID.
48    #[must_use]
49    pub const fn id(&self) -> AgentId {
50        self.id
51    }
52
53    /// Emit a new event and apply it to local state immediately.
54    #[must_use]
55    pub fn emit_event(&mut self) -> EmittedEvent {
56        let seq = self.next_seq;
57        self.next_seq = self.next_seq.saturating_add(1);
58
59        let source_u64 = u64::try_from(self.id).unwrap_or(u64::MAX);
60        let event_id = (source_u64 << 32) | (seq & 0xFFFF_FFFF);
61
62        self.known_events.insert(event_id);
63
64        EmittedEvent {
65            source: self.id,
66            seq,
67            event_id,
68        }
69    }
70
71    /// Apply a delivered event.
72    pub fn observe_event(&mut self, event_id: u64) {
73        self.known_events.insert(event_id);
74    }
75
76    /// Get an immutable snapshot of current local state.
77    #[must_use]
78    pub fn snapshot(&self) -> AgentState {
79        AgentState {
80            id: self.id,
81            known_events: self.known_events.clone(),
82        }
83    }
84}