modbus_core/codec/rtu/
server.rs1use super::*;
3
4pub fn decode_request(buf: &[u8]) -> Result<Option<RequestAdu>> {
6 if buf.is_empty() {
7 return Ok(None);
8 }
9 decode(DecoderType::Request, buf)
10 .and_then(|frame| {
11 let Some((DecodedFrame { slave, pdu }, _frame_pos)) = frame else {
12 return Ok(None);
13 };
14 let hdr = Header { slave };
15 Request::try_from(pdu)
19 .map(RequestPdu)
20 .map(|pdu| Some(RequestAdu { hdr, pdu }))
21 .map_err(|err| {
22 log::error!("Failed to decode request PDU: {err}");
24 err
25 })
26 })
27 .map_err(|_| {
28 unreachable!();
31 })
32}
33
34pub fn encode_response(adu: ResponseAdu, buf: &mut [u8]) -> Result<usize> {
36 let ResponseAdu { hdr, pdu } = adu;
37 if buf.len() < 2 {
38 return Err(Error::BufferSize);
39 }
40 let len = pdu.encode(&mut buf[1..])?;
41 if buf.len() < len + 3 {
42 return Err(Error::BufferSize);
43 }
44 buf[0] = hdr.slave;
45 let crc = crc16(&buf[0..=len]);
46 BigEndian::write_u16(&mut buf[len + 1..], crc);
47 Ok(len + 3)
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn decode_empty_request() {
56 let req = decode_request(&[]).unwrap();
57 assert!(req.is_none());
58 }
59
60 #[test]
61 fn decode_partly_received_request() {
62 let buf = &[
63 0x12, 0x16, ];
66 let req = decode_request(buf).unwrap();
67 assert!(req.is_none());
68 }
69
70 #[test]
71 fn decode_write_single_register_request() {
72 let buf = &[
73 0x12, 0x06, 0x22, 0x22, 0xAB, 0xCD, 0x9F, 0xBE, ];
82 let adu = decode_request(buf).unwrap().unwrap();
83 let RequestAdu { hdr, pdu } = adu;
84 let RequestPdu(pdu) = pdu;
85 assert_eq!(hdr.slave, 0x12);
86 assert_eq!(FunctionCode::from(pdu), FunctionCode::WriteSingleRegister);
87 }
88
89 #[test]
90 fn encode_write_single_register_response() {
91 let adu = ResponseAdu {
92 hdr: Header { slave: 0x12 },
93 pdu: ResponsePdu(Ok(Response::WriteSingleRegister(0x2222, 0xABCD))),
94 };
95 let buf = &mut [0; 100];
96 let len = encode_response(adu, buf).unwrap();
97 assert_eq!(len, 8);
98 assert_eq!(buf[0], 0x12);
99 assert_eq!(buf[1], 0x06);
100 assert_eq!(buf[2], 0x22);
101 assert_eq!(buf[3], 0x22);
102 assert_eq!(buf[4], 0xAB);
103 assert_eq!(buf[5], 0xCD);
104 assert_eq!(buf[6], 0x9F);
105 assert_eq!(buf[7], 0xBE);
106 }
107}