Skip to main content

rusty_modbus_codec/response/
mei.rs

1//! Response type for Encapsulated Interface Transport (FC 2B).
2
3use crate::error::{DecodeError, EncodeError};
4use crate::request::Encode;
5use crate::response::device_id::ReadDeviceIdentificationResponse;
6use rusty_modbus_types::{FunctionCode, MeiType};
7
8/// Response to an Encapsulated Interface Transport request (FC 0x2B).
9#[derive(Debug)]
10pub struct EncapsulatedInterfaceResponse<'buf> {
11    /// The MEI type code.
12    pub mei_type: MeiType,
13    /// MEI-specific data bytes.
14    pub data: &'buf [u8],
15}
16
17impl<'buf> EncapsulatedInterfaceResponse<'buf> {
18    /// Decode from the data bytes following the function code.
19    ///
20    /// # Errors
21    ///
22    /// Returns `DecodeError::Truncated` if `data` is too short.
23    /// Returns `DecodeError::UnknownMeiType` if the MEI type byte is not
24    /// recognized.
25    /// Returns `DecodeError` if a known MEI response payload is malformed.
26    pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
27        if data.is_empty() {
28            return Err(DecodeError::Truncated {
29                expected: 1,
30                actual: 0,
31            });
32        }
33        let mei_type = MeiType::from_raw(data[0]).ok_or(DecodeError::UnknownMeiType(data[0]))?;
34        if mei_type == MeiType::ReadDeviceIdentification {
35            ReadDeviceIdentificationResponse::decode(data)?;
36        }
37        Ok(Self {
38            mei_type,
39            data: &data[1..],
40        })
41    }
42}
43
44impl Encode for EncapsulatedInterfaceResponse<'_> {
45    fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
46        let len = self.encoded_len();
47        if buf.len() < len {
48            return Err(EncodeError::BufferTooSmall {
49                required: len,
50                available: buf.len(),
51            });
52        }
53        EncodeError::check_pdu_len(len)?;
54        buf[0] = FunctionCode::EncapsulatedInterfaceTransport.code();
55        buf[1] = self.mei_type.code();
56        buf[2..2 + self.data.len()].copy_from_slice(self.data);
57        Ok(len)
58    }
59
60    fn encoded_len(&self) -> usize {
61        1 + 1 + self.data.len()
62    }
63}