rusty_modbus_codec/response/
diagnostic.rs1use crate::error::{DecodeError, EncodeError};
4use crate::request::Encode;
5use rusty_modbus_types::{DiagnosticSubFunction, FunctionCode};
6
7fn check_diagnostic_data_len_decode(data: &[u8]) -> Result<(), DecodeError> {
8 if data.len().is_multiple_of(2) {
9 Ok(())
10 } else {
11 Err(DecodeError::InvalidDiagnosticDataLength { length: data.len() })
12 }
13}
14
15fn check_diagnostic_data_len_encode(data: &[u8]) -> Result<(), EncodeError> {
16 if data.len().is_multiple_of(2) {
17 Ok(())
18 } else {
19 Err(EncodeError::InvalidDiagnosticDataLength { length: data.len() })
20 }
21}
22
23#[derive(Debug)]
25pub struct ReadExceptionStatusResponse {
26 pub status: u8,
28}
29
30impl ReadExceptionStatusResponse {
31 pub fn decode(data: &[u8]) -> Result<Self, DecodeError> {
38 DecodeError::check_exact_len(data, 1)?;
39 Ok(Self { status: data[0] })
40 }
41}
42
43impl Encode for ReadExceptionStatusResponse {
44 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
45 let len = self.encoded_len();
46 if buf.len() < len {
47 return Err(EncodeError::BufferTooSmall {
48 required: len,
49 available: buf.len(),
50 });
51 }
52 EncodeError::check_pdu_len(len)?;
53 buf[0] = FunctionCode::ReadExceptionStatus.code();
54 buf[1] = self.status;
55 Ok(len)
56 }
57
58 fn encoded_len(&self) -> usize {
59 1 + 1
60 }
61}
62
63#[derive(Debug)]
67pub struct DiagnosticsResponse<'buf> {
68 pub sub_function: DiagnosticSubFunction,
70 pub data: &'buf [u8],
72}
73
74impl<'buf> DiagnosticsResponse<'buf> {
75 pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
83 if data.len() < 2 {
84 return Err(DecodeError::Truncated {
85 expected: 2,
86 actual: data.len(),
87 });
88 }
89 let raw_sub = u16::from_be_bytes([data[0], data[1]]);
90 let sub_function = DiagnosticSubFunction::from_raw(raw_sub)
91 .ok_or(DecodeError::UnknownDiagnosticSubFunction(raw_sub))?;
92 let payload = &data[2..];
93 check_diagnostic_data_len_decode(payload)?;
94 Ok(Self {
95 sub_function,
96 data: payload,
97 })
98 }
99}
100
101impl Encode for DiagnosticsResponse<'_> {
102 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
103 let len = self.encoded_len();
104 if buf.len() < len {
105 return Err(EncodeError::BufferTooSmall {
106 required: len,
107 available: buf.len(),
108 });
109 }
110 check_diagnostic_data_len_encode(self.data)?;
111 EncodeError::check_pdu_len(len)?;
112 buf[0] = FunctionCode::Diagnostics.code();
113 let sf = self.sub_function.code().to_be_bytes();
114 buf[1] = sf[0];
115 buf[2] = sf[1];
116 buf[3..3 + self.data.len()].copy_from_slice(self.data);
117 Ok(len)
118 }
119
120 fn encoded_len(&self) -> usize {
121 1 + 2 + self.data.len()
122 }
123}
124
125#[derive(Debug)]
127pub struct GetCommEventCounterResponse {
128 pub status: u16,
130 pub event_count: u16,
132}
133
134impl GetCommEventCounterResponse {
135 pub fn decode(data: &[u8]) -> Result<Self, DecodeError> {
141 DecodeError::check_exact_len(data, 4)?;
142 let status = u16::from_be_bytes([data[0], data[1]]);
143 let event_count = u16::from_be_bytes([data[2], data[3]]);
144 Ok(Self {
145 status,
146 event_count,
147 })
148 }
149}
150
151impl Encode for GetCommEventCounterResponse {
152 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
153 let len = self.encoded_len();
154 if buf.len() < len {
155 return Err(EncodeError::BufferTooSmall {
156 required: len,
157 available: buf.len(),
158 });
159 }
160 EncodeError::check_pdu_len(len)?;
161 buf[0] = FunctionCode::GetCommEventCounter.code();
162 let st = self.status.to_be_bytes();
163 buf[1] = st[0];
164 buf[2] = st[1];
165 let ec = self.event_count.to_be_bytes();
166 buf[3] = ec[0];
167 buf[4] = ec[1];
168 Ok(len)
169 }
170
171 fn encoded_len(&self) -> usize {
172 1 + 4
173 }
174}
175
176#[derive(Debug)]
178pub struct GetCommEventLogResponse<'buf> {
179 pub byte_count: u8,
181 pub status: u16,
183 pub event_count: u16,
185 pub message_count: u16,
187 pub events: &'buf [u8],
189}
190
191impl<'buf> GetCommEventLogResponse<'buf> {
192 pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
200 if data.len() < 7 {
201 return Err(DecodeError::Truncated {
202 expected: 7,
203 actual: data.len(),
204 });
205 }
206 let byte_count = data[0];
207 let status = u16::from_be_bytes([data[1], data[2]]);
208 let event_count = u16::from_be_bytes([data[3], data[4]]);
209 let message_count = u16::from_be_bytes([data[5], data[6]]);
210 let events = &data[7..];
211 if byte_count < 6 {
214 return Err(DecodeError::ByteCountMismatch {
215 declared: usize::from(byte_count),
216 actual: 6 + events.len(),
217 });
218 }
219 let declared_events_len = usize::from(byte_count) - 6;
220 if events.len() != declared_events_len {
221 return Err(DecodeError::ByteCountMismatch {
222 declared: usize::from(byte_count),
223 actual: 6 + events.len(),
224 });
225 }
226 Ok(Self {
227 byte_count,
228 status,
229 event_count,
230 message_count,
231 events,
232 })
233 }
234}
235
236impl Encode for GetCommEventLogResponse<'_> {
237 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
238 let len = self.encoded_len();
239 if buf.len() < len {
240 return Err(EncodeError::BufferTooSmall {
241 required: len,
242 available: buf.len(),
243 });
244 }
245 EncodeError::check_byte_count(usize::from(self.byte_count), 6 + self.events.len())?;
246 EncodeError::check_pdu_len(len)?;
247 buf[0] = FunctionCode::GetCommEventLog.code();
248 buf[1] = self.byte_count;
249 let st = self.status.to_be_bytes();
250 buf[2] = st[0];
251 buf[3] = st[1];
252 let ec = self.event_count.to_be_bytes();
253 buf[4] = ec[0];
254 buf[5] = ec[1];
255 let mc = self.message_count.to_be_bytes();
256 buf[6] = mc[0];
257 buf[7] = mc[1];
258 buf[8..8 + self.events.len()].copy_from_slice(self.events);
259 Ok(len)
260 }
261
262 fn encoded_len(&self) -> usize {
263 1 + 1 + 6 + self.events.len()
265 }
266}
267
268#[derive(Debug)]
270pub struct ReportServerIdResponse<'buf> {
271 pub byte_count: u8,
273 pub data: &'buf [u8],
275}
276
277impl<'buf> ReportServerIdResponse<'buf> {
278 pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
286 if data.is_empty() {
287 return Err(DecodeError::Truncated {
288 expected: 1,
289 actual: 0,
290 });
291 }
292 let byte_count = data[0];
293 let payload = &data[1..];
294 if payload.len() != usize::from(byte_count) {
295 return Err(DecodeError::ByteCountMismatch {
296 declared: usize::from(byte_count),
297 actual: payload.len(),
298 });
299 }
300 Ok(Self {
301 byte_count,
302 data: payload,
303 })
304 }
305}
306
307impl Encode for ReportServerIdResponse<'_> {
308 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
309 let len = self.encoded_len();
310 if buf.len() < len {
311 return Err(EncodeError::BufferTooSmall {
312 required: len,
313 available: buf.len(),
314 });
315 }
316 EncodeError::check_byte_count(usize::from(self.byte_count), self.data.len())?;
317 EncodeError::check_pdu_len(len)?;
318 buf[0] = FunctionCode::ReportServerId.code();
319 buf[1] = self.byte_count;
320 buf[2..2 + usize::from(self.byte_count)].copy_from_slice(self.data);
321 Ok(len)
322 }
323
324 fn encoded_len(&self) -> usize {
325 1 + 1 + usize::from(self.byte_count)
326 }
327}