1use std::collections::{HashMap, VecDeque};
10
11pub trait ChannelLayer {
16 fn bridge_send(&mut self, channel: u8, msg: &[u8]) -> bool;
17 fn bridge_recv(&mut self, channel: u8) -> Option<Vec<u8>>;
18 fn is_live(&self) -> bool;
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum ChannelMode {
25 Live,
27 Simulated,
29 Bridging,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34#[repr(u8)]
35pub enum ChannelKind {
36 Fleet = 0,
38 Training = 1,
40 Event = 2,
42 Tiles = 3,
44 Trust = 4,
46 Custom(u8),
48}
49
50impl ChannelKind {
51 pub fn from_byte(b: u8) -> Self {
52 match b {
53 0 => ChannelKind::Fleet,
54 1 => ChannelKind::Training,
55 2 => ChannelKind::Event,
56 3 => ChannelKind::Tiles,
57 4 => ChannelKind::Trust,
58 n => ChannelKind::Custom(n),
59 }
60 }
61
62 pub fn to_byte(self) -> u8 {
63 match self {
64 ChannelKind::Fleet => 0,
65 ChannelKind::Training => 1,
66 ChannelKind::Event => 2,
67 ChannelKind::Tiles => 3,
68 ChannelKind::Trust => 4,
69 ChannelKind::Custom(n) => n,
70 }
71 }
72
73 pub fn name(&self) -> &'static str {
74 match self {
75 ChannelKind::Fleet => "fleet",
76 ChannelKind::Training => "training",
77 ChannelKind::Event => "event",
78 ChannelKind::Tiles => "tiles",
79 ChannelKind::Trust => "trust",
80 ChannelKind::Custom(_) => "custom",
81 }
82 }
83}
84
85#[derive(Debug, Clone)]
88pub struct ChannelMessage {
89 pub payload: Vec<u8>,
90 pub channel: ChannelKind,
91 pub source: String, pub timestamp: u64, pub sim_origin: bool, pub quality_score: f32, }
96
97impl ChannelMessage {
98 pub fn new(channel: ChannelKind, source: &str, payload: &[u8]) -> Self {
99 Self {
100 payload: payload.to_vec(),
101 channel,
102 source: source.to_string(),
103 timestamp: nanos_now(),
104 sim_origin: false,
105 quality_score: 0.5,
106 }
107 }
108
109 pub fn from_sim(channel: ChannelKind, source: &str, payload: &[u8]) -> Self {
110 let mut msg = Self::new(channel, source, payload);
111 msg.sim_origin = true;
112 msg
113 }
114
115 pub fn with_quality(mut self, q: f32) -> Self {
116 self.quality_score = q.max(0.0).min(1.0);
117 self
118 }
119}
120
121#[derive(Debug, Clone)]
125pub struct ChannelAdapter {
126 mode: ChannelMode,
127 channels: HashMap<u8, VecDeque<ChannelMessage>>,
128 max_buffer: usize,
129 messages_sent: u64,
130 messages_received: u64,
131 messages_bridged: u64,
132}
133
134impl ChannelAdapter {
135 pub fn new(mode: ChannelMode) -> Self {
136 Self {
137 mode,
138 channels: HashMap::new(),
139 max_buffer: 256,
140 messages_sent: 0,
141 messages_received: 0,
142 messages_bridged: 0,
143 }
144 }
145
146 pub fn live() -> Self { Self::new(ChannelMode::Live) }
147 pub fn simulated() -> Self { Self::new(ChannelMode::Simulated) }
148 pub fn bridging() -> Self { Self::new(ChannelMode::Bridging) }
149
150 pub fn with_max_buffer(mut self, max: usize) -> Self {
152 self.max_buffer = max;
153 self
154 }
155
156 pub fn send_typed(&mut self, kind: ChannelKind, source: &str, payload: &[u8]) -> bool {
158 let ch = kind.to_byte();
159 let cap = self.max_buffer;
160 let buf = self.channels.entry(ch).or_insert_with(VecDeque::new);
161 if buf.len() >= cap { return false; }
162 buf.push_back(ChannelMessage::new(kind, source, payload));
163 self.messages_sent += 1;
164 true
165 }
166
167 pub fn send_sim(&mut self, kind: ChannelKind, source: &str, payload: &[u8]) -> bool {
169 let ch = kind.to_byte();
170 let cap = self.max_buffer;
171 let buf = self.channels.entry(ch).or_insert_with(VecDeque::new);
172 if buf.len() >= cap { return false; }
173 buf.push_back(ChannelMessage::from_sim(kind, source, payload));
174 self.messages_sent += 1;
175 self.messages_bridged += 1;
176 true
177 }
178
179 pub fn recv(&mut self, kind: ChannelKind) -> Option<Vec<u8>> {
181 let ch = kind.to_byte();
182 let msg = self.channels.get_mut(&ch)?.pop_front()?;
183 self.messages_received += 1;
184 Some(msg.payload)
185 }
186
187 pub fn recv_full(&mut self, kind: ChannelKind) -> Option<ChannelMessage> {
189 let ch = kind.to_byte();
190 let msg = self.channels.get_mut(&ch)?.pop_front()?;
191 self.messages_received += 1;
192 Some(msg)
193 }
194
195 pub fn bridge(&mut self, from: ChannelKind, to: ChannelKind) -> usize {
197 let from_ch = from.to_byte();
198 let all_msgs: Vec<ChannelMessage> = self.channels.remove(&from_ch)
200 .unwrap_or_default().into_iter().collect();
201
202 let mut sim = Vec::new();
204 let mut non_sim = Vec::new();
205 for msg in all_msgs {
206 if msg.sim_origin { sim.push(msg); } else { non_sim.push(msg); }
207 }
208
209 if !non_sim.is_empty() {
211 self.channels.insert(from_ch, non_sim.into_iter().collect());
212 }
213
214 let count = sim.len();
216 let target = self.channels.entry(to.to_byte()).or_insert_with(VecDeque::new);
217 for msg in sim {
218 if target.len() < self.max_buffer {
219 target.push_back(msg);
220 self.messages_bridged += 1;
221 }
222 }
223 count
224 }
225
226 pub fn channel_size(&self, kind: ChannelKind) -> usize {
228 self.channels.get(&kind.to_byte()).map(|b| b.len()).unwrap_or(0)
229 }
230
231 pub fn total_buffered(&self) -> usize {
233 self.channels.values().map(|b| b.len()).sum()
234 }
235
236 pub fn set_mode(&mut self, mode: ChannelMode) {
238 self.mode = mode;
239 }
240
241 pub fn stats(&self) -> ChannelStats {
243 ChannelStats {
244 mode: self.mode,
245 messages_sent: self.messages_sent,
246 messages_received: self.messages_received,
247 messages_bridged: self.messages_bridged,
248 active_channels: self.channels.len(),
249 total_buffered: self.total_buffered(),
250 }
251 }
252}
253
254#[derive(Debug, Clone, Copy)]
255pub struct ChannelStats {
256 pub mode: ChannelMode,
257 pub messages_sent: u64,
258 pub messages_received: u64,
259 pub messages_bridged: u64,
260 pub active_channels: usize,
261 pub total_buffered: usize,
262}
263
264impl ChannelLayer for ChannelAdapter {
265 fn bridge_send(&mut self, channel: u8, msg: &[u8]) -> bool {
266 let is_sim = self.mode != ChannelMode::Live;
267 let kind = ChannelKind::from_byte(channel);
268 let buf = self.channels.entry(channel).or_insert_with(VecDeque::new);
269 if buf.len() >= self.max_buffer { return false; }
270 let mut ch_msg = ChannelMessage::new(kind, "bridge", msg);
271 ch_msg.sim_origin = is_sim;
272 buf.push_back(ch_msg);
273 self.messages_sent += 1;
274 true
275 }
276
277 fn bridge_recv(&mut self, channel: u8) -> Option<Vec<u8>> {
278 let msg = self.channels.get_mut(&channel)?.pop_front()?;
279 self.messages_received += 1;
280 Some(msg.payload)
281 }
282
283 fn is_live(&self) -> bool {
284 self.mode == ChannelMode::Live
285 }
286}
287
288fn nanos_now() -> u64 {
289 use std::time::{SystemTime, UNIX_EPOCH};
290 SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_nanos() as u64).unwrap_or(0)
291}
292
293#[cfg(test)]
296mod tests {
297 use super::*;
298
299 #[test]
300 fn test_channel_send_recv() {
301 let mut ch = ChannelAdapter::live();
302 ch.send_typed(ChannelKind::Fleet, "oracle1", b"hello");
303 let msg = ch.recv(ChannelKind::Fleet).unwrap();
304 assert_eq!(msg, b"hello");
305 }
306
307 #[test]
308 fn test_channel_recv_empty() {
309 let mut ch = ChannelAdapter::simulated();
310 assert!(ch.recv(ChannelKind::Event).is_none());
311 }
312
313 #[test]
314 fn test_channel_ordering() {
315 let mut ch = ChannelAdapter::live();
316 ch.send_typed(ChannelKind::Training, "a", b"1");
317 ch.send_typed(ChannelKind::Training, "b", b"2");
318 ch.send_typed(ChannelKind::Training, "c", b"3");
319
320 assert_eq!(ch.recv(ChannelKind::Training).unwrap(), b"1");
321 assert_eq!(ch.recv(ChannelKind::Training).unwrap(), b"2");
322 }
323
324 #[test]
325 fn test_sim_messages() {
326 let mut ch = ChannelAdapter::simulated();
327 ch.send_sim(ChannelKind::Tiles, "sim", b"tile_data");
328 let msg = ch.recv_full(ChannelKind::Tiles).unwrap();
329 assert!(msg.sim_origin);
330 assert_eq!(msg.payload, b"tile_data");
331 }
332
333 #[test]
334 fn test_bridge() {
335 let mut ch = ChannelAdapter::bridging();
336 ch.send_sim(ChannelKind::Fleet, "sim", b"sim_msg_1");
338 ch.send_sim(ChannelKind::Fleet, "sim", b"sim_msg_2");
339 ch.send_typed(ChannelKind::Fleet, "live_agent", b"live_msg");
341
342 let bridged = ch.bridge(ChannelKind::Fleet, ChannelKind::Event);
344 assert_eq!(bridged, 2); assert_eq!(ch.channel_size(ChannelKind::Event), 2);
348 assert_eq!(ch.channel_size(ChannelKind::Fleet), 1);
350 }
351
352 #[test]
353 fn test_capacity_limit() {
354 let mut ch = ChannelAdapter::live().with_max_buffer(2);
355 assert!(ch.send_typed(ChannelKind::Event, "a", b"1"));
356 assert!(ch.send_typed(ChannelKind::Event, "a", b"2"));
357 assert!(!ch.send_typed(ChannelKind::Event, "a", b"3")); }
359
360 #[test]
361 fn test_is_live() {
362 assert!(ChannelAdapter::live().is_live());
363 assert!(!ChannelAdapter::simulated().is_live());
364 assert!(!ChannelAdapter::bridging().is_live());
365 }
366
367 #[test]
368 fn test_channel_layer_trait() {
369 let mut ch = ChannelAdapter::live();
370 assert!(ch.bridge_send(0, b"fleet_msg")); assert!(ch.bridge_send(3, b"tile_msg")); let fleet = ch.bridge_recv(0).unwrap();
374 assert_eq!(fleet, b"fleet_msg");
375
376 let tiles = ch.bridge_recv(3).unwrap();
377 assert_eq!(tiles, b"tile_msg");
378 }
379
380 #[test]
381 fn test_channel_kinds() {
382 assert_eq!(ChannelKind::from_byte(0), ChannelKind::Fleet);
383 assert_eq!(ChannelKind::from_byte(1), ChannelKind::Training);
384 assert_eq!(ChannelKind::from_byte(5), ChannelKind::Custom(5));
385 assert_eq!(ChannelKind::Fleet.to_byte(), 0);
386 assert_eq!(ChannelKind::Custom(99).to_byte(), 99);
387 }
388
389 #[test]
390 fn test_quality_score() {
391 let msg = ChannelMessage::new(ChannelKind::Event, "src", b"data").with_quality(0.95);
392 assert_eq!(msg.quality_score, 0.95);
393 }
394
395 #[test]
396 fn test_quality_clamping() {
397 let msg = ChannelMessage::new(ChannelKind::Event, "src", b"data").with_quality(1.5);
398 assert_eq!(msg.quality_score, 1.0);
399 }
400
401 #[test]
402 fn test_stats() {
403 let mut ch = ChannelAdapter::bridging();
404 ch.send_typed(ChannelKind::Fleet, "a", b"1");
405 ch.send_sim(ChannelKind::Tiles, "sim", b"2");
406 ch.recv(ChannelKind::Fleet);
407
408 let stats = ch.stats();
409 assert_eq!(stats.messages_sent, 2);
410 assert_eq!(stats.messages_received, 1);
411 assert_eq!(stats.messages_bridged, 1);
412 assert_eq!(stats.active_channels, 2);
413 }
414
415 #[test]
416 fn test_mode_switch() {
417 let mut ch = ChannelAdapter::simulated();
418 assert!(!ch.is_live());
419 ch.set_mode(ChannelMode::Live);
420 assert!(ch.is_live());
421 }
422
423 #[test]
424 fn test_multiple_channels_independent() {
425 let mut ch = ChannelAdapter::live();
426 ch.send_typed(ChannelKind::Fleet, "a", b"f1");
427 ch.send_typed(ChannelKind::Training, "a", b"t1");
428
429 assert_eq!(ch.recv(ChannelKind::Fleet).unwrap(), b"f1");
430 assert_eq!(ch.recv(ChannelKind::Training).unwrap(), b"t1");
431 assert!(ch.recv(ChannelKind::Event).is_none()); }
433
434 #[test]
435 fn test_bridge_empty() {
436 let mut ch = ChannelAdapter::bridging();
437 let bridged = ch.bridge(ChannelKind::Event, ChannelKind::Fleet);
438 assert_eq!(bridged, 0);
439 }
440}