modbius_core/requests/write/
single.rs1use core::convert::TryFrom;
2
3use crate::{BitState, ModbusSerializationError, PublicModbusFunction, util};
4
5#[derive(Debug, Clone, Copy, Hash, Default, PartialEq, Eq, PartialOrd, Ord)]
10pub struct WriteSingleCoil {
11 pub addr: u16,
12 pub state: BitState,
13}
14
15impl WriteSingleCoil {
16 pub const MODBUS_FUNCTION_CODE: PublicModbusFunction = PublicModbusFunction::WriteSingleCoil;
17
18 pub fn new(addr: u16, state: BitState) -> Self {
20 Self { addr, state }
21 }
22
23 pub fn from_data(data: &[u8]) -> Result<(Self, &[u8]), ModbusSerializationError> {
28 if data.len() < 4 {
29 Err(ModbusSerializationError::UnexpectedEOF {
30 expected: 4,
31 got: data.len(),
32 })
33 } else {
34 unsafe { Self::from_data_unchecked(data) }
35 }
36 }
37
38 pub unsafe fn from_data_unchecked(data: &[u8]) -> Result<(Self, &[u8]), ModbusSerializationError> {
46 let (addr, data) = util::read_u16_unchecked(data);
47 let (state, data) = util::read_u16_unchecked(data);
48 let state = BitState::try_from(state)?;
49
50 Ok((Self::new(addr, state), data))
51 }
52
53 pub fn into_data(self) -> [u8;5] {
54 let addr_bytes = self.addr.to_be_bytes();
55 let state_bytes = u16::to_be_bytes(self.state.into());
56
57 [Self::MODBUS_FUNCTION_CODE as u8, addr_bytes[0], addr_bytes[1], state_bytes[0], state_bytes[1]]
58 }
59
60 pub fn write_to_slice(
62 self,
63 out: &mut [u8],
64 ) -> Result<(), ModbusSerializationError> {
65 if out.len() < 5 {
66 return Err(ModbusSerializationError::InsufficientBuffer {
67 expected: 5,
68 got: out.len(),
69 });
70 }
71
72 unsafe { self.write_to_slice_unchecked(out) };
73 Ok(())
74 }
75
76 pub unsafe fn write_to_slice_unchecked(self, out: &mut [u8]) {
81 out.get_unchecked_mut(0..5).copy_from_slice(&self.into_data());
82 }
83}
84
85#[derive(Debug, Clone, Copy, Hash, Default, PartialEq, Eq, PartialOrd, Ord)]
87pub struct WriteSingleRegister {
88 pub addr: u16,
89 pub value: u16,
90}
91
92impl WriteSingleRegister {
93 pub const MODBUS_FUNCTION_CODE: PublicModbusFunction = PublicModbusFunction::WriteSingleRegister;
94
95 pub fn new(addr: u16, value: u16) -> Self {
97 Self { addr, value }
98 }
99
100 pub fn from_data(data: &[u8]) -> Result<(Self, &[u8]), ModbusSerializationError> {
105 if data.len() < 4 {
106 Err(ModbusSerializationError::UnexpectedEOF {
107 expected: 4,
108 got: data.len(),
109 })
110 } else {
111 unsafe { Self::from_data_unchecked(data) }
112 }
113 }
114
115 pub unsafe fn from_data_unchecked(data: &[u8]) -> Result<(Self, &[u8]), ModbusSerializationError> {
123 let (addr, data) = util::read_u16_unchecked(data);
124 let (value, data) = util::read_u16_unchecked(data);
125
126 Ok((Self::new(addr, value), data))
127 }
128
129 pub fn into_data(self) -> [u8;5] {
130 let addr_bytes = self.addr.to_be_bytes();
131 let value_bytes = self.value.to_be_bytes();
132
133 [Self::MODBUS_FUNCTION_CODE as u8, addr_bytes[0], addr_bytes[1], value_bytes[0], value_bytes[1]]
134 }
135
136 pub fn write_to_slice(
138 self,
139 out: &mut [u8],
140 ) -> Result<(), ModbusSerializationError> {
141 if out.len() < 5 {
142 return Err(ModbusSerializationError::InsufficientBuffer {
143 expected: 5,
144 got: out.len(),
145 });
146 }
147
148 unsafe { self.write_to_slice_unchecked(out) };
149 Ok(())
150 }
151
152 pub unsafe fn write_to_slice_unchecked(self, out: &mut [u8]) {
157 out.get_unchecked_mut(0..5).copy_from_slice(&self.into_data());
158 }
159}