jcm/message/response/
direction_disable_response.rs1use std::fmt;
2
3use crate::{Error, InhibitDirection, Message, RequestCode, Response, ResponseCode, Result};
4
5#[repr(C)]
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub struct DirectionDisableResponse {
9 code: ResponseCode,
10 dirs: InhibitDirection,
11}
12
13impl DirectionDisableResponse {
14 pub const fn new() -> Self {
16 Self {
17 code: ResponseCode::new(),
18 dirs: InhibitDirection::new(),
19 }
20 }
21
22 pub const fn code(&self) -> ResponseCode {
24 self.code
25 }
26
27 pub fn set_code(&mut self, code: ResponseCode) {
29 self.code = code;
30 }
31
32 pub fn with_code(mut self, code: ResponseCode) -> Self {
34 self.set_code(code);
35 self
36 }
37
38 pub fn directions(&self) -> InhibitDirection {
40 self.dirs
41 }
42
43 pub fn set_directions(&mut self, dirs: InhibitDirection) {
45 self.dirs = dirs;
46 }
47
48 pub fn with_directions(mut self, dirs: InhibitDirection) -> Self {
50 self.set_directions(dirs);
51 self
52 }
53
54 pub const fn len() -> usize {
56 ResponseCode::len() + InhibitDirection::len()
57 }
58
59 pub fn is_empty(&self) -> bool {
61 self.code.is_empty() && self.dirs.is_empty()
62 }
63
64 pub fn iter_bytes(&self) -> impl Iterator<Item = u8> + '_ {
66 [self.code.into(), self.dirs.into()].into_iter()
67 }
68
69 pub fn into_iter_bytes(self) -> impl Iterator<Item = u8> {
71 [self.code.into(), self.dirs.into()].into_iter()
72 }
73
74 pub fn to_bytes(&self) -> Vec<u8> {
76 self.iter_bytes().collect()
77 }
78
79 pub fn into_bytes(self) -> Vec<u8> {
81 self.into_iter_bytes().collect()
82 }
83
84 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}