1use crate::{ValidationError, request};
8
9use super::util::modbus_message;
10use zerocopy::{IntoBytes, big_endian};
11use zerocopy_derive::*;
12
13modbus_message! {
14 WriteHolding {
16 function_code: 0x06,
17 register: big_endian::U16,
18 value: big_endian::U16,
19 }
20}
21
22impl Response<request::WriteHolding> for WriteHolding {
23 type Data = ();
24
25 fn into_data(self, req: &request::WriteHolding) -> Result<(), ValidationError> {
26 self.validate_crc()?;
27
28 if self.address() == req.address()
29 && self.function() == req.function()
30 && self.register == req.register
31 && self.value == req.value
32 {
33 Ok(())
34 } else {
35 Err(ValidationError::UnexpectedResponse)
36 }
37 }
38}
39
40modbus_message! {
41 ReadHoldings<const N: usize> {
43 function_code: 0x03,
44 data_bytes: u8,
45 data: [big_endian::U16; N],
46 }
47}
48
49impl<const N: usize> Response<request::ReadHoldings> for ReadHoldings<N> {
50 type Data = [big_endian::U16; N];
51
52 fn into_data(self, req: &request::ReadHoldings) -> Result<Self::Data, ValidationError> {
53 self.validate_crc()?;
54
55 if self.address() == req.address()
56 && self.function() == req.function()
57 && self.data_bytes == 2 * req.n_registers.get() as u8
58 {
59 Ok(self.data)
60 } else {
61 Err(ValidationError::UnexpectedResponse)
62 }
63 }
64}
65
66modbus_message! {
67 WriteHoldings {
69 function_code: 0x10,
70 starting_register: big_endian::U16,
71 n_registers: big_endian::U16,
72 }
73}
74
75impl<const N: usize> Response<request::WriteHoldings<N>> for WriteHoldings {
76 type Data = ();
77
78 fn into_data(self, req: &request::WriteHoldings<N>) -> Result<(), ValidationError> {
79 self.validate_crc()?;
80
81 if self.address() == req.address()
82 && self.function() == req.function()
83 && self.starting_register == req.starting_register
84 && self.n_registers == req.n_registers
85 {
86 Ok(())
87 } else {
88 Err(ValidationError::UnexpectedResponse)
89 }
90 }
91}
92
93modbus_message! {
94 ReadInputs<const N: usize> {
96 function_code: 0x04,
97 data_bytes: u8,
98 data: [big_endian::U16; N],
99 }
100}
101
102impl<const N: usize> Response<request::ReadInputs> for ReadInputs<N> {
103 type Data = [big_endian::U16; N];
104
105 fn into_data(self, req: &request::ReadInputs) -> Result<Self::Data, ValidationError> {
106 self.validate_crc()?;
107
108 if self.address() == req.address()
109 && self.function() == req.function()
110 && self.data_bytes == 2 * req.n_registers.get() as u8
111 {
112 Ok(self.data)
113 } else {
114 Err(ValidationError::UnexpectedResponse)
115 }
116 }
117}
118
119pub trait Response<Request> {
121 type Data;
123
124 fn into_data(self, request: &Request) -> Result<Self::Data, ValidationError>;
126}