use crate::bus::SimBus;
use crate::clock::{Duration, Instant};
use crate::io::NodeAddress;
use heapless::Vec;
pub trait SimNode<const N: usize, const Q: usize> {
type Error: core::fmt::Debug;
fn address(&self) -> &NodeAddress;
fn handle(&mut self, src: &NodeAddress, data: &[u8], now: Instant) -> Result<(), Self::Error>;
fn tick(&mut self, now: Instant) -> Result<(), Self::Error>;
fn drain_outbox(
&mut self,
out: &mut heapless::Vec<(NodeAddress, heapless::Vec<u8, N>), Q>,
) -> usize;
}
pub trait SimNodeErased<const N: usize, const Q: usize> {
fn address(&self) -> &NodeAddress;
fn handle(&mut self, src: &NodeAddress, data: &[u8], now: Instant);
fn tick(&mut self, now: Instant);
fn drain_outbox(&mut self, out: &mut Vec<(NodeAddress, Vec<u8, N>), Q>) -> usize;
}
impl<const N: usize, const Q: usize, T> SimNodeErased<N, Q> for T
where
T: SimNode<N, Q>,
T::Error: core::fmt::Debug,
{
fn address(&self) -> &NodeAddress {
SimNode::address(self)
}
fn handle(&mut self, src: &NodeAddress, data: &[u8], now: Instant) {
if let Err(e) = SimNode::handle(self, src, data, now) {
let _ = e;
}
}
fn tick(&mut self, now: Instant) {
if let Err(e) = SimNode::tick(self, now) {
let _ = e;
}
}
fn drain_outbox(&mut self, out: &mut Vec<(NodeAddress, Vec<u8, N>), Q>) -> usize {
SimNode::drain_outbox(self, out)
}
}
pub struct SimRunner<const N: usize, const Q: usize> {
bus: SimBus<N, Q>,
}
impl<const N: usize, const Q: usize> SimRunner<N, Q> {
pub fn new(bus: SimBus<N, Q>) -> Self {
Self { bus }
}
pub fn tick(
&mut self,
nodes: &mut [&mut dyn SimNodeErased<N, Q>],
duration: Duration,
) -> usize {
let delivered = self.bus.tick(duration);
let now = self.bus.now();
let mut count = 0;
for envelope in &delivered {
for node in nodes.iter_mut() {
if *node.address() == envelope.dst {
let _ = node.handle(&envelope.src, &envelope.data, now);
count += 1;
}
}
}
for node in nodes.iter_mut() {
let _ = node.tick(now);
}
let mut outbox = heapless::Vec::new();
for node in nodes.iter_mut() {
outbox.clear();
node.drain_outbox(&mut outbox);
let src = node.address().clone();
for (dst, data) in outbox.iter() {
self.bus.send(src.clone(), dst.clone(), data);
}
}
count
}
pub fn bus(&mut self) -> &mut SimBus<N, Q> {
&mut self.bus
}
}