easy_modbus/codec/
decoder.rs

1use std::io::{Error, ErrorKind::InvalidData, Result};
2
3use bytes::{Buf, BufMut, Bytes, BytesMut};
4use tokio_util::codec::Decoder;
5
6use crate::codec::{RtuClientCodec, RtuServerCodec};
7use crate::frame::{
8    Exception,
9    Function,
10    Head, request::{ReadCoilsRequest, Request}, response::{ReadCoilsResponse, Response}, Version,
11};
12use crate::frame::request::*;
13use crate::frame::response::*;
14use crate::util::crc;
15
16use super::{TcpClientCodec, TcpServerCodec};
17
18impl Decoder for RtuClientCodec {
19    type Item = Response;
20    type Error = Error;
21
22    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Response>> {
23        if src.len() < 2 {
24            return Ok(None);
25        }
26
27        let mut data_bytes = BytesMut::new();
28
29        let head_bytes = src.copy_to_bytes(2);
30        data_bytes.put_slice(&(head_bytes.to_vec()));
31        let mut head = Head::rtu_try_from(head_bytes)?;
32
33        let len: usize = {
34            if head.is_exception {
35                1
36            } else {
37                match head.function {
38                    Function::ReadCoils
39                    | Function::ReadDiscreteInputs
40                    | Function::ReadMultipleHoldingRegisters
41                    | Function::ReadInputRegisters => {
42                        src.get(0).map_or(0, |&bytes_num| bytes_num as usize + 1)
43                    }
44                    Function::WriteSingleCoil
45                    | Function::WriteSingleHoldingRegister
46                    | Function::WriteMultipleCoils
47                    | Function::WriteMultipleHoldingRegisters => 4,
48                }
49            }
50        };
51
52        if src.len() < len + 2 {
53            return Ok(None);
54        }
55
56        head.body_length(len as u16);
57
58        let body_bytes = src.copy_to_bytes(len);
59        data_bytes.put_slice(&(body_bytes.to_vec()));
60        let response = get_response(body_bytes, head);
61
62        let crc = src.get_u16();
63        if crc::check(&(data_bytes.to_vec()), crc) {
64            return Ok(Some(response));
65        }
66        return Err(Error::new(
67            InvalidData,
68            format!("Invalid crc code: 0x{:0>2X}", crc),
69        ));
70    }
71}
72
73impl Decoder for RtuServerCodec {
74    type Item = Request;
75    type Error = Error;
76
77    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Request>> {
78        if src.len() < 2 {
79            return Ok(None);
80        }
81
82        let mut data_bytes = BytesMut::new();
83        let head_bytes = src.copy_to_bytes(2);
84        data_bytes.put_slice(&(head_bytes.to_vec()));
85        let mut head = Head::rtu_try_from(head_bytes)?;
86
87        let len: usize = {
88            match head.function {
89                Function::ReadCoils
90                | Function::ReadDiscreteInputs
91                | Function::ReadMultipleHoldingRegisters
92                | Function::ReadInputRegisters
93                | Function::WriteSingleCoil
94                | Function::WriteSingleHoldingRegister => 4,
95                Function::WriteMultipleCoils | Function::WriteMultipleHoldingRegisters => {
96                    src.get(4).map_or(0, |&bytes_num| bytes_num as usize + 5)
97                }
98            }
99        };
100        if src.len() < len + 2 {
101            return Ok(None);
102        }
103
104        head.body_length(len as u16);
105        let body_bytes = src.copy_to_bytes(len);
106        data_bytes.put_slice(&(body_bytes.to_vec()));
107        let request = get_request(body_bytes, head);
108        let crc = src.get_u16();
109        if crc::check(&(data_bytes.to_vec()), crc) {
110            return Ok(Some(request));
111        }
112        return Err(Error::new(
113            InvalidData,
114            format!("Invalid crc code: 0x{:0>2X}", crc),
115        ));
116    }
117}
118
119impl Decoder for TcpClientCodec {
120    type Item = Response;
121    type Error = Error;
122
123    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Response>> {
124        if src.len() < 4 {
125            return Ok(None);
126        }
127        let head = Head::tcp_try_from(src.copy_to_bytes(8))?;
128        let len = head.length as usize - 2;
129        let response = get_response(src.copy_to_bytes(len), head);
130        Ok(Some(response))
131    }
132}
133
134impl Decoder for TcpServerCodec {
135    type Item = Request;
136    type Error = Error;
137
138    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Request>> {
139        if src.len() < 8 {
140            return Ok(None);
141        }
142        let head = Head::tcp_try_from(src.copy_to_bytes(8))?;
143        let len = head.length as usize - 2;
144        let request = get_request(src.copy_to_bytes(len), head);
145        Ok(Some(request))
146    }
147}
148
149fn get_request(src: Bytes, head: Head) -> Request {
150    match head.function {
151        Function::ReadCoils => Request::ReadCoils(head, ReadCoilsRequest::from(src)),
152        Function::ReadDiscreteInputs => {
153            Request::ReadDiscreteInputs(head, ReadDiscreteInputsRequest::from(src))
154        }
155        Function::ReadMultipleHoldingRegisters => Request::ReadMultipleHoldingRegisters(
156            head,
157            ReadMultipleHoldingRegistersRequest::from(src),
158        ),
159        Function::ReadInputRegisters => {
160            Request::ReadInputRegisters(head, ReadInputRegistersRequest::from(src))
161        }
162        Function::WriteSingleCoil => {
163            Request::WriteSingleCoil(head, WriteSingleCoilRequest::from(src))
164        }
165        Function::WriteSingleHoldingRegister => {
166            Request::WriteSingleHoldingRegister(head, WriteSingleHoldingRegisterRequest::from(src))
167        }
168        Function::WriteMultipleCoils => {
169            Request::WriteMultipleCoils(head, WriteMultipleCoilsRequest::from(src))
170        }
171        Function::WriteMultipleHoldingRegisters => Request::WriteMultipleHoldingRegisters(
172            head,
173            WriteMultipleHoldingRegistersRequest::from(src),
174        ),
175    }
176}
177
178fn get_response(src: Bytes, head: Head) -> Response {
179    if head.is_exception {
180        return Response::Exception(head, ExceptionResponse::from(src));
181    }
182
183    match head.function {
184        Function::ReadCoils => Response::ReadCoils(head, ReadCoilsResponse::from(src)),
185        Function::ReadDiscreteInputs => {
186            Response::ReadDiscreteInputs(head, ReadDiscreteInputsResponse::from(src))
187        }
188        Function::ReadMultipleHoldingRegisters => Response::ReadMultipleHoldingRegisters(
189            head,
190            ReadMultipleHoldingRegistersResponse::from(src),
191        ),
192        Function::ReadInputRegisters => {
193            Response::ReadInputRegisters(head, ReadInputRegistersResponse::from(src))
194        }
195        Function::WriteSingleCoil => {
196            Response::WriteSingleCoil(head, WriteSingleCoilResponse::from(src))
197        }
198        Function::WriteSingleHoldingRegister => Response::WriteSingleHoldingRegister(
199            head,
200            WriteSingleHoldingRegisterResponse::from(src),
201        ),
202        Function::WriteMultipleCoils => {
203            Response::WriteMultipleCoils(head, WriteMultipleCoilsResponse::from(src))
204        }
205        Function::WriteMultipleHoldingRegisters => Response::WriteMultipleHoldingRegisters(
206            head,
207            WriteMultipleHoldingRegistersResponse::from(src),
208        ),
209    }
210}
211
212impl From<Bytes> for ReadCoilsRequest {
213    fn from(mut buf: Bytes) -> Self {
214        ReadCoilsRequest {
215            first_address: buf.get_u16(),
216            coils_number: buf.get_u16(),
217        }
218    }
219}
220
221impl From<Bytes> for ReadDiscreteInputsRequest {
222    fn from(mut buf: Bytes) -> Self {
223        ReadDiscreteInputsRequest {
224            first_address: buf.get_u16(),
225            discrete_inputs_number: buf.get_u16(),
226        }
227    }
228}
229
230impl From<Bytes> for ReadMultipleHoldingRegistersRequest {
231    fn from(mut buf: Bytes) -> Self {
232        ReadMultipleHoldingRegistersRequest {
233            first_address: buf.get_u16(),
234            registers_number: buf.get_u16(),
235        }
236    }
237}
238
239impl From<Bytes> for ReadInputRegistersRequest {
240    fn from(mut buf: Bytes) -> Self {
241        ReadInputRegistersRequest {
242            first_address: buf.get_u16(),
243            registers_number: buf.get_u16(),
244        }
245    }
246}
247
248impl From<Bytes> for WriteSingleCoilRequest {
249    fn from(mut buf: Bytes) -> Self {
250        WriteSingleCoilRequest {
251            coil_address: buf.get_u16(),
252            value: buf.get_u16(),
253        }
254    }
255}
256
257impl From<Bytes> for WriteSingleHoldingRegisterRequest {
258    fn from(mut buf: Bytes) -> Self {
259        WriteSingleHoldingRegisterRequest {
260            register_address: buf.get_u16(),
261            value: buf.get_u16(),
262        }
263    }
264}
265
266impl From<Bytes> for WriteMultipleCoilsRequest {
267    fn from(mut buf: Bytes) -> Self {
268        WriteMultipleCoilsRequest {
269            first_address: buf.get_u16(),
270            coils_number: buf.get_u16(),
271            bytes_number: buf.get_u8(),
272            values: buf.to_vec(),
273        }
274    }
275}
276
277impl From<Bytes> for WriteMultipleHoldingRegistersRequest {
278    fn from(mut buf: Bytes) -> Self {
279        WriteMultipleHoldingRegistersRequest {
280            first_address: buf.get_u16(),
281            registers_number: buf.get_u16(),
282            bytes_number: buf.get_u8(),
283            values: buf.to_vec(),
284        }
285    }
286}
287
288impl From<Bytes> for ReadCoilsResponse {
289    fn from(mut buf: Bytes) -> Self {
290        ReadCoilsResponse {
291            bytes_number: buf.get_u8(),
292            values: buf.to_vec(),
293        }
294    }
295}
296
297impl From<Bytes> for ReadDiscreteInputsResponse {
298    fn from(mut buf: Bytes) -> Self {
299        ReadDiscreteInputsResponse {
300            bytes_number: buf.get_u8(),
301            values: buf.to_vec(),
302        }
303    }
304}
305
306impl From<Bytes> for ReadMultipleHoldingRegistersResponse {
307    fn from(mut buf: Bytes) -> Self {
308        ReadMultipleHoldingRegistersResponse {
309            bytes_number: buf.get_u8(),
310            values: buf.to_vec(),
311        }
312    }
313}
314
315impl From<Bytes> for ReadInputRegistersResponse {
316    fn from(mut buf: Bytes) -> Self {
317        ReadInputRegistersResponse {
318            bytes_number: buf.get_u8(),
319            values: buf.to_vec(),
320        }
321    }
322}
323
324impl From<Bytes> for WriteSingleCoilResponse {
325    fn from(mut buf: Bytes) -> Self {
326        WriteSingleCoilResponse {
327            coil_address: buf.get_u16(),
328            value: buf.get_u16(),
329        }
330    }
331}
332
333impl From<Bytes> for WriteSingleHoldingRegisterResponse {
334    fn from(mut buf: Bytes) -> Self {
335        WriteSingleHoldingRegisterResponse {
336            register_address: buf.get_u16(),
337            value: buf.get_u16(),
338        }
339    }
340}
341
342impl From<Bytes> for WriteMultipleCoilsResponse {
343    fn from(mut buf: Bytes) -> Self {
344        WriteMultipleCoilsResponse {
345            first_address: buf.get_u16(),
346            coils_number: buf.get_u16(),
347        }
348    }
349}
350
351impl From<Bytes> for WriteMultipleHoldingRegistersResponse {
352    fn from(mut buf: Bytes) -> Self {
353        WriteMultipleHoldingRegistersResponse {
354            first_address: buf.get_u16(),
355            registers_number: buf.get_u16(),
356        }
357    }
358}
359
360impl From<Bytes> for ExceptionResponse {
361    fn from(mut buf: Bytes) -> Self {
362        ExceptionResponse {
363            exception: Exception::try_from(buf.get_u8()).unwrap(),
364        }
365    }
366}
367
368impl Head {
369    fn tcp_try_from(mut buf: Bytes) -> Result<Self> {
370        let tid = buf.get_u16();
371        let pid = buf.get_u16();
372        let length = buf.get_u16();
373        let uid = buf.get_u8();
374        let (function, is_exception) = get_function(buf.get_u8())?;
375        Ok(Head {
376            tid,
377            pid,
378            length,
379            uid,
380            function,
381            version: Version::Tcp,
382            is_exception,
383        })
384    }
385
386    fn rtu_try_from(mut buf: Bytes) -> Result<Self> {
387        let uid = buf.get_u8();
388        let (function, is_exception) = get_function(buf.get_u8())?;
389        Ok(Head {
390            tid: 0,
391            pid: 0,
392            length: 0,
393            uid,
394            function,
395            version: Version::Rtu,
396            is_exception,
397        })
398    }
399}
400
401impl TryFrom<u8> for Exception {
402    type Error = Error;
403
404    fn try_from(value: u8) -> Result<Self> {
405        match Exception::from_code(value) {
406            None => {
407                return Err(Error::new(
408                    InvalidData,
409                    format!("Invalid Exception code: 0x{:0>2X}", value),
410                ));
411            }
412            Some(exception) => Ok(exception),
413        }
414    }
415}
416
417impl TryFrom<u8> for Function {
418    type Error = Error;
419    fn try_from(value: u8) -> Result<Self> {
420        let func = match value {
421            0x01 => Function::ReadCoils,
422            0x02 => Function::ReadDiscreteInputs,
423            0x03 => Function::ReadMultipleHoldingRegisters,
424            0x04 => Function::ReadInputRegisters,
425            0x05 => Function::WriteSingleCoil,
426            0x06 => Function::WriteSingleHoldingRegister,
427            0x0F => Function::WriteMultipleCoils,
428            0x10 => Function::WriteMultipleHoldingRegisters,
429            _ => {
430                return Err(Error::new(
431                    Exception::IllegalFunction.as_error_kind(),
432                    format!("Invalid function code: 0x{:0>2X}", value),
433                ));
434            }
435        };
436        Ok(func)
437    }
438}
439
440fn get_function(function_code: u8) -> Result<(Function, bool)> {
441    let function: Function;
442    let mut is_exception = false;
443    if function_code <= 0x80 {
444        function = Function::try_from(function_code)?;
445    } else {
446        function = Function::try_from(function_code - 0x80)?;
447        is_exception = true;
448    }
449    Ok((function, is_exception))
450}
451
452#[cfg(test)]
453mod rtu_client_decoder_test {
454    use bytes::BytesMut;
455    use tokio_util::codec::Decoder;
456
457    use crate::codec::RtuClientCodec;
458    use crate::frame::{Exception, Function};
459    use crate::Frame;
460
461    #[test]
462    fn read_coils_response_test() {
463        let mut codec = RtuClientCodec::default();
464        let v: Vec<u8> = vec![0x0B, 0x01, 0x04, 0xCD, 0x6B, 0xB2, 0x7F, 0x2B, 0xE1];
465        let mut buf = BytesMut::from(&v[..]);
466        let response_l = codec.decode(&mut buf).unwrap().unwrap();
467        let frame = Frame::rtu();
468        let response_r = frame.read_coils_response(0x0B, vec![0xCD, 0x6B, 0xB2, 0x7F]);
469        assert_eq!(response_l, response_r);
470    }
471
472    #[test]
473    fn read_discrete_inputs_response_test() {
474        let mut codec = RtuClientCodec::default();
475        let v: Vec<u8> = vec![0x0B, 0x02, 0x04, 0xAC, 0xDB, 0xFB, 0x0D, 0x82, 0x7C];
476        let mut buf = BytesMut::from(&v[..]);
477        let response_l = codec.decode(&mut buf).unwrap().unwrap();
478        let frame = Frame::rtu();
479        let response_r = frame.read_discrete_response(0x0B, vec![0xAC, 0xDB, 0xFB, 0x0D]);
480        assert_eq!(response_l, response_r);
481    }
482
483    #[test]
484    fn read_multiple_holding_registers_response_test() {
485        let mut codec = RtuClientCodec::default();
486        let v: Vec<u8> = vec![
487            0x0B, 0x03, 0x06, 0xAE, 0x41, 0x56, 0x52, 0x43, 0x40, 0xFA, 0xCD,
488        ];
489        let mut buf = BytesMut::from(&v[..]);
490        let response_l = codec.decode(&mut buf).unwrap().unwrap();
491        let frame = Frame::rtu();
492        let response_r =
493            frame.read_holding_register_response(0x0B, vec![0xAE, 0x41, 0x56, 0x52, 0x43, 0x40]);
494        assert_eq!(response_l, response_r);
495    }
496
497    #[test]
498    fn read_input_registers_response_test() {
499        let mut codec = RtuClientCodec::default();
500        let v: Vec<u8> = vec![0x0B, 0x04, 0x02, 0x10, 0x2F, 0x6D, 0x2D];
501        let mut buf = BytesMut::from(&v[..]);
502        let response_l = codec.decode(&mut buf).unwrap().unwrap();
503        let frame = Frame::rtu();
504        let response_r = frame.read_input_register_response(0x0B, vec![0x10, 0x2F]);
505        assert_eq!(response_l, response_r);
506    }
507
508    #[test]
509    fn write_single_coil_response_test() {
510        let mut codec = RtuClientCodec::default();
511        let v: Vec<u8> = vec![0x0B, 0x05, 0x00, 0xBF, 0x00, 0x00, 0xFC, 0x84];
512        let mut buf = BytesMut::from(&v[..]);
513        let response_l = codec.decode(&mut buf).unwrap().unwrap();
514        let frame = Frame::rtu();
515        let response_r = frame.write_single_coil_response(0x0B, 0x00BF, 0x0000);
516        assert_eq!(response_l, response_r);
517    }
518
519    #[test]
520    fn write_single_holding_register_response_test() {
521        let mut codec = RtuClientCodec::default();
522        let v: Vec<u8> = vec![0x0B, 0x006, 0x000, 0x004, 0x0AB, 0x0CD, 0x076, 0x004];
523        let mut buf = BytesMut::from(&v[..]);
524        let response_l = codec.decode(&mut buf).unwrap().unwrap();
525        let frame = Frame::rtu();
526        let response_r = frame.write_single_holding_register_response(0x0B, 0x0004, 0xABCD);
527        assert_eq!(response_l, response_r);
528    }
529
530    #[test]
531    fn write_multiple_coils_response_test() {
532        let mut codec = RtuClientCodec::default();
533        let v: Vec<u8> = vec![0x0B, 0x0F, 0x00, 0x1B, 0x00, 0x09, 0xE5, 0x60];
534        let mut buf = BytesMut::from(&v[..]);
535        let response_l = codec.decode(&mut buf).unwrap().unwrap();
536        let frame = Frame::rtu();
537        let response_r = frame.write_multiple_coils_response(0x0B, 0x001B, 0x0009);
538        assert_eq!(response_l, response_r);
539    }
540
541    #[test]
542    fn write_multiple_holding_registers_response_test() {
543        let mut codec = RtuClientCodec::default();
544        let v: Vec<u8> = vec![0x0B, 0x10, 0x00, 0x12, 0x00, 0x02, 0xE1, 0x67];
545        let mut buf = BytesMut::from(&v[..]);
546        let response_l = codec.decode(&mut buf).unwrap().unwrap();
547        let frame = Frame::rtu();
548        let response_r = frame.write_multiple_holding_registers_response(0x0B, 0x0012, 0x0002);
549        assert_eq!(response_l, response_r);
550    }
551
552    #[test]
553    fn exception_response_test() {
554        let mut codec = RtuClientCodec::default();
555        let v: Vec<u8> = vec![0x0A, 0x81, 0x02, 0xB0, 0x53];
556        let mut buf = BytesMut::from(&v[..]);
557        let response_l = codec.decode(&mut buf).unwrap().unwrap();
558        let frame = Frame::rtu();
559        let response_r =
560            frame.exception_response(0x0A, Function::ReadCoils, Exception::IllegalDataAddress);
561        assert_eq!(response_l, response_r);
562    }
563}
564
565#[cfg(test)]
566mod tcp_client_decoder_test {
567    use bytes::BytesMut;
568    use tokio_util::codec::Decoder;
569
570    use crate::{codec::TcpClientCodec, Frame};
571    use crate::frame::{Exception, Function};
572
573    #[test]
574    fn read_coils_response_test() {
575        let mut codec = TcpClientCodec::default();
576        let v: Vec<u8> = vec![
577            0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01, 0x01, 0x02, 0x00, 0x01,
578        ];
579        let mut buf = BytesMut::from(&v[..]);
580        let response_l = codec.decode(&mut buf).unwrap().unwrap();
581        let frame = Frame::tcp();
582        let response_r = frame.read_coils_response(0x01, vec![0x00, 0x01]);
583        assert_eq!(response_l, response_r);
584    }
585
586    #[test]
587    fn read_discrete_inputs_response_test() {
588        let mut codec = TcpClientCodec::default();
589        let v: Vec<u8> = vec![
590            0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x01, 0x02, 0x04, 0xAC, 0xDB, 0xFB, 0x0D,
591        ];
592        let mut buf = BytesMut::from(&v[..]);
593        let response_l = codec.decode(&mut buf).unwrap().unwrap();
594        let frame = Frame::tcp();
595        let response_r = frame.read_discrete_response(0x01, vec![0xAC, 0xDB, 0xFB, 0x0D]);
596        assert_eq!(response_l, response_r);
597    }
598
599    #[test]
600    fn read_multiple_holding_registers_response_test() {
601        let mut codec = TcpClientCodec::default();
602        let v: Vec<u8> = vec![
603            0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x01, 0x03, 0x06, 0xAE, 0x41, 0x56, 0x52, 0x43,
604            0x40,
605        ];
606        let mut buf = BytesMut::from(&v[..]);
607        let response_l = codec.decode(&mut buf).unwrap().unwrap();
608        let frame = Frame::tcp();
609        let response_r =
610            frame.read_holding_register_response(0x01, vec![0xAE, 0x41, 0x56, 0x52, 0x43, 0x40]);
611        assert_eq!(response_l, response_r);
612    }
613
614    #[test]
615    fn read_input_registers_response_test() {
616        let mut codec = TcpClientCodec::default();
617        let v: Vec<u8> = vec![
618            0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01, 0x04, 0x02, 0x10, 0x2F,
619        ];
620        let mut buf = BytesMut::from(&v[..]);
621        let response_l = codec.decode(&mut buf).unwrap().unwrap();
622        let frame = Frame::tcp();
623        let response_r = frame.read_input_register_response(0x01, vec![0x10, 0x2F]);
624        assert_eq!(response_l, response_r);
625    }
626
627    #[test]
628    fn write_single_coil_response_test() {
629        let mut codec = TcpClientCodec::default();
630        let v: Vec<u8> = vec![
631            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x05, 0x00, 0xBF, 0x00, 0x00,
632        ];
633        let mut buf = BytesMut::from(&v[..]);
634        let response_l = codec.decode(&mut buf).unwrap().unwrap();
635        let frame = Frame::tcp();
636        let response_r = frame.write_single_coil_response(0x01, 0x00BF, 0x0000);
637        assert_eq!(response_l, response_r);
638    }
639
640    #[test]
641    fn write_single_holding_register_response_test() {
642        let mut codec = TcpClientCodec::default();
643        let v: Vec<u8> = vec![
644            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x06, 0x00, 0x04, 0xAB, 0xCD,
645        ];
646        let mut buf = BytesMut::from(&v[..]);
647        let response_l = codec.decode(&mut buf).unwrap().unwrap();
648        let frame = Frame::tcp();
649        let response_r = frame.write_single_holding_register_response(0x01, 0x0004, 0xABCD);
650        assert_eq!(response_l, response_r);
651    }
652
653    #[test]
654    fn write_multiple_coils_response_test() {
655        let mut codec = TcpClientCodec::default();
656        let v: Vec<u8> = vec![
657            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x0F, 0x00, 0x1B, 0x00, 0x09,
658        ];
659        let mut buf = BytesMut::from(&v[..]);
660        let response_l = codec.decode(&mut buf).unwrap().unwrap();
661        let frame = Frame::tcp();
662        let response_r = frame.write_multiple_coils_response(0x01, 0x001B, 0x0009);
663        assert_eq!(response_l, response_r);
664    }
665
666    #[test]
667    fn write_multiple_holding_registers_response_test() {
668        let mut codec = TcpClientCodec::default();
669        let v: Vec<u8> = vec![
670            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x10, 0x00, 0x12, 0x00, 0x02,
671        ];
672        let mut buf = BytesMut::from(&v[..]);
673        let response_l = codec.decode(&mut buf).unwrap().unwrap();
674        let frame = Frame::tcp();
675        let response_r = frame.write_multiple_holding_registers_response(0x01, 0x0012, 0x0002);
676        assert_eq!(response_l, response_r);
677    }
678
679    #[test]
680    fn exception_response_test() {
681        let mut codec = TcpClientCodec::default();
682        let v: Vec<u8> = vec![0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x0A, 0x81, 0x02];
683        let mut buf = BytesMut::from(&v[..]);
684        let response_l = codec.decode(&mut buf).unwrap().unwrap();
685        let frame = Frame::tcp();
686        let response_r =
687            frame.exception_response(0x0A, Function::ReadCoils, Exception::IllegalDataAddress);
688        assert_eq!(response_l, response_r);
689    }
690}
691
692#[cfg(test)]
693mod rtu_server_decoder_test {
694    use bytes::BytesMut;
695    use tokio_util::codec::Decoder;
696
697    use crate::codec::RtuServerCodec;
698    use crate::frame::Frame;
699
700    #[test]
701    fn read_coils_request_test() {
702        let mut codec = RtuServerCodec::default();
703        let v: Vec<u8> = vec![0x0B, 0x01, 0x00, 0x1D, 0x00, 0x1F, 0xED, 0x6E];
704        let mut buf = BytesMut::from(&v[..]);
705        let request_l = codec.decode(&mut buf).unwrap().unwrap();
706
707        let frame = Frame::rtu();
708        let request_r = frame.read_coils_request(0x0B, 0x001D, 0x001F);
709        assert_eq!(request_l, request_r);
710    }
711
712    #[test]
713    fn read_discrete_inputs_test() {
714        let mut codec = RtuServerCodec::default();
715        let v: Vec<u8> = vec![0x0B, 0x02, 0x00, 0x7A, 0x00, 0x1C, 0x58, 0xB0];
716        let mut buf = BytesMut::from(&v[..]);
717        let request_l = codec.decode(&mut buf).unwrap().unwrap();
718        let frame = Frame::rtu();
719        let request_r = frame.read_discrete_request(0x0B, 0x007A, 0x001C);
720        assert_eq!(request_l, request_r);
721    }
722
723    #[test]
724    fn read_multiple_holding_registers_test() {
725        let mut codec = RtuServerCodec::default();
726        let v: Vec<u8> = vec![0x0B, 0x03, 0x00, 0x6F, 0x00, 0x03, 0x35, 0x7C];
727        let mut buf = BytesMut::from(&v[..]);
728        let request_l = codec.decode(&mut buf).unwrap().unwrap();
729        let frame = Frame::rtu();
730        let request_r = frame.read_multiple_holding_registers_request(0x0B, 0x006F, 0x0003);
731        assert_eq!(request_l, request_r);
732    }
733
734    #[test]
735    fn read_input_registers_test() {
736        let mut codec = RtuServerCodec::default();
737        let v: Vec<u8> = vec![0x0B, 0x04, 0x00, 0x0A, 0x00, 0x01, 0x11, 0x62];
738        let mut buf = BytesMut::from(&v[..]);
739        let request_l = codec.decode(&mut buf).unwrap().unwrap();
740        let frame = Frame::rtu();
741        let request_r = frame.read_input_registers_request(0x0B, 0x000A, 0x0001);
742        assert_eq!(request_l, request_r);
743    }
744
745    #[test]
746    fn write_single_coil_test() {
747        let mut codec = RtuServerCodec::default();
748        let v: Vec<u8> = vec![0x0B, 0x05, 0x00, 0xBF, 0x00, 0x00, 0xFC, 0x84];
749        let mut buf = BytesMut::from(&v[..]);
750        let request_l = codec.decode(&mut buf).unwrap().unwrap();
751        let frame = Frame::rtu();
752        let request_r = frame.write_single_coil_request(0x0B, 0x00BF, 0x0000);
753        assert_eq!(request_l, request_r);
754    }
755
756    #[test]
757    fn write_single_holding_register_test() {
758        let mut codec = RtuServerCodec::default();
759        let v: Vec<u8> = vec![0x0B, 0x06, 0x00, 0x04, 0xAB, 0xCD, 0x76, 0x04];
760        let mut buf = BytesMut::from(&v[..]);
761        let request_l = codec.decode(&mut buf).unwrap().unwrap();
762        let frame = Frame::rtu();
763        let request_r = frame.write_single_holding_register_request(0x0B, 0x0004, 0xABCD);
764        assert_eq!(request_l, request_r);
765    }
766
767    #[test]
768    fn write_multiple_coils_test() {
769        let mut codec = RtuServerCodec::default();
770        let v: Vec<u8> = vec![
771            0x0B, 0x0F, 0x00, 0x1B, 0x00, 0x09, 0x02, 0x4D, 0x01, 0x6C, 0xA7,
772        ];
773        let mut buf = BytesMut::from(&v[..]);
774        let request_l = codec.decode(&mut buf).unwrap().unwrap();
775        let frame = Frame::rtu();
776        let request_r = frame.write_multiple_coils_request(0x0B, 0x001B, 0x0009, vec![0x4D, 0x01]);
777        assert_eq!(request_l, request_r);
778    }
779
780    #[test]
781    fn write_multiple_holding_registers_test() {
782        let mut codec = RtuServerCodec::default();
783        let v: Vec<u8> = vec![
784            0x0B, 0x10, 0x00, 0x12, 0x00, 0x02, 0x04, 0x0B, 0x0A, 0xC1, 0x02, 0xA0, 0xD5,
785        ];
786        let mut buf = BytesMut::from(&v[..]);
787        let request_l = codec.decode(&mut buf).unwrap().unwrap();
788        let frame = Frame::rtu();
789        let request_r = frame.write_multiple_holding_registers_request(
790            0x0B,
791            0x0012,
792            vec![0x0B, 0x0A, 0xC1, 0x02],
793        );
794        assert_eq!(request_l, request_r);
795    }
796}
797
798#[cfg(test)]
799mod tcp_server_decoder_test {
800    use bytes::BytesMut;
801    use tokio_util::codec::Decoder;
802
803    use crate::codec::TcpServerCodec;
804    use crate::frame::Frame;
805
806    #[test]
807    fn read_coils_request_test() {
808        let mut codec = TcpServerCodec::default();
809        let v: Vec<u8> = vec![
810            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x00, 0x02, 0x00, 0x08,
811        ];
812        let mut buf = BytesMut::from(&v[..]);
813        let request_l = codec.decode(&mut buf).unwrap().unwrap();
814
815        let frame = Frame::tcp();
816        let request_r = frame.read_coils_request(0x01, 0x02, 0x08);
817        assert_eq!(request_l, request_r);
818    }
819
820    #[test]
821    fn read_discrete_inputs_test() {
822        let mut codec = TcpServerCodec::default();
823        let v: Vec<u8> = vec![
824            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x00, 0x7A, 0x00, 0x1C,
825        ];
826        let mut buf = BytesMut::from(&v[..]);
827        let request_l = codec.decode(&mut buf).unwrap().unwrap();
828        let frame = Frame::tcp();
829        let request_r = frame.read_discrete_request(0x01, 0x007A, 0x001C);
830        assert_eq!(request_l, request_r);
831    }
832
833    #[test]
834    fn read_multiple_holding_registers_test() {
835        let mut codec = TcpServerCodec::default();
836        let v: Vec<u8> = vec![
837            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x6F, 0x00, 0x03,
838        ];
839        let mut buf = BytesMut::from(&v[..]);
840        let request_l = codec.decode(&mut buf).unwrap().unwrap();
841        let frame = Frame::tcp();
842        let request_r = frame.read_multiple_holding_registers_request(0x01, 0x006F, 0x0003);
843        assert_eq!(request_l, request_r);
844    }
845
846    #[test]
847    fn read_input_registers_test() {
848        let mut codec = TcpServerCodec::default();
849        let v: Vec<u8> = vec![
850            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x04, 0x00, 0x0A, 0x00, 0x01,
851        ];
852        let mut buf = BytesMut::from(&v[..]);
853        let request_l = codec.decode(&mut buf).unwrap().unwrap();
854        let frame = Frame::tcp();
855        let request_r = frame.read_input_registers_request(0x01, 0x000A, 0x0001);
856        assert_eq!(request_l, request_r);
857    }
858
859    #[test]
860    fn write_single_coil_test() {
861        let mut codec = TcpServerCodec::default();
862        let v: Vec<u8> = vec![
863            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x05, 0x00, 0xBF, 0x00, 0x00,
864        ];
865        let mut buf = BytesMut::from(&v[..]);
866        let request_l = codec.decode(&mut buf).unwrap().unwrap();
867        let frame = Frame::tcp();
868        let request_r = frame.write_single_coil_request(0x01, 0x00BF, 0x0000);
869        assert_eq!(request_l, request_r);
870    }
871
872    #[test]
873    fn write_single_holding_register_test() {
874        let mut codec = TcpServerCodec::default();
875        let v: Vec<u8> = vec![
876            0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x06, 0x00, 0x04, 0xAB, 0xCD,
877        ];
878        let mut buf = BytesMut::from(&v[..]);
879        let request_l = codec.decode(&mut buf).unwrap().unwrap();
880        let frame = Frame::tcp();
881        let request_r = frame.write_single_holding_register_request(0x01, 0x0004, 0xABCD);
882        assert_eq!(request_l, request_r);
883    }
884
885    #[test]
886    fn write_multiple_coils_test() {
887        let mut codec = TcpServerCodec::default();
888        let v: Vec<u8> = vec![
889            0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x01, 0x0F, 0x00, 0x1B, 0x00, 0x09, 0x02, 0x4D,
890            0x01,
891        ];
892        let mut buf = BytesMut::from(&v[..]);
893        let request_l = codec.decode(&mut buf).unwrap().unwrap();
894        let frame = Frame::tcp();
895        let request_r = frame.write_multiple_coils_request(0x01, 0x001B, 0x0009, vec![0x4D, 0x01]);
896        assert_eq!(request_l, request_r);
897    }
898
899    #[test]
900    fn write_multiple_holding_registers_test() {
901        let mut codec = TcpServerCodec::default();
902        let v: Vec<u8> = vec![
903            0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x10, 0x00, 0x12, 0x00, 0x02, 0x04, 0x0B,
904            0x0A, 0xC1, 0x02,
905        ];
906        let mut buf = BytesMut::from(&v[..]);
907        let request_l = codec.decode(&mut buf).unwrap().unwrap();
908        let frame = Frame::tcp();
909        let request_r = frame.write_multiple_holding_registers_request(
910            0x01,
911            0x0012,
912            vec![0x0B, 0x0A, 0xC1, 0x02],
913        );
914        assert_eq!(request_l, request_r);
915    }
916}