use crate::error::{DecodeError, EncodeError};
use crate::request::Encode;
use rusty_modbus_types::{Address, FunctionCode, MAX_WRITE_REGISTERS, Quantity};
#[derive(Debug)]
pub struct WriteSingleRegisterResponse {
pub address: Address,
pub value: u16,
}
impl WriteSingleRegisterResponse {
pub fn decode(data: &[u8]) -> Result<Self, DecodeError> {
DecodeError::check_exact_len(data, 4)?;
let address = Address(u16::from_be_bytes([data[0], data[1]]));
let value = u16::from_be_bytes([data[2], data[3]]);
Ok(Self { address, value })
}
}
impl Encode for WriteSingleRegisterResponse {
fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
let len = self.encoded_len();
if buf.len() < len {
return Err(EncodeError::BufferTooSmall {
required: len,
available: buf.len(),
});
}
EncodeError::check_pdu_len(len)?;
buf[0] = FunctionCode::WriteSingleRegister.code();
let addr = self.address.0.to_be_bytes();
buf[1] = addr[0];
buf[2] = addr[1];
let val = self.value.to_be_bytes();
buf[3] = val[0];
buf[4] = val[1];
Ok(len)
}
fn encoded_len(&self) -> usize {
1 + 4
}
}
#[derive(Debug)]
pub struct WriteMultipleRegistersResponse {
pub address: Address,
pub quantity: Quantity,
}
impl WriteMultipleRegistersResponse {
pub fn decode(data: &[u8]) -> Result<Self, DecodeError> {
DecodeError::check_exact_len(data, 4)?;
let address = Address(u16::from_be_bytes([data[0], data[1]]));
let quantity = Quantity(u16::from_be_bytes([data[2], data[3]]));
Ok(Self { address, quantity })
}
}
impl Encode for WriteMultipleRegistersResponse {
fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
let len = self.encoded_len();
if buf.len() < len {
return Err(EncodeError::BufferTooSmall {
required: len,
available: buf.len(),
});
}
EncodeError::check_quantity(self.quantity.0, MAX_WRITE_REGISTERS)?;
EncodeError::check_pdu_len(len)?;
buf[0] = FunctionCode::WriteMultipleRegisters.code();
let addr = self.address.0.to_be_bytes();
buf[1] = addr[0];
buf[2] = addr[1];
let qty = self.quantity.0.to_be_bytes();
buf[3] = qty[0];
buf[4] = qty[1];
Ok(len)
}
fn encoded_len(&self) -> usize {
1 + 4
}
}
#[derive(Debug)]
pub struct MaskWriteRegisterResponse {
pub address: Address,
pub and_mask: u16,
pub or_mask: u16,
}
impl MaskWriteRegisterResponse {
pub fn decode(data: &[u8]) -> Result<Self, DecodeError> {
DecodeError::check_exact_len(data, 6)?;
let address = Address(u16::from_be_bytes([data[0], data[1]]));
let and_mask = u16::from_be_bytes([data[2], data[3]]);
let or_mask = u16::from_be_bytes([data[4], data[5]]);
Ok(Self {
address,
and_mask,
or_mask,
})
}
}
impl Encode for MaskWriteRegisterResponse {
fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
let len = self.encoded_len();
if buf.len() < len {
return Err(EncodeError::BufferTooSmall {
required: len,
available: buf.len(),
});
}
EncodeError::check_pdu_len(len)?;
buf[0] = FunctionCode::MaskWriteRegister.code();
let addr = self.address.0.to_be_bytes();
buf[1] = addr[0];
buf[2] = addr[1];
let and_m = self.and_mask.to_be_bytes();
buf[3] = and_m[0];
buf[4] = and_m[1];
let or_m = self.or_mask.to_be_bytes();
buf[5] = or_m[0];
buf[6] = or_m[1];
Ok(len)
}
fn encoded_len(&self) -> usize {
1 + 6
}
}
#[derive(Debug)]
pub struct ReadWriteMultipleRegistersResponse<'buf> {
pub byte_count: u8,
pub register_data: &'buf [u8],
}
impl<'buf> ReadWriteMultipleRegistersResponse<'buf> {
#[must_use]
pub fn count(&self) -> usize {
self.register_data.len() / 2
}
#[must_use]
pub fn register(&self, index: usize) -> u16 {
let off = index * 2;
u16::from_be_bytes([self.register_data[off], self.register_data[off + 1]])
}
pub fn registers(&self) -> impl Iterator<Item = u16> + '_ {
self.register_data
.chunks_exact(2)
.map(|c| u16::from_be_bytes([c[0], c[1]]))
}
#[must_use]
pub fn raw(&self) -> &'buf [u8] {
self.register_data
}
pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
if data.is_empty() {
return Err(DecodeError::Truncated {
expected: 1,
actual: 0,
});
}
let byte_count = data[0];
let register_data = &data[1..];
if register_data.len() != usize::from(byte_count) {
return Err(DecodeError::ByteCountMismatch {
declared: usize::from(byte_count),
actual: register_data.len(),
});
}
Ok(Self {
byte_count,
register_data,
})
}
}
impl Encode for ReadWriteMultipleRegistersResponse<'_> {
fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
let len = self.encoded_len();
if buf.len() < len {
return Err(EncodeError::BufferTooSmall {
required: len,
available: buf.len(),
});
}
EncodeError::check_byte_count(usize::from(self.byte_count), self.register_data.len())?;
EncodeError::check_pdu_len(len)?;
buf[0] = FunctionCode::ReadWriteMultipleRegisters.code();
buf[1] = self.byte_count;
buf[2..2 + usize::from(self.byte_count)].copy_from_slice(self.register_data);
Ok(len)
}
fn encoded_len(&self) -> usize {
1 + 1 + usize::from(self.byte_count)
}
}