tokio_modbus/codec/
mod.rs

1// SPDX-FileCopyrightText: Copyright (c) 2017-2025 slowtec GmbH <post@slowtec.de>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use std::{
5    convert::TryFrom,
6    io::{self, BufRead as _, Cursor, Error, ErrorKind},
7};
8
9use byteorder::{BigEndian, ReadBytesExt as _};
10
11use crate::{
12    bytes::{Buf as _, Bytes},
13    frame::{Coil, RequestPdu, ResponsePdu},
14    ExceptionCode, ExceptionResponse, FunctionCode, Request, Response,
15};
16
17#[cfg(feature = "rtu")]
18pub(crate) mod rtu;
19
20#[cfg(feature = "tcp")]
21pub(crate) mod tcp;
22
23/// Maximum request/response PDU size.
24///
25/// As defined by the spec for both RTU and TCP.
26const MAX_PDU_SIZE: usize = 253;
27
28#[cfg(any(test, feature = "rtu", feature = "tcp"))]
29#[allow(clippy::cast_possible_truncation)]
30fn u16_len(len: usize) -> u16 {
31    // This type conversion should always be safe, because either
32    // the caller is responsible to pass a valid usize or the
33    // possible values are limited by the protocol.
34    debug_assert!(len <= u16::MAX.into());
35    len as u16
36}
37
38#[cfg(any(test, feature = "rtu", feature = "tcp"))]
39#[allow(clippy::cast_possible_truncation)]
40fn u8_len(len: usize) -> u8 {
41    // This type conversion should always be safe, because either
42    // the caller is responsible to pass a valid usize or the
43    // possible values are limited by the protocol.
44    debug_assert!(len <= u8::MAX.into());
45    len as u8
46}
47
48#[cfg(any(test, feature = "rtu", feature = "tcp"))]
49fn encode_request_pdu(buf: &mut crate::bytes::BytesMut, request: &Request<'_>) {
50    use crate::{bytes::BufMut as _, frame::Request::*};
51    buf.put_u8(request.function_code().value());
52    match request {
53        ReadCoils(address, quantity)
54        | ReadDiscreteInputs(address, quantity)
55        | ReadInputRegisters(address, quantity)
56        | ReadHoldingRegisters(address, quantity) => {
57            buf.put_u16(*address);
58            buf.put_u16(*quantity);
59        }
60        WriteSingleCoil(address, state) => {
61            buf.put_u16(*address);
62            buf.put_u16(bool_to_coil(*state));
63        }
64        WriteMultipleCoils(address, coils) => {
65            buf.put_u16(*address);
66            buf.put_u16(u16_len(coils.len()));
67            buf.put_u8(u8_len(packed_coils_size(coils)));
68            encode_packed_coils(buf, coils);
69        }
70        WriteSingleRegister(address, word) => {
71            buf.put_u16(*address);
72            buf.put_u16(*word);
73        }
74        WriteMultipleRegisters(address, words) => {
75            buf.put_u16(*address);
76            let len = words.len();
77            buf.put_u16(u16_len(len));
78            buf.put_u8(u8_len(len * 2));
79            for w in words.as_ref() {
80                buf.put_u16(*w);
81            }
82        }
83        ReportServerId => {}
84        MaskWriteRegister(address, and_mask, or_mask) => {
85            buf.put_u16(*address);
86            buf.put_u16(*and_mask);
87            buf.put_u16(*or_mask);
88        }
89        ReadWriteMultipleRegisters(read_address, quantity, write_address, words) => {
90            buf.put_u16(*read_address);
91            buf.put_u16(*quantity);
92            buf.put_u16(*write_address);
93            let len = words.len();
94            buf.put_u16(u16_len(len));
95            buf.put_u8(u8_len(len * 2));
96            for w in words.as_ref() {
97                buf.put_u16(*w);
98            }
99        }
100        Custom(_, custom_data) => {
101            buf.put_slice(custom_data.as_ref());
102        }
103    }
104}
105
106#[cfg(any(test, feature = "server"))]
107fn encode_response_pdu(buf: &mut crate::bytes::BytesMut, response: &Response) {
108    use crate::{bytes::BufMut as _, frame::Response::*};
109    buf.put_u8(response.function_code().value());
110    match response {
111        ReadCoils(coils) | ReadDiscreteInputs(coils) => {
112            buf.put_u8(u8_len(packed_coils_size(coils)));
113            encode_packed_coils(buf, coils);
114        }
115        ReadInputRegisters(registers)
116        | ReadHoldingRegisters(registers)
117        | ReadWriteMultipleRegisters(registers) => {
118            buf.put_u8(u8_len(registers.len() * 2));
119            for r in registers {
120                buf.put_u16(*r);
121            }
122        }
123        WriteSingleCoil(address, state) => {
124            buf.put_u16(*address);
125            buf.put_u16(bool_to_coil(*state));
126        }
127        WriteMultipleCoils(address, quantity) | WriteMultipleRegisters(address, quantity) => {
128            buf.put_u16(*address);
129            buf.put_u16(*quantity);
130        }
131        ReportServerId(server_id, run_indication, additional_data) => {
132            buf.put_u8(2 + u8_len(additional_data.len()));
133            buf.put_u8(*server_id);
134            buf.put_u8(if *run_indication { 0xFF } else { 0x00 });
135            buf.put_slice(additional_data);
136        }
137        WriteSingleRegister(address, word) => {
138            buf.put_u16(*address);
139            buf.put_u16(*word);
140        }
141        MaskWriteRegister(address, and_mask, or_mask) => {
142            buf.put_u16(*address);
143            buf.put_u16(*and_mask);
144            buf.put_u16(*or_mask);
145        }
146        Custom(_, custom_data) => {
147            buf.put_slice(custom_data);
148        }
149    }
150}
151
152#[cfg(any(test, feature = "server"))]
153fn encode_exception_response_pdu(buf: &mut crate::bytes::BytesMut, response: ExceptionResponse) {
154    use crate::bytes::BufMut as _;
155    debug_assert!(response.function.value() < 0x80);
156    buf.put_u8(response.function.value() + 0x80);
157    buf.put_u8(response.exception.into());
158}
159
160#[cfg(feature = "server")]
161fn encode_response_result_pdu(
162    buf: &mut crate::bytes::BytesMut,
163    res: &Result<Response, ExceptionResponse>,
164) {
165    match res {
166        Ok(response) => encode_response_pdu(buf, response),
167        Err(response) => encode_exception_response_pdu(buf, *response),
168    }
169}
170
171fn read_u16_be(reader: &mut impl io::Read) -> io::Result<u16> {
172    reader.read_u16::<BigEndian>()
173}
174
175// Only needed for requests with a dynamic payload size.
176fn check_request_pdu_size(pdu_size: usize) -> io::Result<()> {
177    if pdu_size > MAX_PDU_SIZE {
178        return Err(io::Error::new(
179            ErrorKind::InvalidData,
180            "request PDU size exceeded",
181        ));
182    }
183    Ok(())
184}
185
186#[allow(clippy::too_many_lines)] // TODO
187fn decode_request_pdu_bytes(bytes: &Bytes) -> io::Result<Request<'static>> {
188    use crate::frame::Request::*;
189    let pdu_size = bytes.len();
190    let rdr = &mut Cursor::new(&bytes);
191    let fn_code = rdr.read_u8()?;
192    let req = match fn_code {
193        0x01 => ReadCoils(read_u16_be(rdr)?, read_u16_be(rdr)?),
194        0x02 => ReadDiscreteInputs(read_u16_be(rdr)?, read_u16_be(rdr)?),
195        0x05 => WriteSingleCoil(read_u16_be(rdr)?, coil_to_bool(read_u16_be(rdr)?)?),
196        0x0F => {
197            check_request_pdu_size(pdu_size)?;
198            let address = read_u16_be(rdr)?;
199            let quantity = read_u16_be(rdr)?;
200            let byte_count = usize::from(rdr.read_u8()?);
201            if bytes.len() < 6 + byte_count {
202                return Err(io::Error::new(ErrorKind::InvalidData, "too short"));
203            }
204            rdr.consume(byte_count);
205            let packed_coils = &bytes[6..6 + byte_count];
206            WriteMultipleCoils(address, decode_packed_coils(packed_coils, quantity).into())
207        }
208        0x04 => ReadInputRegisters(read_u16_be(rdr)?, read_u16_be(rdr)?),
209        0x03 => ReadHoldingRegisters(read_u16_be(rdr)?, read_u16_be(rdr)?),
210        0x06 => WriteSingleRegister(read_u16_be(rdr)?, read_u16_be(rdr)?),
211        0x10 => {
212            check_request_pdu_size(pdu_size)?;
213            let address = read_u16_be(rdr)?;
214            let quantity = read_u16_be(rdr)?;
215            let byte_count = rdr.read_u8()?;
216            if u16::from(byte_count) != quantity * 2 {
217                return Err(io::Error::new(ErrorKind::InvalidData, "invalid quantity"));
218            }
219            let mut data = Vec::with_capacity(quantity.into());
220            for _ in 0..quantity {
221                data.push(read_u16_be(rdr)?);
222            }
223            WriteMultipleRegisters(address, data.into())
224        }
225        0x11 => ReportServerId,
226        0x16 => {
227            let address = read_u16_be(rdr)?;
228            let and_mask = read_u16_be(rdr)?;
229            let or_mask = read_u16_be(rdr)?;
230            MaskWriteRegister(address, and_mask, or_mask)
231        }
232        0x17 => {
233            check_request_pdu_size(pdu_size)?;
234            let read_address = read_u16_be(rdr)?;
235            let read_quantity = read_u16_be(rdr)?;
236            let write_address = read_u16_be(rdr)?;
237            let write_quantity = read_u16_be(rdr)?;
238            let write_count = rdr.read_u8()?;
239            if u16::from(write_count) != write_quantity * 2 {
240                return Err(io::Error::new(
241                    ErrorKind::InvalidData,
242                    "invalid write quantity",
243                ));
244            }
245            let mut data = Vec::with_capacity(write_quantity.into());
246            for _ in 0..write_quantity {
247                data.push(read_u16_be(rdr)?);
248            }
249            ReadWriteMultipleRegisters(read_address, read_quantity, write_address, data.into())
250        }
251        fn_code if fn_code < 0x80 => {
252            // Consume all remaining bytes as custom data.
253            return Ok(Custom(fn_code, bytes[1..].to_vec().into()));
254        }
255        fn_code => {
256            return Err(Error::new(
257                ErrorKind::InvalidData,
258                format!("invalid function code: 0x{fn_code:02X}"),
259            ));
260        }
261    };
262    // Verify that all data has been consumed and decoded.
263    if rdr.has_remaining() {
264        return Err(io::Error::new(
265            io::ErrorKind::InvalidData,
266            "undecoded request data",
267        ));
268    }
269    Ok(req)
270}
271
272impl TryFrom<Bytes> for Request<'static> {
273    type Error = Error;
274
275    fn try_from(pdu_bytes: Bytes) -> Result<Self, Self::Error> {
276        decode_request_pdu_bytes(&pdu_bytes)
277    }
278}
279
280impl TryFrom<Bytes> for RequestPdu<'static> {
281    type Error = Error;
282
283    fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
284        let pdu = Request::try_from(bytes)?.into();
285        Ok(pdu)
286    }
287}
288
289// Only needed for responses with a dynamic payload size.
290fn check_response_pdu_size(pdu_size: usize) -> io::Result<()> {
291    if pdu_size > MAX_PDU_SIZE {
292        return Err(io::Error::new(
293            ErrorKind::InvalidInput,
294            "response PDU size exceeded",
295        ));
296    }
297    Ok(())
298}
299
300#[allow(clippy::too_many_lines)] // TODO
301fn decode_response_pdu_bytes(bytes: Bytes) -> io::Result<Response> {
302    use crate::frame::Response::*;
303    let pdu_size = bytes.len();
304    let rdr = &mut Cursor::new(&bytes);
305    let fn_code = rdr.read_u8()?;
306    let response = match fn_code {
307        0x01 => {
308            check_response_pdu_size(pdu_size)?;
309            let byte_count = rdr.read_u8()?;
310            if bytes.len() < 2 + usize::from(byte_count) {
311                return Err(io::Error::new(ErrorKind::InvalidData, "too short"));
312            }
313            let packed_coils = &bytes[2..2 + usize::from(byte_count)];
314            rdr.consume(byte_count.into());
315            // Here we have no information about the exact requested quantity so we just
316            // unpack the whole byte.
317            let quantity = u16::from(byte_count) * 8;
318            ReadCoils(decode_packed_coils(packed_coils, quantity))
319        }
320        0x02 => {
321            check_response_pdu_size(pdu_size)?;
322            let byte_count = rdr.read_u8()?;
323            if bytes.len() < 2 + usize::from(byte_count) {
324                return Err(io::Error::new(ErrorKind::InvalidData, "too short"));
325            }
326            let packed_coils = &bytes[2..2 + usize::from(byte_count)];
327            rdr.consume(byte_count.into());
328            // Here we have no information about the exact requested quantity so we just
329            // unpack the whole byte.
330            let quantity = u16::from(byte_count) * 8;
331            ReadDiscreteInputs(decode_packed_coils(packed_coils, quantity))
332        }
333        0x05 => WriteSingleCoil(read_u16_be(rdr)?, coil_to_bool(read_u16_be(rdr)?)?),
334        0x0F => WriteMultipleCoils(read_u16_be(rdr)?, read_u16_be(rdr)?),
335        0x04 => {
336            check_response_pdu_size(pdu_size)?;
337            let byte_count = rdr.read_u8()?;
338            if byte_count % 2 != 0 {
339                return Err(io::Error::new(
340                    io::ErrorKind::InvalidData,
341                    "invalid quantity",
342                ));
343            }
344            let quantity = byte_count / 2;
345            let mut data = Vec::with_capacity(quantity.into());
346            for _ in 0..quantity {
347                data.push(read_u16_be(rdr)?);
348            }
349            ReadInputRegisters(data)
350        }
351        0x03 => {
352            check_response_pdu_size(pdu_size)?;
353            let byte_count = rdr.read_u8()?;
354            if byte_count % 2 != 0 {
355                return Err(io::Error::new(
356                    io::ErrorKind::InvalidData,
357                    "invalid quantity",
358                ));
359            }
360            let quantity = byte_count / 2;
361            let mut data = Vec::with_capacity(quantity.into());
362            for _ in 0..quantity {
363                data.push(read_u16_be(rdr)?);
364            }
365            ReadHoldingRegisters(data)
366        }
367        0x06 => WriteSingleRegister(read_u16_be(rdr)?, read_u16_be(rdr)?),
368        0x10 => WriteMultipleRegisters(read_u16_be(rdr)?, read_u16_be(rdr)?),
369        0x11 => {
370            check_response_pdu_size(pdu_size)?;
371            let byte_count = rdr.read_u8()?;
372            if byte_count < 2 {
373                return Err(io::Error::new(io::ErrorKind::InvalidData, "too short"));
374            }
375            let data_len = (byte_count - 2).into();
376            let server_id = rdr.read_u8()?;
377            let run_indication_status = match rdr.read_u8()? {
378                0x00 => false,
379                0xFF => true,
380                status => {
381                    return Err(Error::new(
382                        ErrorKind::InvalidData,
383                        format!("invalid run indication status: 0x{status:02X}"),
384                    ));
385                }
386            };
387            let mut data = Vec::with_capacity(data_len);
388            for _ in 0..data_len {
389                data.push(rdr.read_u8()?);
390            }
391            ReportServerId(server_id, run_indication_status, data)
392        }
393        0x16 => {
394            let address = read_u16_be(rdr)?;
395            let and_mask = read_u16_be(rdr)?;
396            let or_mask = read_u16_be(rdr)?;
397            MaskWriteRegister(address, and_mask, or_mask)
398        }
399        0x17 => {
400            check_response_pdu_size(pdu_size)?;
401            let byte_count = rdr.read_u8()?;
402            if byte_count % 2 != 0 {
403                return Err(io::Error::new(
404                    io::ErrorKind::InvalidData,
405                    "invalid quantity",
406                ));
407            }
408            let quantity = byte_count / 2;
409            let mut data = Vec::with_capacity(quantity.into());
410            for _ in 0..quantity {
411                data.push(read_u16_be(rdr)?);
412            }
413            ReadWriteMultipleRegisters(data)
414        }
415        _ => {
416            // Consume all remaining bytes as custom data.
417            let mut bytes = bytes;
418            return Ok(Custom(fn_code, bytes.split_off(1)));
419        }
420    };
421    // Verify that all data has been consumed and decoded.
422    if rdr.has_remaining() {
423        return Err(io::Error::new(
424            io::ErrorKind::InvalidData,
425            "undecoded response data",
426        ));
427    }
428    Ok(response)
429}
430
431impl TryFrom<Bytes> for Response {
432    type Error = Error;
433
434    fn try_from(pdu_bytes: Bytes) -> Result<Self, Self::Error> {
435        decode_response_pdu_bytes(pdu_bytes)
436    }
437}
438
439impl TryFrom<Bytes> for ExceptionResponse {
440    type Error = Error;
441
442    fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
443        let mut rdr = Cursor::new(&bytes);
444        let fn_err_code = rdr.read_u8()?;
445        if fn_err_code < 0x80 {
446            return Err(Error::new(
447                ErrorKind::InvalidData,
448                "Invalid exception function code",
449            ));
450        }
451        let function = fn_err_code - 0x80;
452        let exception = ExceptionCode::new(rdr.read_u8()?);
453        Ok(ExceptionResponse {
454            function: FunctionCode::new(function),
455            exception,
456        })
457    }
458}
459
460impl TryFrom<Bytes> for ResponsePdu {
461    type Error = Error;
462
463    fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
464        let fn_code = Cursor::new(&bytes).read_u8()?;
465        let pdu = if fn_code < 0x80 {
466            Response::try_from(bytes)?.into()
467        } else {
468            ExceptionResponse::try_from(bytes)?.into()
469        };
470        Ok(pdu)
471    }
472}
473
474#[cfg(any(test, feature = "rtu", feature = "tcp"))]
475fn bool_to_coil(state: bool) -> u16 {
476    if state {
477        0xFF00
478    } else {
479        0x0000
480    }
481}
482
483fn coil_to_bool(coil: u16) -> io::Result<bool> {
484    match coil {
485        0xFF00 => Ok(true),
486        0x0000 => Ok(false),
487        _ => Err(Error::new(ErrorKind::InvalidData, "Invalid coil value: {}")),
488    }
489}
490
491#[cfg(any(test, feature = "rtu", feature = "tcp"))]
492fn packed_coils_size(coils: &[Coil]) -> usize {
493    coils.len().div_ceil(8)
494}
495
496#[cfg(any(test, feature = "rtu", feature = "tcp"))]
497fn encode_packed_coils(buf: &mut crate::bytes::BytesMut, coils: &[Coil]) -> usize {
498    let packed_coils_size = packed_coils_size(coils);
499    let offset = buf.len();
500    buf.resize(offset + packed_coils_size, 0);
501    let buf = &mut buf[offset..];
502    for (i, b) in coils.iter().enumerate() {
503        let v = u8::from(*b); // 0 or 1
504        buf[i / 8] |= v << (i % 8);
505    }
506    packed_coils_size
507}
508
509fn decode_packed_coils(bytes: &[u8], count: u16) -> Vec<Coil> {
510    let mut res = Vec::with_capacity(count.into());
511    for i in 0usize..count.into() {
512        res.push((bytes[i / 8] >> (i % 8)) & 0b1 > 0);
513    }
514    res
515}
516
517#[cfg(any(feature = "rtu", feature = "tcp"))]
518fn request_pdu_size(request: &Request<'_>) -> io::Result<usize> {
519    use crate::frame::Request::*;
520    let size = match request {
521        ReadCoils(_, _)
522        | ReadDiscreteInputs(_, _)
523        | ReadInputRegisters(_, _)
524        | ReadHoldingRegisters(_, _)
525        | WriteSingleRegister(_, _)
526        | WriteSingleCoil(_, _) => 5,
527        WriteMultipleCoils(_, coils) => 6 + packed_coils_size(coils),
528        WriteMultipleRegisters(_, data) => 6 + data.len() * 2,
529        ReportServerId => 1,
530        MaskWriteRegister(_, _, _) => 7,
531        ReadWriteMultipleRegisters(_, _, _, data) => 10 + data.len() * 2,
532        Custom(_, data) => 1 + data.len(),
533    };
534    if size > MAX_PDU_SIZE {
535        return Err(io::Error::new(
536            ErrorKind::InvalidInput,
537            "request PDU size exceeded",
538        ));
539    }
540    Ok(size)
541}
542
543#[cfg(feature = "server")]
544fn response_pdu_size(response: &Response) -> io::Result<usize> {
545    use crate::frame::Response::*;
546    let size = match response {
547        ReadCoils(coils) | ReadDiscreteInputs(coils) => 2 + packed_coils_size(coils),
548        WriteSingleCoil(_, _)
549        | WriteMultipleCoils(_, _)
550        | WriteMultipleRegisters(_, _)
551        | WriteSingleRegister(_, _) => 5,
552        ReadInputRegisters(data)
553        | ReadHoldingRegisters(data)
554        | ReadWriteMultipleRegisters(data) => 2 + data.len() * 2,
555        ReportServerId(_, _, data) => 3 + data.len(),
556        MaskWriteRegister(_, _, _) => 7,
557        Custom(_, data) => 1 + data.len(),
558    };
559    if size > MAX_PDU_SIZE {
560        return Err(io::Error::new(
561            ErrorKind::InvalidInput,
562            "response PDU size exceeded",
563        ));
564    }
565    Ok(size)
566}
567
568#[cfg(feature = "server")]
569fn response_result_pdu_size(res: &Result<Response, ExceptionResponse>) -> io::Result<usize> {
570    match res {
571        Ok(response) => response_pdu_size(response),
572        Err(_) => Ok(2),
573    }
574}
575
576#[cfg(test)]
577mod tests {
578
579    use std::borrow::Cow;
580
581    use crate::bytes::BytesMut;
582
583    use super::*;
584
585    fn encode_request_pdu_to_bytes(request: &Request<'_>) -> Bytes {
586        let mut buf = BytesMut::new();
587        encode_request_pdu(&mut buf, request);
588        buf.freeze()
589    }
590
591    fn encode_response_pdu_to_bytes(response: &Response) -> Bytes {
592        let mut buf = BytesMut::new();
593        encode_response_pdu(&mut buf, response);
594        buf.freeze()
595    }
596
597    fn encode_exception_response_pdu_to_bytes(response: ExceptionResponse) -> Bytes {
598        let mut buf = BytesMut::new();
599        encode_exception_response_pdu(&mut buf, response);
600        buf.freeze()
601    }
602
603    fn encode_packed_coils_to_bytes(coils: &[Coil]) -> Bytes {
604        let mut buf = BytesMut::new();
605        encode_packed_coils(&mut buf, coils);
606        buf.freeze()
607    }
608
609    #[test]
610    fn convert_bool_to_coil() {
611        assert_eq!(bool_to_coil(true), 0xFF00);
612        assert_eq!(bool_to_coil(false), 0x0000);
613    }
614
615    #[test]
616    fn convert_coil_to_bool() {
617        assert!(coil_to_bool(0xFF00).unwrap());
618        assert!(!coil_to_bool(0x0000).unwrap());
619    }
620
621    #[test]
622    fn convert_booleans_to_bytes() {
623        assert_eq!(&encode_packed_coils_to_bytes(&[])[..], &[]);
624        assert_eq!(&encode_packed_coils_to_bytes(&[true])[..], &[0b1]);
625        assert_eq!(&encode_packed_coils_to_bytes(&[false])[..], &[0b0]);
626        assert_eq!(&encode_packed_coils_to_bytes(&[true, false])[..], &[0b_01]);
627        assert_eq!(&encode_packed_coils_to_bytes(&[false, true])[..], &[0b_10]);
628        assert_eq!(&encode_packed_coils_to_bytes(&[true, true])[..], &[0b_11]);
629        assert_eq!(
630            &encode_packed_coils_to_bytes(&[true; 8])[..],
631            &[0b_1111_1111]
632        );
633        assert_eq!(&encode_packed_coils_to_bytes(&[true; 9])[..], &[255, 1]);
634        assert_eq!(&encode_packed_coils_to_bytes(&[false; 8])[..], &[0]);
635        assert_eq!(&encode_packed_coils_to_bytes(&[false; 9])[..], &[0, 0]);
636    }
637
638    #[test]
639    fn test_unpack_bits() {
640        assert_eq!(decode_packed_coils(&[], 0), &[]);
641        assert_eq!(decode_packed_coils(&[0, 0], 0), &[]);
642        assert_eq!(decode_packed_coils(&[0b1], 1), &[true]);
643        assert_eq!(decode_packed_coils(&[0b01], 2), &[true, false]);
644        assert_eq!(decode_packed_coils(&[0b10], 2), &[false, true]);
645        assert_eq!(decode_packed_coils(&[0b101], 3), &[true, false, true]);
646        assert_eq!(decode_packed_coils(&[0xff, 0b11], 10), &[true; 10]);
647    }
648
649    #[test]
650    fn exception_response_into_bytes() {
651        let bytes = encode_exception_response_pdu_to_bytes(ExceptionResponse {
652            function: FunctionCode::ReadHoldingRegisters,
653            exception: ExceptionCode::IllegalDataAddress,
654        });
655        assert_eq!(bytes[0], 0x83);
656        assert_eq!(bytes[1], 0x02);
657    }
658
659    #[test]
660    fn exception_response_from_bytes() {
661        assert!(ExceptionResponse::try_from(Bytes::from(vec![0x79, 0x02])).is_err());
662
663        let bytes = Bytes::from(vec![0x83, 0x02]);
664        let response = ExceptionResponse::try_from(bytes).unwrap();
665        assert_eq!(
666            response,
667            ExceptionResponse {
668                function: FunctionCode::ReadHoldingRegisters,
669                exception: ExceptionCode::IllegalDataAddress,
670            }
671        );
672    }
673
674    #[test]
675    fn pdu_into_bytes() {
676        let req_pdu = encode_request_pdu_to_bytes(&Request::ReadCoils(0x01, 5));
677        let response_pdu = encode_response_pdu_to_bytes(&Response::ReadCoils(vec![]));
678        let ex_pdu = encode_exception_response_pdu_to_bytes(ExceptionResponse {
679            function: FunctionCode::ReadHoldingRegisters,
680            exception: ExceptionCode::ServerDeviceFailure,
681        });
682
683        assert_eq!(req_pdu[0], 0x01);
684        assert_eq!(req_pdu[1], 0x00);
685        assert_eq!(req_pdu[2], 0x01);
686        assert_eq!(req_pdu[3], 0x00);
687        assert_eq!(req_pdu[4], 0x05);
688
689        assert_eq!(response_pdu[0], 0x01);
690        assert_eq!(response_pdu[1], 0x00);
691
692        assert_eq!(ex_pdu[0], 0x83);
693        assert_eq!(ex_pdu[1], 0x04);
694
695        let req_pdu = encode_request_pdu_to_bytes(&Request::ReadHoldingRegisters(0x082B, 2));
696        assert_eq!(req_pdu.len(), 5);
697        assert_eq!(req_pdu[0], 0x03);
698        assert_eq!(req_pdu[1], 0x08);
699        assert_eq!(req_pdu[2], 0x2B);
700        assert_eq!(req_pdu[3], 0x00);
701        assert_eq!(req_pdu[4], 0x02);
702    }
703
704    #[test]
705    fn pdu_with_a_lot_of_data_into_bytes() {
706        let _req_pdu = encode_request_pdu_to_bytes(&Request::WriteMultipleRegisters(
707            0x01,
708            Cow::Borrowed(&[0; 80]),
709        ));
710        let _response_pdu =
711            encode_response_pdu_to_bytes(&Response::ReadInputRegisters(vec![0; 80]));
712    }
713
714    mod serialize_requests {
715
716        use super::*;
717
718        #[test]
719        fn read_coils() {
720            let bytes = encode_request_pdu_to_bytes(&Request::ReadCoils(0x12, 4));
721            assert_eq!(bytes[0], 1);
722            assert_eq!(bytes[1], 0x00);
723            assert_eq!(bytes[2], 0x12);
724            assert_eq!(bytes[3], 0x00);
725            assert_eq!(bytes[4], 0x04);
726        }
727
728        #[test]
729        fn read_discrete_inputs() {
730            let bytes = encode_request_pdu_to_bytes(&Request::ReadDiscreteInputs(0x03, 19));
731            assert_eq!(bytes[0], 2);
732            assert_eq!(bytes[1], 0x00);
733            assert_eq!(bytes[2], 0x03);
734            assert_eq!(bytes[3], 0x00);
735            assert_eq!(bytes[4], 19);
736        }
737
738        #[test]
739        fn write_single_coil() {
740            let bytes = encode_request_pdu_to_bytes(&Request::WriteSingleCoil(0x1234, true));
741            assert_eq!(bytes[0], 5);
742            assert_eq!(bytes[1], 0x12);
743            assert_eq!(bytes[2], 0x34);
744            assert_eq!(bytes[3], 0xFF);
745            assert_eq!(bytes[4], 0x00);
746        }
747
748        #[test]
749        fn write_multiple_coils() {
750            let states = [true, false, true, true];
751            let bytes = encode_request_pdu_to_bytes(&Request::WriteMultipleCoils(
752                0x3311,
753                Cow::Borrowed(&states),
754            ));
755            assert_eq!(bytes[0], 0x0F);
756            assert_eq!(bytes[1], 0x33);
757            assert_eq!(bytes[2], 0x11);
758            assert_eq!(bytes[3], 0x00);
759            assert_eq!(bytes[4], 0x04);
760            assert_eq!(bytes[5], 0x01);
761            assert_eq!(bytes[6], 0b_0000_1101);
762        }
763
764        #[test]
765        fn read_input_registers() {
766            let bytes = encode_request_pdu_to_bytes(&Request::ReadInputRegisters(0x09, 77));
767            assert_eq!(bytes[0], 4);
768            assert_eq!(bytes[1], 0x00);
769            assert_eq!(bytes[2], 0x09);
770            assert_eq!(bytes[3], 0x00);
771            assert_eq!(bytes[4], 0x4D);
772        }
773
774        #[test]
775        fn read_holding_registers() {
776            let bytes = encode_request_pdu_to_bytes(&Request::ReadHoldingRegisters(0x09, 77));
777            assert_eq!(bytes[0], 3);
778            assert_eq!(bytes[1], 0x00);
779            assert_eq!(bytes[2], 0x09);
780            assert_eq!(bytes[3], 0x00);
781            assert_eq!(bytes[4], 0x4D);
782        }
783
784        #[test]
785        fn write_single_register() {
786            let bytes = encode_request_pdu_to_bytes(&Request::WriteSingleRegister(0x07, 0xABCD));
787            assert_eq!(bytes[0], 6);
788            assert_eq!(bytes[1], 0x00);
789            assert_eq!(bytes[2], 0x07);
790            assert_eq!(bytes[3], 0xAB);
791            assert_eq!(bytes[4], 0xCD);
792        }
793
794        #[test]
795        fn write_multiple_registers() {
796            let bytes = encode_request_pdu_to_bytes(&Request::WriteMultipleRegisters(
797                0x06,
798                Cow::Borrowed(&[0xABCD, 0xEF12]),
799            ));
800
801            // function code
802            assert_eq!(bytes[0], 0x10);
803
804            // write starting address
805            assert_eq!(bytes[1], 0x00);
806            assert_eq!(bytes[2], 0x06);
807
808            // quantity to write
809            assert_eq!(bytes[3], 0x00);
810            assert_eq!(bytes[4], 0x02);
811
812            // write byte count
813            assert_eq!(bytes[5], 0x04);
814
815            // values
816            assert_eq!(bytes[6], 0xAB);
817            assert_eq!(bytes[7], 0xCD);
818            assert_eq!(bytes[8], 0xEF);
819            assert_eq!(bytes[9], 0x12);
820        }
821
822        #[test]
823        fn report_server_id() {
824            let bytes = encode_request_pdu_to_bytes(&Request::ReportServerId);
825            assert_eq!(bytes[0], 0x11);
826        }
827
828        #[test]
829        fn masked_write_register() {
830            let bytes =
831                encode_request_pdu_to_bytes(&Request::MaskWriteRegister(0xABCD, 0xEF12, 0x2345));
832
833            // function code
834            assert_eq!(bytes[0], 0x16);
835
836            // address
837            assert_eq!(bytes[1], 0xAB);
838            assert_eq!(bytes[2], 0xCD);
839
840            // and mask
841            assert_eq!(bytes[3], 0xEF);
842            assert_eq!(bytes[4], 0x12);
843
844            // or mask
845            assert_eq!(bytes[5], 0x23);
846            assert_eq!(bytes[6], 0x45);
847        }
848
849        #[test]
850        fn read_write_multiple_registers() {
851            let data = [0xABCD, 0xEF12];
852            let bytes = encode_request_pdu_to_bytes(&Request::ReadWriteMultipleRegisters(
853                0x05,
854                51,
855                0x03,
856                Cow::Borrowed(&data),
857            ));
858
859            // function code
860            assert_eq!(bytes[0], 0x17);
861
862            // read starting address
863            assert_eq!(bytes[1], 0x00);
864            assert_eq!(bytes[2], 0x05);
865
866            // quantity to read
867            assert_eq!(bytes[3], 0x00);
868            assert_eq!(bytes[4], 0x33);
869
870            // write starting address
871            assert_eq!(bytes[5], 0x00);
872            assert_eq!(bytes[6], 0x03);
873
874            // quantity to write
875            assert_eq!(bytes[7], 0x00);
876            assert_eq!(bytes[8], 0x02);
877
878            // write byte count
879            assert_eq!(bytes[9], 0x04);
880
881            // values
882            assert_eq!(bytes[10], 0xAB);
883            assert_eq!(bytes[11], 0xCD);
884            assert_eq!(bytes[12], 0xEF);
885            assert_eq!(bytes[13], 0x12);
886        }
887
888        #[test]
889        fn custom() {
890            let bytes = encode_request_pdu_to_bytes(&Request::Custom(
891                0x55,
892                Cow::Borrowed(&[0xCC, 0x88, 0xAA, 0xFF]),
893            ));
894            assert_eq!(bytes[0], 0x55);
895            assert_eq!(bytes[1], 0xCC);
896            assert_eq!(bytes[2], 0x88);
897            assert_eq!(bytes[3], 0xAA);
898            assert_eq!(bytes[4], 0xFF);
899        }
900    }
901
902    mod deserialize_requests {
903
904        use super::*;
905
906        #[test]
907        fn empty_request() {
908            assert!(Request::try_from(Bytes::from(vec![])).is_err());
909        }
910
911        #[test]
912        fn read_coils() {
913            assert!(Request::try_from(Bytes::from(vec![0x01])).is_err());
914            assert!(Request::try_from(Bytes::from(vec![0x01, 0x0, 0x0, 0x22])).is_err());
915
916            let bytes = Bytes::from(vec![0x01, 0x00, 0x12, 0x0, 0x4]);
917            let req = Request::try_from(bytes).unwrap();
918            assert_eq!(req, Request::ReadCoils(0x12, 4));
919        }
920
921        #[test]
922        fn read_discrete_inputs() {
923            let bytes = Bytes::from(vec![2, 0x00, 0x03, 0x00, 19]);
924            let req = Request::try_from(bytes).unwrap();
925            assert_eq!(req, Request::ReadDiscreteInputs(0x03, 19));
926        }
927
928        #[test]
929        fn write_single_coil() {
930            let bytes = Bytes::from(vec![5, 0x12, 0x34, 0xFF, 0x00]);
931            let req = Request::try_from(bytes).unwrap();
932            assert_eq!(req, Request::WriteSingleCoil(0x1234, true));
933        }
934
935        #[test]
936        fn write_multiple_coils() {
937            assert!(Request::try_from(Bytes::from(vec![
938                0x0F,
939                0x33,
940                0x11,
941                0x00,
942                0x04,
943                0x02,
944                0b_0000_1101,
945            ]))
946            .is_err());
947
948            let bytes = Bytes::from(vec![0x0F, 0x33, 0x11, 0x00, 0x04, 0x01, 0b_0000_1101]);
949            let req = Request::try_from(bytes).unwrap();
950            assert_eq!(
951                req,
952                Request::WriteMultipleCoils(0x3311, Cow::Borrowed(&[true, false, true, true]))
953            );
954        }
955
956        #[test]
957        fn read_input_registers() {
958            let bytes = Bytes::from(vec![4, 0x00, 0x09, 0x00, 0x4D]);
959            let req = Request::try_from(bytes).unwrap();
960            assert_eq!(req, Request::ReadInputRegisters(0x09, 77));
961        }
962
963        #[test]
964        fn read_holding_registers() {
965            let bytes = Bytes::from(vec![3, 0x00, 0x09, 0x00, 0x4D]);
966            let req = Request::try_from(bytes).unwrap();
967            assert_eq!(req, Request::ReadHoldingRegisters(0x09, 77));
968        }
969
970        #[test]
971        fn write_single_register() {
972            let bytes = Bytes::from(vec![6, 0x00, 0x07, 0xAB, 0xCD]);
973            let req = Request::try_from(bytes).unwrap();
974            assert_eq!(req, Request::WriteSingleRegister(0x07, 0xABCD));
975        }
976
977        #[test]
978        fn write_multiple_registers() {
979            assert!(Request::try_from(Bytes::from(vec![
980                0x10, 0x00, 0x06, 0x00, 0x02, 0x05, 0xAB, 0xCD, 0xEF, 0x12,
981            ]))
982            .is_err());
983
984            let bytes = Bytes::from(vec![
985                0x10, 0x00, 0x06, 0x00, 0x02, 0x04, 0xAB, 0xCD, 0xEF, 0x12,
986            ]);
987            let req = Request::try_from(bytes).unwrap();
988            assert_eq!(
989                req,
990                Request::WriteMultipleRegisters(0x06, Cow::Borrowed(&[0xABCD, 0xEF12]))
991            );
992        }
993
994        #[test]
995        fn report_server_id() {
996            let bytes = Bytes::from(vec![0x11]);
997            let req = Request::try_from(bytes).unwrap();
998            assert_eq!(req, Request::ReportServerId);
999        }
1000
1001        #[test]
1002        fn masked_write_register() {
1003            let bytes = Bytes::from(vec![0x16, 0xAB, 0xCD, 0xEF, 0x12, 0x23, 0x45]);
1004            let req = Request::try_from(bytes).unwrap();
1005            assert_eq!(req, Request::MaskWriteRegister(0xABCD, 0xEF12, 0x2345));
1006        }
1007
1008        #[test]
1009        fn read_write_multiple_registers() {
1010            assert!(Request::try_from(Bytes::from(vec![
1011                0x17, 0x00, 0x05, 0x00, 0x33, 0x00, 0x03, 0x00, 0x02, 0x05, 0xAB, 0xCD, 0xEF, 0x12,
1012            ]))
1013            .is_err());
1014            let bytes = Bytes::from(vec![
1015                0x17, 0x00, 0x05, 0x00, 0x33, 0x00, 0x03, 0x00, 0x02, 0x04, 0xAB, 0xCD, 0xEF, 0x12,
1016            ]);
1017            let req = Request::try_from(bytes).unwrap();
1018            let data = [0xABCD, 0xEF12];
1019            assert_eq!(
1020                req,
1021                Request::ReadWriteMultipleRegisters(0x05, 51, 0x03, Cow::Borrowed(&data))
1022            );
1023        }
1024
1025        #[test]
1026        fn custom() {
1027            let bytes = Bytes::from(vec![0x55, 0xCC, 0x88, 0xAA, 0xFF]);
1028            let req = Request::try_from(bytes).unwrap();
1029            assert_eq!(
1030                req,
1031                Request::Custom(0x55, Cow::Borrowed(&[0xCC, 0x88, 0xAA, 0xFF]))
1032            );
1033        }
1034    }
1035
1036    mod serialize_responses {
1037
1038        use super::*;
1039
1040        #[test]
1041        fn read_coils() {
1042            let bytes = encode_response_pdu_to_bytes(&Response::ReadCoils(vec![
1043                true, false, false, true, false,
1044            ]));
1045            assert_eq!(bytes[0], 1);
1046            assert_eq!(bytes[1], 1);
1047            assert_eq!(bytes[2], 0b_0000_1001);
1048        }
1049
1050        #[test]
1051        fn read_discrete_inputs() {
1052            let bytes = encode_response_pdu_to_bytes(&Response::ReadDiscreteInputs(vec![
1053                true, false, true, true,
1054            ]));
1055            assert_eq!(bytes[0], 2);
1056            assert_eq!(bytes[1], 1);
1057            assert_eq!(bytes[2], 0b_0000_1101);
1058        }
1059
1060        #[test]
1061        fn write_single_coil() {
1062            let bytes = encode_response_pdu_to_bytes(&Response::WriteSingleCoil(0x33, true));
1063            assert_eq!(bytes[0], 5);
1064            assert_eq!(bytes[1], 0x00);
1065            assert_eq!(bytes[2], 0x33);
1066            assert_eq!(bytes[3], 0xFF);
1067            assert_eq!(bytes[4], 0x00);
1068        }
1069
1070        #[test]
1071        fn write_multiple_coils() {
1072            let bytes = encode_response_pdu_to_bytes(&Response::WriteMultipleCoils(0x3311, 5));
1073            assert_eq!(bytes[0], 0x0F);
1074            assert_eq!(bytes[1], 0x33);
1075            assert_eq!(bytes[2], 0x11);
1076            assert_eq!(bytes[3], 0x00);
1077            assert_eq!(bytes[4], 0x05);
1078        }
1079
1080        #[test]
1081        fn read_input_registers() {
1082            let bytes = encode_response_pdu_to_bytes(&Response::ReadInputRegisters(vec![
1083                0xAA00, 0xCCBB, 0xEEDD,
1084            ]));
1085            assert_eq!(bytes[0], 4);
1086            assert_eq!(bytes[1], 0x06);
1087            assert_eq!(bytes[2], 0xAA);
1088            assert_eq!(bytes[3], 0x00);
1089            assert_eq!(bytes[4], 0xCC);
1090            assert_eq!(bytes[5], 0xBB);
1091            assert_eq!(bytes[6], 0xEE);
1092            assert_eq!(bytes[7], 0xDD);
1093        }
1094
1095        #[test]
1096        fn read_holding_registers() {
1097            let bytes =
1098                encode_response_pdu_to_bytes(&Response::ReadHoldingRegisters(vec![0xAA00, 0x1111]));
1099            assert_eq!(bytes[0], 3);
1100            assert_eq!(bytes[1], 0x04);
1101            assert_eq!(bytes[2], 0xAA);
1102            assert_eq!(bytes[3], 0x00);
1103            assert_eq!(bytes[4], 0x11);
1104            assert_eq!(bytes[5], 0x11);
1105        }
1106
1107        #[test]
1108        fn write_single_register() {
1109            let bytes = encode_response_pdu_to_bytes(&Response::WriteSingleRegister(0x07, 0xABCD));
1110            assert_eq!(bytes[0], 6);
1111            assert_eq!(bytes[1], 0x00);
1112            assert_eq!(bytes[2], 0x07);
1113            assert_eq!(bytes[3], 0xAB);
1114            assert_eq!(bytes[4], 0xCD);
1115        }
1116
1117        #[test]
1118        fn write_multiple_registers() {
1119            let bytes = encode_response_pdu_to_bytes(&Response::WriteMultipleRegisters(0x06, 2));
1120            assert_eq!(bytes[0], 0x10);
1121            assert_eq!(bytes[1], 0x00);
1122            assert_eq!(bytes[2], 0x06);
1123            assert_eq!(bytes[3], 0x00);
1124            assert_eq!(bytes[4], 0x02);
1125        }
1126
1127        #[test]
1128        fn report_server_id() {
1129            let bytes = encode_response_pdu_to_bytes(&Response::ReportServerId(
1130                0x42,
1131                true,
1132                vec![0x10, 0x20],
1133            ));
1134            assert_eq!(bytes[0], 0x11);
1135            assert_eq!(bytes[1], 0x04);
1136            assert_eq!(bytes[2], 0x42);
1137            assert_eq!(bytes[3], 0xFF);
1138            assert_eq!(bytes[4], 0x10);
1139            assert_eq!(bytes[5], 0x20);
1140        }
1141
1142        #[test]
1143        fn masked_write_register() {
1144            let bytes =
1145                encode_response_pdu_to_bytes(&Response::MaskWriteRegister(0x06, 0x8001, 0x4002));
1146            assert_eq!(bytes[0], 0x16);
1147            assert_eq!(bytes[1], 0x00);
1148            assert_eq!(bytes[2], 0x06);
1149            assert_eq!(bytes[3], 0x80);
1150            assert_eq!(bytes[4], 0x01);
1151            assert_eq!(bytes[5], 0x40);
1152            assert_eq!(bytes[6], 0x02);
1153        }
1154
1155        #[test]
1156        fn read_write_multiple_registers() {
1157            let bytes =
1158                encode_response_pdu_to_bytes(&Response::ReadWriteMultipleRegisters(vec![0x1234]));
1159            assert_eq!(bytes[0], 0x17);
1160            assert_eq!(bytes[1], 0x02);
1161            assert_eq!(bytes[2], 0x12);
1162            assert_eq!(bytes[3], 0x34);
1163        }
1164
1165        #[test]
1166        fn custom() {
1167            let bytes = encode_response_pdu_to_bytes(&Response::Custom(
1168                0x55,
1169                Bytes::from_static(&[0xCC, 0x88, 0xAA, 0xFF]),
1170            ));
1171            assert_eq!(bytes[0], 0x55);
1172            assert_eq!(bytes[1], 0xCC);
1173            assert_eq!(bytes[2], 0x88);
1174            assert_eq!(bytes[3], 0xAA);
1175            assert_eq!(bytes[4], 0xFF);
1176        }
1177    }
1178
1179    mod deserialize_responses {
1180
1181        use super::*;
1182
1183        #[test]
1184        fn read_coils() {
1185            let bytes = Bytes::from(vec![1, 1, 0b_0000_1001]);
1186            let response = Response::try_from(bytes).unwrap();
1187            assert_eq!(
1188                response,
1189                Response::ReadCoils(vec![true, false, false, true, false, false, false, false])
1190            );
1191        }
1192
1193        #[test]
1194        fn read_coils_max_quantity() {
1195            let quantity = 2000;
1196            let byte_count = quantity / 8;
1197            let mut raw: Vec<u8> = vec![1, u8_len(byte_count)];
1198            let mut values: Vec<u8> = (0..byte_count).map(|_| 0b_1111_1111).collect();
1199            raw.append(&mut values);
1200            let bytes = Bytes::from(raw);
1201            let response = Response::try_from(bytes).unwrap();
1202            assert_eq!(response, Response::ReadCoils(vec![true; quantity]));
1203        }
1204
1205        #[test]
1206        fn read_discrete_inputs() {
1207            let bytes = Bytes::from(vec![2, 1, 0b_0000_1001]);
1208            let response = Response::try_from(bytes).unwrap();
1209            assert_eq!(
1210                response,
1211                Response::ReadDiscreteInputs(vec![
1212                    true, false, false, true, false, false, false, false,
1213                ],)
1214            );
1215        }
1216
1217        #[test]
1218        fn read_discrete_inputs_max_quantity() {
1219            let quantity = 2000;
1220            let byte_count = quantity / 8;
1221            let mut raw: Vec<u8> = vec![2, u8_len(byte_count)];
1222            let mut values: Vec<u8> = (0..byte_count).map(|_| 0b_1111_1111).collect();
1223            raw.append(&mut values);
1224            let bytes = Bytes::from(raw);
1225            let response = Response::try_from(bytes).unwrap();
1226            assert_eq!(response, Response::ReadDiscreteInputs(vec![true; quantity]));
1227        }
1228
1229        #[test]
1230        fn write_single_coil() {
1231            let bytes = Bytes::from(vec![5, 0x00, 0x33, 0xFF, 0x00]);
1232            let response = Response::try_from(bytes).unwrap();
1233            assert_eq!(response, Response::WriteSingleCoil(0x33, true));
1234        }
1235
1236        #[test]
1237        fn write_multiple_coils() {
1238            let bytes = Bytes::from(vec![0x0F, 0x33, 0x11, 0x00, 0x05]);
1239            let response = Response::try_from(bytes).unwrap();
1240            assert_eq!(response, Response::WriteMultipleCoils(0x3311, 5));
1241        }
1242
1243        #[test]
1244        fn read_input_registers() {
1245            let bytes = Bytes::from(vec![4, 0x06, 0xAA, 0x00, 0xCC, 0xBB, 0xEE, 0xDD]);
1246            let response = Response::try_from(bytes).unwrap();
1247            assert_eq!(
1248                response,
1249                Response::ReadInputRegisters(vec![0xAA00, 0xCCBB, 0xEEDD])
1250            );
1251        }
1252
1253        #[test]
1254        fn read_holding_registers() {
1255            let bytes = Bytes::from(vec![3, 0x04, 0xAA, 0x00, 0x11, 0x11]);
1256            let response = Response::try_from(bytes).unwrap();
1257            assert_eq!(
1258                response,
1259                Response::ReadHoldingRegisters(vec![0xAA00, 0x1111])
1260            );
1261        }
1262
1263        #[test]
1264        fn write_single_register() {
1265            let bytes = Bytes::from(vec![6, 0x00, 0x07, 0xAB, 0xCD]);
1266            let response = Response::try_from(bytes).unwrap();
1267            assert_eq!(response, Response::WriteSingleRegister(0x07, 0xABCD));
1268        }
1269
1270        #[test]
1271        fn write_multiple_registers() {
1272            let bytes = Bytes::from(vec![0x10, 0x00, 0x06, 0x00, 0x02]);
1273            let response = Response::try_from(bytes).unwrap();
1274            assert_eq!(response, Response::WriteMultipleRegisters(0x06, 2));
1275        }
1276
1277        #[test]
1278        fn report_server_id() {
1279            let bytes = Bytes::from(vec![0x11, 0x04, 0x042, 0xFF, 0x10, 0x20]);
1280            let response = Response::try_from(bytes).unwrap();
1281            assert_eq!(
1282                response,
1283                Response::ReportServerId(0x42, true, vec![0x10, 0x20])
1284            );
1285        }
1286
1287        #[test]
1288        fn masked_write_register() {
1289            let bytes = Bytes::from(vec![0x16, 0x00, 0x06, 0x80, 0x01, 0x40, 0x02]);
1290            let response = Response::try_from(bytes).unwrap();
1291            assert_eq!(response, Response::MaskWriteRegister(6, 0x8001, 0x4002));
1292        }
1293
1294        #[test]
1295        fn read_write_multiple_registers() {
1296            let bytes = Bytes::from(vec![0x17, 0x02, 0x12, 0x34]);
1297            let response = Response::try_from(bytes).unwrap();
1298            assert_eq!(response, Response::ReadWriteMultipleRegisters(vec![0x1234]));
1299        }
1300
1301        #[test]
1302        fn custom() {
1303            let bytes = Bytes::from(vec![0x55, 0xCC, 0x88, 0xAA, 0xFF]);
1304            let response = Response::try_from(bytes).unwrap();
1305            assert_eq!(
1306                response,
1307                Response::Custom(0x55, Bytes::from_static(&[0xCC, 0x88, 0xAA, 0xFF]))
1308            );
1309        }
1310    }
1311}