ctaphid_types/
response.rs1use core::convert::{TryFrom, TryInto};
5
6use crate::{
7 channel::Channel,
8 error::{ParseError, SerializationError},
9 util::{Parser, Serializer},
10};
11
12#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
18pub struct InitResponse<T: AsRef<[u8]>> {
19 pub nonce: [u8; 8],
21 pub channel: Channel,
23 pub protocol_version: u8,
25 pub device_version: DeviceVersion,
27 pub capabilities: Capabilities,
29 pub rest: T,
31}
32
33impl<T: AsRef<[u8]>> InitResponse<T> {
34 pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize, SerializationError> {
36 let mut serializer = Serializer::new(buffer);
37 serializer.push_slice(&self.nonce)?;
38 serializer.push_slice(&self.channel.to_bytes())?;
39 serializer.push_slice(&[self.protocol_version])?;
40 serializer.push_slice(&self.device_version.to_bytes())?;
41 serializer.push_slice(&[self.capabilities.bits()])?;
42 serializer.push_slice(self.rest.as_ref())?;
43 Ok(serializer.bytes_written())
44 }
45}
46
47impl<'a, T: AsRef<[u8]> + TryFrom<&'a [u8]>> TryFrom<&'a [u8]> for InitResponse<T> {
48 type Error = ParseError;
49
50 fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
51 let mut parser = Parser::new(data);
52 let nonce = parser.take_array()?;
53 let channel = parser.take_into()?;
54 let protocol_version = parser.take()?;
55 let device_version = parser.take_into()?;
56 let capabilities = parser.take()?;
57 let rest = parser.into_rest();
58
59 Ok(Self {
60 nonce,
61 channel,
62 protocol_version,
63 device_version,
64 capabilities: Capabilities::from_bits_truncate(capabilities),
65 rest: rest
66 .try_into()
67 .map_err(|_| ParseError::BufferCreationFailed)?,
68 })
69 }
70}
71
72#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
78pub struct DeviceVersion {
79 pub major: u8,
81 pub minor: u8,
83 pub build: u8,
85}
86
87impl DeviceVersion {
88 pub fn to_bytes(self) -> [u8; 3] {
90 self.into()
91 }
92}
93
94impl From<DeviceVersion> for [u8; 3] {
95 fn from(version: DeviceVersion) -> Self {
96 [version.major, version.minor, version.build]
97 }
98}
99
100impl From<&[u8; 3]> for DeviceVersion {
101 fn from(data: &[u8; 3]) -> Self {
102 Self {
103 major: data[0],
104 minor: data[1],
105 build: data[2],
106 }
107 }
108}
109
110bitflags::bitflags! {
111 #[derive(Default)]
117 pub struct Capabilities: u8 {
118 const WINK = 0x01;
120 const CBOR = 0x04;
122 const NMSG = 0x08;
124 }
125}
126
127impl Capabilities {
128 pub fn has_wink(&self) -> bool {
130 self.contains(Self::WINK)
131 }
132
133 pub fn has_cbor(&self) -> bool {
135 self.contains(Self::CBOR)
136 }
137
138 pub fn has_msg(&self) -> bool {
140 !self.contains(Self::NMSG)
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use std::convert::TryFrom as _;
147
148 use quickcheck::{Arbitrary, TestResult};
149
150 use super::{Capabilities, DeviceVersion, InitResponse};
151
152 impl Arbitrary for Capabilities {
153 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
154 Self::from_bits_truncate(Arbitrary::arbitrary(g))
155 }
156 }
157
158 impl Arbitrary for DeviceVersion {
159 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
160 Self {
161 major: Arbitrary::arbitrary(g),
162 minor: Arbitrary::arbitrary(g),
163 build: Arbitrary::arbitrary(g),
164 }
165 }
166 }
167
168 impl Arbitrary for InitResponse<Vec<u8>> {
169 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
170 Self {
171 nonce: [
172 Arbitrary::arbitrary(g),
173 Arbitrary::arbitrary(g),
174 Arbitrary::arbitrary(g),
175 Arbitrary::arbitrary(g),
176 Arbitrary::arbitrary(g),
177 Arbitrary::arbitrary(g),
178 Arbitrary::arbitrary(g),
179 Arbitrary::arbitrary(g),
180 ],
181 channel: Arbitrary::arbitrary(g),
182 protocol_version: Arbitrary::arbitrary(g),
183 device_version: Arbitrary::arbitrary(g),
184 capabilities: Arbitrary::arbitrary(g),
185 rest: Arbitrary::arbitrary(g),
186 }
187 }
188
189 fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
190 let nonce = self.nonce;
191 let channel = self.channel;
192 let protocol_version = self.protocol_version;
193 let device_version = self.device_version;
194 let capabilities = self.capabilities;
195 Box::new(self.rest.shrink().map(move |rest| Self {
196 nonce,
197 channel,
198 protocol_version,
199 device_version,
200 capabilities,
201 rest,
202 }))
203 }
204 }
205
206 quickcheck::quickcheck! {
207 fn parse_init(data: Vec<u8>) -> bool {
208 let _ = InitResponse::<Vec<u8>>::try_from(data.as_slice());
209 true
210 }
211 }
212
213 quickcheck::quickcheck! {
214 fn serialize_init(init: InitResponse<Vec<u8>>) -> bool {
215 let mut buffer = vec![0; init.rest.len() + 17];
216 let _ = init.serialize(&mut buffer);
217 true
218 }
219 }
220
221 quickcheck::quickcheck! {
222 fn serialize_parse_init(init: InitResponse<Vec<u8>>) -> TestResult {
223 let mut buffer = vec![0; init.rest.len() + 17];
224 let n = init.serialize(&mut buffer).unwrap();
225 let parsed = InitResponse::try_from(&buffer[..n]).unwrap();
226 TestResult::from_bool(init == parsed)
227 }
228 }
229}