rusty_modbus_codec/request/
reg_write.rs1use rusty_modbus_types::{Address, FunctionCode, Quantity};
4
5use crate::error::{DecodeError, EncodeError};
6use crate::request::Encode;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct WriteSingleRegisterRequest {
13 pub address: Address,
15 pub value: u16,
17}
18
19impl WriteSingleRegisterRequest {
20 pub fn decode(data: &[u8]) -> Result<Self, DecodeError> {
27 DecodeError::check_exact_len(data, 4)?;
28 let address = Address(u16::from_be_bytes([data[0], data[1]]));
29 let value = u16::from_be_bytes([data[2], data[3]]);
30 Ok(Self { address, value })
31 }
32}
33
34impl Encode for WriteSingleRegisterRequest {
35 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
36 let len = self.encoded_len();
37 if buf.len() < len {
38 return Err(EncodeError::BufferTooSmall {
39 required: len,
40 available: buf.len(),
41 });
42 }
43 EncodeError::check_pdu_len(len)?;
44 buf[0] = FunctionCode::WriteSingleRegister.code();
45 buf[1..3].copy_from_slice(&self.address.0.to_be_bytes());
46 buf[3..5].copy_from_slice(&self.value.to_be_bytes());
47 Ok(len)
48 }
49
50 fn encoded_len(&self) -> usize {
51 5
52 }
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub struct WriteMultipleRegistersRequest<'buf> {
60 pub address: Address,
62 pub quantity: Quantity,
64 pub byte_count: u8,
66 pub register_values: &'buf [u8],
68}
69
70impl<'buf> WriteMultipleRegistersRequest<'buf> {
71 const MAX_QUANTITY: u16 = 123;
73
74 pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
83 if data.len() < 5 {
84 return Err(DecodeError::Truncated {
85 expected: 5,
86 actual: data.len(),
87 });
88 }
89 let address = Address(u16::from_be_bytes([data[0], data[1]]));
90 let quantity = u16::from_be_bytes([data[2], data[3]]);
91 if quantity == 0 || quantity > Self::MAX_QUANTITY {
92 return Err(DecodeError::QuantityOutOfRange { quantity });
93 }
94 let byte_count = data[4];
95 if u16::from(byte_count) != quantity * 2 {
97 return Err(DecodeError::ByteCountMismatch {
98 declared: usize::from(byte_count),
99 actual: (quantity * 2) as usize,
100 });
101 }
102 let remaining = data.len() - 5;
104 if byte_count as usize != remaining {
105 return Err(DecodeError::ByteCountMismatch {
106 declared: byte_count as usize,
107 actual: remaining,
108 });
109 }
110 let register_values = &data[5..];
111 Ok(Self {
112 address,
113 quantity: Quantity(quantity),
114 byte_count,
115 register_values,
116 })
117 }
118}
119
120impl Encode for WriteMultipleRegistersRequest<'_> {
121 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
122 let len = self.encoded_len();
123 if buf.len() < len {
124 return Err(EncodeError::BufferTooSmall {
125 required: len,
126 available: buf.len(),
127 });
128 }
129 EncodeError::check_quantity(self.quantity.0, Self::MAX_QUANTITY)?;
130 let expected_bytes = usize::from(self.quantity.0) * 2;
131 EncodeError::check_byte_count(usize::from(self.byte_count), expected_bytes)?;
132 EncodeError::check_byte_count(expected_bytes, self.register_values.len())?;
133 EncodeError::check_pdu_len(len)?;
134 buf[0] = FunctionCode::WriteMultipleRegisters.code();
135 buf[1..3].copy_from_slice(&self.address.0.to_be_bytes());
136 buf[3..5].copy_from_slice(&self.quantity.0.to_be_bytes());
137 buf[5] = self.byte_count;
138 buf[6..6 + self.register_values.len()].copy_from_slice(self.register_values);
139 Ok(len)
140 }
141
142 fn encoded_len(&self) -> usize {
143 6 + self.register_values.len()
145 }
146}
147
148#[derive(Debug, Clone, Copy, PartialEq, Eq)]
153pub struct MaskWriteRegisterRequest {
154 pub address: Address,
156 pub and_mask: u16,
158 pub or_mask: u16,
160}
161
162impl MaskWriteRegisterRequest {
163 pub fn decode(data: &[u8]) -> Result<Self, DecodeError> {
170 DecodeError::check_exact_len(data, 6)?;
171 let address = Address(u16::from_be_bytes([data[0], data[1]]));
172 let and_mask = u16::from_be_bytes([data[2], data[3]]);
173 let or_mask = u16::from_be_bytes([data[4], data[5]]);
174 Ok(Self {
175 address,
176 and_mask,
177 or_mask,
178 })
179 }
180}
181
182impl Encode for MaskWriteRegisterRequest {
183 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
184 let len = self.encoded_len();
185 if buf.len() < len {
186 return Err(EncodeError::BufferTooSmall {
187 required: len,
188 available: buf.len(),
189 });
190 }
191 EncodeError::check_pdu_len(len)?;
192 buf[0] = FunctionCode::MaskWriteRegister.code();
193 buf[1..3].copy_from_slice(&self.address.0.to_be_bytes());
194 buf[3..5].copy_from_slice(&self.and_mask.to_be_bytes());
195 buf[5..7].copy_from_slice(&self.or_mask.to_be_bytes());
196 Ok(len)
197 }
198
199 fn encoded_len(&self) -> usize {
200 7
201 }
202}
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq)]
209pub struct ReadWriteMultipleRegistersRequest<'buf> {
210 pub read_address: Address,
212 pub read_quantity: Quantity,
214 pub write_address: Address,
216 pub write_quantity: Quantity,
218 pub write_byte_count: u8,
220 pub write_register_values: &'buf [u8],
222}
223
224impl<'buf> ReadWriteMultipleRegistersRequest<'buf> {
225 const MAX_READ_QUANTITY: u16 = 125;
227 const MAX_WRITE_QUANTITY: u16 = 121;
229
230 pub fn decode(data: &'buf [u8]) -> Result<Self, DecodeError> {
239 if data.len() < 9 {
240 return Err(DecodeError::Truncated {
241 expected: 9,
242 actual: data.len(),
243 });
244 }
245 let read_address = Address(u16::from_be_bytes([data[0], data[1]]));
246 let read_quantity = u16::from_be_bytes([data[2], data[3]]);
247 if read_quantity == 0 || read_quantity > Self::MAX_READ_QUANTITY {
248 return Err(DecodeError::QuantityOutOfRange {
249 quantity: read_quantity,
250 });
251 }
252 let write_address = Address(u16::from_be_bytes([data[4], data[5]]));
253 let write_quantity = u16::from_be_bytes([data[6], data[7]]);
254 if write_quantity == 0 || write_quantity > Self::MAX_WRITE_QUANTITY {
255 return Err(DecodeError::QuantityOutOfRange {
256 quantity: write_quantity,
257 });
258 }
259 let write_byte_count = data[8];
260 if u16::from(write_byte_count) != write_quantity * 2 {
262 return Err(DecodeError::ByteCountMismatch {
263 declared: usize::from(write_byte_count),
264 actual: (write_quantity * 2) as usize,
265 });
266 }
267 let remaining = data.len() - 9;
269 if write_byte_count as usize != remaining {
270 return Err(DecodeError::ByteCountMismatch {
271 declared: write_byte_count as usize,
272 actual: remaining,
273 });
274 }
275 let write_register_values = &data[9..];
276 Ok(Self {
277 read_address,
278 read_quantity: Quantity(read_quantity),
279 write_address,
280 write_quantity: Quantity(write_quantity),
281 write_byte_count,
282 write_register_values,
283 })
284 }
285}
286
287impl Encode for ReadWriteMultipleRegistersRequest<'_> {
288 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
289 let len = self.encoded_len();
290 if buf.len() < len {
291 return Err(EncodeError::BufferTooSmall {
292 required: len,
293 available: buf.len(),
294 });
295 }
296 EncodeError::check_quantity(self.read_quantity.0, Self::MAX_READ_QUANTITY)?;
297 EncodeError::check_quantity(self.write_quantity.0, Self::MAX_WRITE_QUANTITY)?;
298 let expected_bytes = usize::from(self.write_quantity.0) * 2;
299 EncodeError::check_byte_count(usize::from(self.write_byte_count), expected_bytes)?;
300 EncodeError::check_byte_count(expected_bytes, self.write_register_values.len())?;
301 EncodeError::check_pdu_len(len)?;
302 buf[0] = FunctionCode::ReadWriteMultipleRegisters.code();
303 buf[1..3].copy_from_slice(&self.read_address.0.to_be_bytes());
304 buf[3..5].copy_from_slice(&self.read_quantity.0.to_be_bytes());
305 buf[5..7].copy_from_slice(&self.write_address.0.to_be_bytes());
306 buf[7..9].copy_from_slice(&self.write_quantity.0.to_be_bytes());
307 buf[9] = self.write_byte_count;
308 buf[10..10 + self.write_register_values.len()].copy_from_slice(self.write_register_values);
309 Ok(len)
310 }
311
312 fn encoded_len(&self) -> usize {
313 10 + self.write_register_values.len()
315 }
316}