xio_common/messages/
write_value_to_module_channel.rs

1use crate::base::{DataValueRaw, ErrorCode, HasErrorCode};
2use crate::{
3    error, DataValueReaderExt, DataValueWriterExt, Endian,
4    ErrorCodeReaderExt, ErrorCodeWriterExt, HasFixedCommandId, IsRequest,
5    IsResponse, IsValidResponseFor, MessageExt, ReadExt, ReadFromPayload,
6    Result, TryFromResponse, WithFixedPayloadLength, WriteExt,
7};
8use std::io::{Read, Write};
9
10#[derive(Clone, Debug, PartialEq)]
11pub struct Request {
12    pub module_id: u16,
13    pub channel_index: u16,
14    pub value: DataValueRaw,
15}
16
17impl IsRequest for Request {
18    type Response = Response;
19}
20
21impl From<Request> for super::Request {
22    fn from(m: Request) -> Self {
23        super::Request::WriteValueToModuleChannel(m)
24    }
25}
26
27impl WithFixedPayloadLength for Request {
28    const FIXED_PAYLOAD_LENGTH: u16 = u16::FIXED_PAYLOAD_LENGTH
29        + u16::FIXED_PAYLOAD_LENGTH
30        + DataValueRaw::FIXED_PAYLOAD_LENGTH;
31}
32
33impl HasFixedCommandId for Request {
34    const COMMAND_ID: u16 = 0x3808;
35}
36
37impl MessageExt for Request {
38    fn payload_length(&self) -> u16 {
39        Self::FIXED_PAYLOAD_LENGTH
40    }
41
42    fn write_payload(&self, w: &mut dyn Write) -> Result<()> {
43        w.write_u16::<Endian>(self.module_id)?;
44        w.write_u16::<Endian>(self.channel_index)?;
45        w.write_data_value(&self.value)?;
46        Ok(())
47    }
48}
49
50impl ReadFromPayload for Request {
51    fn read_from_payload<R: Read>(
52        r: &mut R,
53        payload_length: u16,
54    ) -> Result<Self> {
55        Self::verify_payload_length(
56            payload_length,
57            "write_value_to_module_channel_request",
58        )?;
59        let module_id = r.read_u16::<Endian>()?;
60        let channel_index = r.read_u16::<Endian>()?;
61        let value = r.read_data_value()?;
62        Ok(Self {
63            module_id,
64            channel_index,
65            value,
66        })
67    }
68}
69
70#[cfg(test)]
71mod test_request {
72    use super::*;
73
74    #[test]
75    fn write_to() {
76        let mut buffer = Vec::new();
77        let options: u8 = 0x45;
78        let sequence: u8 = 0x93;
79
80        let message = Request {
81            module_id: 0x1122,
82            channel_index: 0x3344,
83            value: 0x42u64.into(),
84        };
85        message.write_to(&mut buffer, options, sequence).unwrap();
86        assert_eq!(
87            buffer,
88            [
89                0x45, // options
90                0x93, // sequence
91                0x08, // command lower byte
92                0x38, // command upper byte
93                0x0D, // length lower byte
94                0x00, // length upper byte
95                0x22, // module_id lower byte
96                0x11, // module_id upper byte
97                0x44, // channel_index lower byte
98                0x33, // channel_index upper byte
99                0x08, // value data type
100                0x42, // value byte 0
101                0x00, // value byte 1
102                0x00, // value byte 2
103                0x00, // value byte 3
104                0x00, // value byte 4
105                0x00, // value byte 5
106                0x00, // value byte 6
107                0x00, // value byte 7
108            ]
109        );
110    }
111    #[test]
112    fn read_from_payload() {
113        let buffer = vec![
114            0x22, // module_id lower byte
115            0x11, // module_id upper byte
116            0x44, // channel_index lower byte
117            0x33, // channel_index upper byte
118            0x08, // value data type
119            0x42, // value byte 0
120            0x00, // value byte 1
121            0x00, // value byte 2
122            0x00, // value byte 3
123            0x00, // value byte 4
124            0x00, // value byte 5
125            0x00, // value byte 6
126            0x00, // value byte 7
127        ];
128        let len = buffer.len() as u16;
129        let message =
130            Request::read_from_payload(&mut buffer.as_slice(), len)
131                .unwrap();
132        assert_eq!(
133            message,
134            Request {
135                module_id: 0x1122,
136                channel_index: 0x3344,
137                value: 0x42u64.into(),
138            }
139        );
140    }
141}
142
143#[derive(Clone, Debug, PartialEq)]
144pub struct Response {
145    pub error: ErrorCode,
146}
147
148impl IsResponse for Response {
149    type Request = Request;
150}
151
152impl IsValidResponseFor for Response {
153    fn is_valid_response_for(&self, _request: &Request) -> bool {
154        true
155    }
156}
157
158impl HasErrorCode for Response {
159    fn error_code(&self) -> ErrorCode {
160        self.error
161    }
162}
163
164impl TryFromResponse for Response {
165    fn try_from_response(r: super::Response) -> Result<Self> {
166        if let super::Response::WriteValueToModuleChannel(r) = r {
167            Ok(r)
168        } else {
169            error::UnexpectedResponseType.fail()?
170        }
171    }
172}
173
174impl From<Response> for super::Response {
175    fn from(m: Response) -> Self {
176        super::Response::WriteValueToModuleChannel(m)
177    }
178}
179
180impl WithFixedPayloadLength for Response {
181    const FIXED_PAYLOAD_LENGTH: u16 = ErrorCode::FIXED_PAYLOAD_LENGTH;
182}
183
184impl HasFixedCommandId for Response {
185    const COMMAND_ID: u16 = 0x3809;
186}
187
188impl MessageExt for Response {
189    fn payload_length(&self) -> u16 {
190        Self::FIXED_PAYLOAD_LENGTH
191    }
192
193    fn write_payload(&self, w: &mut dyn Write) -> Result<()> {
194        w.write_error_code(self.error)?;
195        Ok(())
196    }
197}
198
199impl ReadFromPayload for Response {
200    fn read_from_payload<R: Read>(
201        r: &mut R,
202        payload_length: u16,
203    ) -> Result<Self> {
204        Self::verify_payload_length(
205            payload_length,
206            "write_value_to_module_channel_response",
207        )?;
208        let error = r.read_error_code()?;
209        Ok(Self { error })
210    }
211}
212
213#[cfg(test)]
214mod test_response {
215    use super::*;
216
217    #[test]
218    fn write_to() {
219        let mut buffer = Vec::new();
220        let options: u8 = 0x45;
221        let sequence: u8 = 0x93;
222
223        let message = Response {
224            error: ErrorCode::InvalidState, // 0x0107
225        };
226        message.write_to(&mut buffer, options, sequence).unwrap();
227        assert_eq!(
228            buffer,
229            [
230                0x45, // options
231                0x93, // sequence
232                0x09, // command lower byte
233                0x38, // command upper byte
234                0x02, // length lower byte
235                0x00, // length upper byte
236                0x07, // error lower byte
237                0x01, // error upper byte
238            ]
239        );
240    }
241    #[test]
242    fn read_from_payload() {
243        let buffer = vec![
244            0x07, // error lower byte
245            0x01, // error upper byte
246        ];
247        let len = buffer.len() as u16;
248        let message =
249            Response::read_from_payload(&mut buffer.as_slice(), len)
250                .unwrap();
251        assert_eq!(
252            message,
253            Response {
254                error: ErrorCode::InvalidState, // 0x0107
255            }
256        );
257    }
258}