use std::borrow::Cow;
use crate::link::{Wire, WireError};
use crate::machine::Board;
use crate::time::VirtualNanos;
pub trait Edge: Board {
type Signals;
type Outputs;
const FIELDS: &'static [Field];
const OUTPUT_FIELDS: &'static [Field];
const REST: Self::Signals;
fn sense(&mut self, signals: &Self::Signals);
fn drive(&mut self) -> Self::Outputs;
}
pub trait Coupled: Board {
fn fields(&self) -> &'static [Field];
fn output_fields(&self) -> &'static [Field];
fn rest_wire(&self) -> Vec<u8>;
fn sense_wire(&mut self, bytes: &[u8]) -> Result<(), WireError>;
fn drive_wire(&mut self) -> Vec<u8>;
}
impl<B: Edge> Coupled for B
where
B::Signals: Wire,
B::Outputs: Wire,
{
fn fields(&self) -> &'static [Field] {
B::FIELDS
}
fn output_fields(&self) -> &'static [Field] {
B::OUTPUT_FIELDS
}
fn rest_wire(&self) -> Vec<u8> {
let mut bytes = Vec::new();
B::REST.encode(&mut bytes);
bytes
}
fn sense_wire(&mut self, bytes: &[u8]) -> Result<(), WireError> {
let signals = B::Signals::decode(&mut &*bytes)?;
self.sense(&signals);
Ok(())
}
fn drive_wire(&mut self) -> Vec<u8> {
let mut bytes = Vec::new();
self.drive().encode(&mut bytes);
bytes
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Field {
pub name: Cow<'static, str>,
pub unit: Cow<'static, str>,
pub width: u8,
pub signed: bool,
}
impl Field {
#[must_use]
pub const fn new(name: &'static str, unit: &'static str, width: u8, signed: bool) -> Self {
Self {
name: Cow::Borrowed(name),
unit: Cow::Borrowed(unit),
width,
signed,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Pulse {
pub width: VirtualNanos,
pub period: VirtualNanos,
}