1use crate::clock::{Clock, Duration, Instant, SimClock};
4use crate::fault::FaultConfig;
5use crate::io::NodeAddress;
6use crate::rng::{Rng, Xorshift64};
7
8#[derive(Debug, Clone)]
14pub struct Envelope<const N: usize> {
15 pub src: NodeAddress,
16 pub dst: NodeAddress,
17 pub data: heapless::Vec<u8, N>,
18 pub deliver_at: Instant,
20}
21
22pub struct SimBus<const N: usize, const Q: usize> {
34 clock: SimClock,
35 rng: Xorshift64,
36 faults: FaultConfig,
37 queue: heapless::Vec<Envelope<N>, Q>,
38}
39
40impl<const N: usize, const Q: usize> SimBus<N, Q> {
41 pub fn new(seed: u64, faults: FaultConfig) -> Self {
42 Self {
43 clock: SimClock::new(),
44 rng: Xorshift64::new(seed),
45 faults,
46 queue: heapless::Vec::new(),
47 }
48 }
49
50 pub fn now(&self) -> Instant {
52 self.clock.now()
53 }
54
55 pub fn tick(&mut self, duration: Duration) -> heapless::Vec<Envelope<N>, Q> {
58 self.clock.advance(duration);
59 let now = self.clock.now();
60
61 let mut delivered = heapless::Vec::new();
62 let mut remaining = heapless::Vec::new();
63
64 for envelope in self.queue.drain(..) {
65 if envelope.deliver_at <= now {
66 let _ = delivered.push(envelope);
67 } else {
68 let _ = remaining.push(envelope);
69 }
70 }
71
72 if delivered.len() > 1 {
73 for i in 0..delivered.len() - 1 {
74 if self
75 .rng
76 .chance(self.faults.message_reorder.0, self.faults.message_reorder.1)
77 {
78 delivered.swap(i, i + 1);
79 }
80 }
81 }
82
83 self.queue = remaining;
84 delivered
85 }
86
87 pub fn send(&mut self, src: NodeAddress, dst: NodeAddress, data: &[u8]) -> bool {
92 if self
93 .rng
94 .chance(self.faults.message_loss.0, self.faults.message_loss.1)
95 {
96 return false;
97 }
98
99 if self
100 .rng
101 .chance(self.faults.timeout.0, self.faults.timeout.1)
102 {
103 return false;
104 }
105
106 let mut payload = heapless::Vec::new();
107
108 for &byte in data {
109 if self
110 .rng
111 .chance(self.faults.corruption.0, self.faults.corruption.1)
112 {
113 let _ = payload.push(byte ^ self.rng.next_u8());
114 } else {
115 let _ = payload.push(byte);
116 }
117 }
118
119 let deliver_at = if self
120 .rng
121 .chance(self.faults.message_delay.0, self.faults.message_delay.1)
122 {
123 let delay_us = self.rng.next_u64() % self.faults.max_delay.as_micros().max(1);
124 self.clock.now() + Duration::from_micros(delay_us)
125 } else {
126 self.clock.now()
127 };
128
129 let envelope = Envelope {
130 src,
131 dst,
132 data: payload,
133 deliver_at,
134 };
135
136 self.queue.push(envelope).is_ok()
137 }
138
139 pub fn faults(&self) -> &FaultConfig {
141 &self.faults
142 }
143
144 pub fn set_faults(&mut self, faults: FaultConfig) {
146 self.faults = faults;
147 }
148
149 pub fn next_u8(&mut self) -> u8 {
152 self.rng.next_u8()
153 }
154
155 pub fn chance(&mut self, numerator: u32, denominator: u32) -> bool {
156 self.rng.chance(numerator, denominator)
157 }
158}
159
160