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