rusty_modbus_codec/response/
reg_read.rs1use crate::error::{DecodeError, EncodeError};
4use crate::request::Encode;
5use rusty_modbus_types::FunctionCode;
6
7#[derive(Debug)]
9pub struct ReadHoldingRegistersResponse<'buf> {
10 pub byte_count: u8,
12 pub register_data: &'buf [u8],
14}
15
16impl<'buf> ReadHoldingRegistersResponse<'buf> {
17 #[must_use]
19 pub fn count(&self) -> usize {
20 self.register_data.len() / 2
21 }
22
23 #[must_use]
29 pub fn register(&self, index: usize) -> u16 {
30 let off = index * 2;
31 u16::from_be_bytes([self.register_data[off], self.register_data[off + 1]])
32 }
33
34 pub fn registers(&self) -> impl Iterator<Item = u16> + '_ {
36 self.register_data
37 .chunks_exact(2)
38 .map(|c| u16::from_be_bytes([c[0], c[1]]))
39 }
40
41 #[must_use]
43 pub fn raw(&self) -> &'buf [u8] {
44 self.register_data
45 }
46
47 pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
55 if data.is_empty() {
56 return Err(DecodeError::Truncated {
57 expected: 1,
58 actual: 0,
59 });
60 }
61 let byte_count = data[0];
62 let register_data = &data[1..];
63 if register_data.len() != usize::from(byte_count) {
64 return Err(DecodeError::ByteCountMismatch {
65 declared: usize::from(byte_count),
66 actual: register_data.len(),
67 });
68 }
69 Ok(Self {
70 byte_count,
71 register_data,
72 })
73 }
74}
75
76impl Encode for ReadHoldingRegistersResponse<'_> {
77 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
78 let len = self.encoded_len();
79 if buf.len() < len {
80 return Err(EncodeError::BufferTooSmall {
81 required: len,
82 available: buf.len(),
83 });
84 }
85 EncodeError::check_byte_count(usize::from(self.byte_count), self.register_data.len())?;
86 EncodeError::check_pdu_len(len)?;
87 buf[0] = FunctionCode::ReadHoldingRegisters.code();
88 buf[1] = self.byte_count;
89 buf[2..2 + usize::from(self.byte_count)].copy_from_slice(self.register_data);
90 Ok(len)
91 }
92
93 fn encoded_len(&self) -> usize {
94 1 + 1 + usize::from(self.byte_count)
95 }
96}
97
98#[derive(Debug)]
100pub struct ReadInputRegistersResponse<'buf> {
101 pub byte_count: u8,
103 pub register_data: &'buf [u8],
105}
106
107impl<'buf> ReadInputRegistersResponse<'buf> {
108 #[must_use]
110 pub fn count(&self) -> usize {
111 self.register_data.len() / 2
112 }
113
114 #[must_use]
120 pub fn register(&self, index: usize) -> u16 {
121 let off = index * 2;
122 u16::from_be_bytes([self.register_data[off], self.register_data[off + 1]])
123 }
124
125 pub fn registers(&self) -> impl Iterator<Item = u16> + '_ {
127 self.register_data
128 .chunks_exact(2)
129 .map(|c| u16::from_be_bytes([c[0], c[1]]))
130 }
131
132 #[must_use]
134 pub fn raw(&self) -> &'buf [u8] {
135 self.register_data
136 }
137
138 pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
146 if data.is_empty() {
147 return Err(DecodeError::Truncated {
148 expected: 1,
149 actual: 0,
150 });
151 }
152 let byte_count = data[0];
153 let register_data = &data[1..];
154 if register_data.len() != usize::from(byte_count) {
155 return Err(DecodeError::ByteCountMismatch {
156 declared: usize::from(byte_count),
157 actual: register_data.len(),
158 });
159 }
160 Ok(Self {
161 byte_count,
162 register_data,
163 })
164 }
165}
166
167impl Encode for ReadInputRegistersResponse<'_> {
168 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
169 let len = self.encoded_len();
170 if buf.len() < len {
171 return Err(EncodeError::BufferTooSmall {
172 required: len,
173 available: buf.len(),
174 });
175 }
176 EncodeError::check_byte_count(usize::from(self.byte_count), self.register_data.len())?;
177 EncodeError::check_pdu_len(len)?;
178 buf[0] = FunctionCode::ReadInputRegisters.code();
179 buf[1] = self.byte_count;
180 buf[2..2 + usize::from(self.byte_count)].copy_from_slice(self.register_data);
181 Ok(len)
182 }
183
184 fn encoded_len(&self) -> usize {
185 1 + 1 + usize::from(self.byte_count)
186 }
187}