mod value;
use alloc::vec::Vec;
use core::{fmt::Debug, marker::PhantomData};
use binrw::{BinRead, BinWrite};
pub use self::value::*;
use crate::{protocol, protocol::r#struct::Readable};
#[must_use]
#[derive(Copy, Clone, Debug, BinWrite)]
#[bw(big)]
pub struct Args<V: Value> {
starting_address: u16,
n_registers: u16,
phantom_data: PhantomData<V>,
}
impl<V: Value> Args<V> {
#[must_use]
pub const fn n_registers(&self) -> u16 {
self.n_registers
}
#[expect(clippy::missing_panics_doc)]
pub fn new(starting_address: u16, n_values: usize) -> Result<Self, protocol::Error> {
let n_registers = n_values * V::N_BYTES / 2;
if (1..=125).contains(&n_registers) {
Ok(Self {
starting_address,
n_registers: u16::try_from(n_registers).unwrap(),
phantom_data: PhantomData,
})
} else {
Err(protocol::Error::InvalidCount(n_registers))
}
}
}
#[must_use]
#[derive(Clone, derive_more::Debug, BinRead)]
#[br(big)]
pub struct Output<V: Value> {
pub n_bytes: u8,
#[br(
assert(usize::from(n_bytes).is_multiple_of(V::N_BYTES)),
count = usize::from(n_bytes) / V::N_BYTES,
)]
pub values: Vec<V>,
}
#[must_use]
#[derive(Clone, derive_more::Debug, BinRead)]
#[br(big)]
pub struct OutputExact<const N: usize, V: Value> {
#[br(assert(usize::from(n_bytes) == V::N_BYTES * N))]
pub n_bytes: u8,
pub values: [V; N],
}
pub trait Value: Readable + 'static {
const N_BYTES: usize;
}