pub const NOT_AVAILABLE: u8 = 0xFF;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Signals {
bytes: [u8; 8],
}
impl Default for Signals {
fn default() -> Self {
Self::new()
}
}
impl Signals {
pub fn new() -> Signals {
Signals {
bytes: [NOT_AVAILABLE; 8],
}
}
pub fn from_bytes(bytes: [u8; 8]) -> Signals {
Signals { bytes }
}
pub fn as_bytes(&self) -> &[u8; 8] {
&self.bytes
}
pub fn set_u8(&mut self, at: usize, value: u8) -> &mut Signals {
if at < 8 {
self.bytes[at] = value;
}
self
}
pub fn set_u16(&mut self, at: usize, value: u16) -> &mut Signals {
if at + 1 < 8 {
self.bytes[at..at + 2].copy_from_slice(&value.to_le_bytes());
}
self
}
pub fn u8(&self, at: usize) -> Option<u8> {
self.bytes.get(at).copied()
}
pub fn u16(&self, at: usize) -> Option<u16> {
if at + 1 < 8 {
Some(u16::from_le_bytes([self.bytes[at], self.bytes[at + 1]]))
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_new_payload_reports_nothing() {
let payload = Signals::new();
assert_eq!(payload.as_bytes(), &[NOT_AVAILABLE; 8]);
assert_eq!(payload.u8(0), Some(NOT_AVAILABLE));
assert_eq!(payload.u16(0), Some(0xFFFF));
}
#[test]
fn a_signal_reads_back_from_where_it_was_written() {
let mut payload = Signals::new();
payload.set_u16(3, 8_000).set_u8(2, 125);
assert_eq!(payload.u16(3), Some(8_000));
assert_eq!(payload.u8(2), Some(125));
assert_eq!(payload.u8(0), Some(NOT_AVAILABLE));
assert_eq!(Signals::from_bytes(*payload.as_bytes()), payload);
}
#[test]
fn a_signal_past_the_payload_is_refused_rather_than_wrapped() {
let mut payload = Signals::new();
payload.set_u8(8, 1);
payload.set_u16(7, 1);
assert_eq!(payload.as_bytes(), &[NOT_AVAILABLE; 8]);
assert_eq!(payload.u8(8), None);
assert_eq!(payload.u16(7), None);
}
}