jcm/message/response/
direction_disable_response.rs

1use std::fmt;
2
3use crate::{Error, InhibitDirection, Message, RequestCode, Response, ResponseCode, Result};
4
5/// Represents the [Response] to a [DirectionDisableRequest](crate::DirectionDisableRequest).
6#[repr(C)]
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub struct DirectionDisableResponse {
9    code: ResponseCode,
10    dirs: InhibitDirection,
11}
12
13impl DirectionDisableResponse {
14    /// Creates a new [DirectionDisableResponse].
15    pub const fn new() -> Self {
16        Self {
17            code: ResponseCode::new(),
18            dirs: InhibitDirection::new(),
19        }
20    }
21
22    /// Gets the [ResponseCode] for the [DirectionDisableResponse].
23    pub const fn code(&self) -> ResponseCode {
24        self.code
25    }
26
27    /// Sets the [ResponseCode] for the [DirectionDisableResponse].
28    pub fn set_code(&mut self, code: ResponseCode) {
29        self.code = code;
30    }
31
32    /// Builder function that sets the [ResponseCode] for the [DirectionDisableResponse].
33    pub fn with_code(mut self, code: ResponseCode) -> Self {
34        self.set_code(code);
35        self
36    }
37
38    /// Gets the [InhibitDirection] for the [InhibitDirectionResponse].
39    pub fn directions(&self) -> InhibitDirection {
40        self.dirs
41    }
42
43    /// Sets the [InhibitDirection] for the [InhibitDirectionResponse].
44    pub fn set_directions(&mut self, dirs: InhibitDirection) {
45        self.dirs = dirs;
46    }
47
48    /// Builder function that sets the [InhibitDirection] for the [InhibitDirectionResponse].
49    pub fn with_directions(mut self, dirs: InhibitDirection) -> Self {
50        self.set_directions(dirs);
51        self
52    }
53
54    /// Gets the length of the [DirectionDisableResponse].
55    pub const fn len() -> usize {
56        ResponseCode::len() + InhibitDirection::len()
57    }
58
59    /// Gets whether the [DirectionDisableResponse] is empty.
60    pub fn is_empty(&self) -> bool {
61        self.code.is_empty() && self.dirs.is_empty()
62    }
63
64    /// Gets an iterator over [DirectionDisableResponse] bytes.
65    pub fn iter_bytes(&self) -> impl Iterator<Item = u8> + '_ {
66        [self.code.into(), self.dirs.into()].into_iter()
67    }
68
69    /// Gets an iterator over [DirectionDisableResponse] bytes.
70    pub fn into_iter_bytes(self) -> impl Iterator<Item = u8> {
71        [self.code.into(), self.dirs.into()].into_iter()
72    }
73
74    /// Converts a [DirectionDisableResponse] into a byte vector.
75    pub fn to_bytes(&self) -> Vec<u8> {
76        self.iter_bytes().collect()
77    }
78
79    /// Converts a [DirectionDisableResponse] into a byte vector.
80    pub fn into_bytes(self) -> Vec<u8> {
81        self.into_iter_bytes().collect()
82    }
83
84    /// Converts a byte buffer into a [DirectionDisableResponse].
85    pub fn from_bytes(buf: &[u8]) -> Result<Self> {
86        let len = Self::len();
87        let buf_len = buf.len();
88
89        if buf_len < len {
90            Err(Error::InvalidResponseLen((buf_len, len)))
91        } else {
92            Ok(Self {
93                code: buf[0].try_into()?,
94                dirs: buf.get(1).copied().unwrap_or(0).into(),
95            })
96        }
97    }
98}
99
100impl Default for DirectionDisableResponse {
101    fn default() -> Self {
102        Self::new()
103    }
104}
105
106impl From<&Response> for DirectionDisableResponse {
107    fn from(val: &Response) -> Self {
108        Self {
109            code: val.code(),
110            dirs: val.additional().first().copied().unwrap_or(0).into(),
111        }
112    }
113}
114
115impl From<Response> for DirectionDisableResponse {
116    fn from(val: Response) -> Self {
117        (&val).into()
118    }
119}
120
121impl From<DirectionDisableResponse> for Response {
122    fn from(val: DirectionDisableResponse) -> Self {
123        Self {
124            code: val.code,
125            additional: [val.dirs.bits()].into(),
126        }
127    }
128}
129
130impl From<&DirectionDisableResponse> for Response {
131    fn from(val: &DirectionDisableResponse) -> Self {
132        Self {
133            code: val.code,
134            additional: [val.dirs.bits()].into(),
135        }
136    }
137}
138
139impl TryFrom<Message> for DirectionDisableResponse {
140    type Error = Error;
141
142    fn try_from(val: Message) -> Result<Self> {
143        (&val).try_into()
144    }
145}
146
147impl TryFrom<&Message> for DirectionDisableResponse {
148    type Error = Error;
149
150    fn try_from(val: &Message) -> Result<Self> {
151        match val.data.message_code().request_code()? {
152            RequestCode::DirectionDisable => Ok(Response::try_from(val)?.into()),
153            code => Err(Error::InvalidRequestCode(code.into())),
154        }
155    }
156}
157
158impl fmt::Display for DirectionDisableResponse {
159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160        write!(f, "{{")?;
161        write!(f, r#""code":{}, "#, self.code)?;
162        write!(f, r#""directions":{}"#, self.dirs)?;
163        write!(f, "}}")
164    }
165}
166
167#[cfg(test)]
168mod tests {
169    use super::*;
170
171    #[test]
172    fn test_direction_disable_response() {
173        let raw = [ResponseCode::Ack as u8, 0];
174        let exp = DirectionDisableResponse::new()
175            .with_code(ResponseCode::Ack)
176            .with_directions(InhibitDirection::new());
177        let res = Response::new()
178            .with_code(ResponseCode::Ack)
179            .with_additional(&[0]);
180
181        assert_eq!(
182            DirectionDisableResponse::from_bytes(raw.as_ref()).as_ref(),
183            Ok(&exp)
184        );
185        assert_eq!(&DirectionDisableResponse::from(&res), &exp);
186        assert_eq!(Response::from(&exp), res);
187
188        let out = exp.into_bytes();
189
190        assert_eq!(out, raw);
191    }
192
193    #[test]
194    fn test_direction_disable_response_invalid() {
195        assert!(DirectionDisableResponse::from_bytes(&[]).is_err());
196        assert!(
197            DirectionDisableResponse::from_bytes([ResponseCode::Reserved as u8, 0].as_ref())
198                .is_err()
199        );
200    }
201}