use crate::error::{DecodeError, EncodeError};
use crate::request::Encode;
use rusty_modbus_types::{FunctionCode, MAX_FIFO_VALUES};
#[derive(Debug)]
pub struct ReadFifoQueueResponse<'buf> {
pub byte_count: u16,
pub fifo_count: u16,
pub fifo_values: &'buf [u8],
}
impl<'buf> ReadFifoQueueResponse<'buf> {
pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
if data.len() < 4 {
return Err(DecodeError::Truncated {
expected: 4,
actual: data.len(),
});
}
let byte_count = u16::from_be_bytes([data[0], data[1]]);
let fifo_count = u16::from_be_bytes([data[2], data[3]]);
let fifo_values = &data[4..];
if byte_count < 2 {
return Err(DecodeError::ByteCountMismatch {
declared: usize::from(byte_count),
actual: 2 + fifo_values.len(),
});
}
let expected_remaining = usize::from(byte_count) - 2;
if fifo_values.len() != expected_remaining {
return Err(DecodeError::ByteCountMismatch {
declared: expected_remaining,
actual: fifo_values.len(),
});
}
if fifo_count > 31 {
return Err(DecodeError::QuantityOutOfRange {
quantity: fifo_count,
});
}
let expected_data_len = usize::from(fifo_count) * 2;
if fifo_values.len() != expected_data_len {
return Err(DecodeError::ByteCountMismatch {
declared: expected_data_len,
actual: fifo_values.len(),
});
}
Ok(Self {
byte_count,
fifo_count,
fifo_values,
})
}
}
impl Encode for ReadFifoQueueResponse<'_> {
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), 2 + self.fifo_values.len())?;
if self.fifo_count > MAX_FIFO_VALUES {
return Err(EncodeError::QuantityOutOfRange {
quantity: self.fifo_count,
});
}
let expected_data_len = usize::from(self.fifo_count) * 2;
EncodeError::check_byte_count(expected_data_len, self.fifo_values.len())?;
EncodeError::check_pdu_len(len)?;
buf[0] = FunctionCode::ReadFifoQueue.code();
let bc = self.byte_count.to_be_bytes();
buf[1] = bc[0];
buf[2] = bc[1];
let fc = self.fifo_count.to_be_bytes();
buf[3] = fc[0];
buf[4] = fc[1];
buf[5..5 + self.fifo_values.len()].copy_from_slice(self.fifo_values);
Ok(len)
}
fn encoded_len(&self) -> usize {
1 + 2 + 2 + self.fifo_values.len()
}
}