use crate::errors::MbusError;
pub const MAX_REGISTERS_PER_PDU: usize = 125;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Holding;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Input;
#[allow(deprecated)]
pub type HoldingRegisters<const N: usize = MAX_REGISTERS_PER_PDU> = Registers<N, Holding>;
#[allow(deprecated)]
pub type InputRegisters<const N: usize = MAX_REGISTERS_PER_PDU> = Registers<N, Input>;
#[derive(Debug, PartialEq, Eq, Clone)]
#[deprecated(
since = "0.11.0",
note = "Do not use `Registers` directly. Please use the typed registers `HoldingRegisters` or `InputRegisters` instead. In the future, this struct will not be exported to the user space."
)]
pub struct Registers<const N: usize = MAX_REGISTERS_PER_PDU, Mode = Holding> {
from_address: u16,
quantity: u16,
values: [u16; N],
_mode: core::marker::PhantomData<Mode>,
}
#[allow(deprecated)]
impl<const N: usize, Mode> Registers<N, Mode> {
pub fn new(from_address: u16, quantity: u16) -> Result<Self, MbusError> {
if quantity as usize > N {
return Err(MbusError::InvalidQuantity);
}
Ok(Self {
from_address,
quantity,
values: [0; N],
_mode: core::marker::PhantomData,
})
}
pub fn with_values(mut self, values: &[u16], length: u16) -> Result<Self, MbusError> {
if length > N as u16 {
return Err(MbusError::InvalidQuantity);
}
if length > self.quantity {
return Err(MbusError::InvalidQuantity);
}
self.values[..length as usize].copy_from_slice(values);
Ok(self)
}
pub fn new_from_be_bytes(
from_address: u16,
quantity: u16,
bytes: &[u8],
) -> Result<Self, MbusError> {
let mut reg = Self::new(from_address, quantity)?;
for (i, chunk) in bytes.chunks_exact(2).take(quantity as usize).enumerate() {
reg.values[i] = u16::from_be_bytes([chunk[0], chunk[1]]);
}
Ok(reg)
}
pub fn from_address(&self) -> u16 {
self.from_address
}
pub fn quantity(&self) -> u16 {
self.quantity
}
pub fn values(&self) -> &[u16; N] {
&self.values
}
pub fn value(&self, address: u16) -> Result<u16, MbusError> {
if address < self.from_address || address >= self.from_address + self.quantity {
return Err(MbusError::InvalidAddress);
}
let index = (address - self.from_address) as usize;
self.values
.get(index)
.copied()
.ok_or(MbusError::InvalidAddress)
}
}
#[allow(deprecated)]
impl<const N: usize> Registers<N, Holding> {
pub fn set_value(&mut self, address: u16, value: u16) -> Result<(), MbusError> {
if address < self.from_address || address >= self.from_address + self.quantity {
return Err(MbusError::InvalidAddress);
}
let index = (address - self.from_address) as usize;
self.values[index] = value;
Ok(())
}
}