use crate::error::{DecodeError, EncodeError};
use crate::request::Encode;
use rusty_modbus_types::{Address, CoilValue, FunctionCode, MAX_WRITE_COILS, Quantity};
#[derive(Debug)]
pub struct WriteSingleCoilResponse {
pub address: Address,
pub value: CoilValue,
}
impl WriteSingleCoilResponse {
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 raw_value = u16::from_be_bytes([data[2], data[3]]);
let value =
CoilValue::from_wire(raw_value).ok_or(DecodeError::InvalidCoilValue(raw_value))?;
Ok(Self { address, value })
}
}
impl Encode for WriteSingleCoilResponse {
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::WriteSingleCoil.code();
let addr = self.address.0.to_be_bytes();
buf[1] = addr[0];
buf[2] = addr[1];
let val = self.value.to_wire().to_be_bytes();
buf[3] = val[0];
buf[4] = val[1];
Ok(len)
}
fn encoded_len(&self) -> usize {
1 + 4
}
}
#[derive(Debug)]
pub struct WriteMultipleCoilsResponse {
pub address: Address,
pub quantity: Quantity,
}
impl WriteMultipleCoilsResponse {
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 WriteMultipleCoilsResponse {
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_COILS)?;
EncodeError::check_pdu_len(len)?;
buf[0] = FunctionCode::WriteMultipleCoils.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
}
}