ctaphid_types/
command.rs

1// Copyright (C) 2021 Robin Krahl <robin.krahl@ireas.org>
2// SPDX-License-Identifier: Apache-2.0 or MIT
3
4/// A CTAPHID command.
5///
6/// See [§ 11.2.9 of the CTAP specification][spec].
7///
8/// [spec]: https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#usb-commands
9#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
10pub enum Command {
11    /// The message command.
12    Message,
13    /// The CBOR command.
14    Cbor,
15    /// The init command.
16    Init,
17    /// The ping command.
18    Ping,
19    /// The cancel command.
20    Cancel,
21    /// The error command.
22    Error,
23    /// The keep alive command.
24    KeepAlive,
25    /// The wink command.
26    Wink,
27    /// The lock command.
28    Lock,
29    /// A vendor command.
30    Vendor(VendorCommand),
31    /// An unknown command.
32    Unknown(u8),
33}
34
35impl From<Command> for u8 {
36    fn from(command: Command) -> Self {
37        match command {
38            Command::Message => 0x03,
39            Command::Cbor => 0x10,
40            Command::Init => 0x06,
41            Command::Ping => 0x01,
42            Command::Cancel => 0x11,
43            Command::Error => 0x3f,
44            Command::KeepAlive => 0x3b,
45            Command::Wink => 0x08,
46            Command::Lock => 0x04,
47            Command::Vendor(command) => command.into(),
48            Command::Unknown(command) => command,
49        }
50    }
51}
52
53impl From<u8> for Command {
54    fn from(value: u8) -> Self {
55        match value {
56            0x01 => Self::Ping,
57            0x03 => Self::Message,
58            0x04 => Self::Lock,
59            0x06 => Self::Init,
60            0x08 => Self::Wink,
61            0x10 => Self::Cbor,
62            0x11 => Self::Cancel,
63            0x3b => Self::KeepAlive,
64            0x3f => Self::Error,
65            _ => VendorCommand::new(value).map_or(Command::Unknown(value), Command::Vendor),
66        }
67    }
68}
69
70/// A CTAPHID vendor command.
71///
72/// See [§ 11.2.9.3 of the CTAP specification][spec].
73///
74/// [spec]: https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#usb-vendor-specific-commands
75#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
76pub struct VendorCommand(u8);
77
78impl VendorCommand {
79    const FIRST: u8 = 0x40;
80    const LAST: u8 = 0x7f;
81
82    /// The range for valid vendor command IDs.
83    pub const RANGE: core::ops::RangeInclusive<u8> = (Self::FIRST..=Self::LAST);
84
85    /// The vendor-specific command with the ID 0x40.
86    pub const H40: VendorCommand = VendorCommand(0x40);
87    /// The vendor-specific command with the ID 0x41.
88    pub const H41: VendorCommand = VendorCommand(0x41);
89    /// The vendor-specific command with the ID 0x42.
90    pub const H42: VendorCommand = VendorCommand(0x42);
91    /// The vendor-specific command with the ID 0x43.
92    pub const H43: VendorCommand = VendorCommand(0x43);
93    /// The vendor-specific command with the ID 0x44.
94    pub const H44: VendorCommand = VendorCommand(0x44);
95    /// The vendor-specific command with the ID 0x45.
96    pub const H45: VendorCommand = VendorCommand(0x45);
97    /// The vendor-specific command with the ID 0x46.
98    pub const H46: VendorCommand = VendorCommand(0x46);
99    /// The vendor-specific command with the ID 0x47.
100    pub const H47: VendorCommand = VendorCommand(0x47);
101    /// The vendor-specific command with the ID 0x48.
102    pub const H48: VendorCommand = VendorCommand(0x48);
103    /// The vendor-specific command with the ID 0x49.
104    pub const H49: VendorCommand = VendorCommand(0x49);
105    /// The vendor-specific command with the ID 0x4a.
106    pub const H4A: VendorCommand = VendorCommand(0x4a);
107    /// The vendor-specific command with the ID 0x4b.
108    pub const H4B: VendorCommand = VendorCommand(0x4b);
109    /// The vendor-specific command with the ID 0x4c.
110    pub const H4C: VendorCommand = VendorCommand(0x4c);
111    /// The vendor-specific command with the ID 0x4d.
112    pub const H4D: VendorCommand = VendorCommand(0x4d);
113    /// The vendor-specific command with the ID 0x4e.
114    pub const H4E: VendorCommand = VendorCommand(0x4e);
115    /// The vendor-specific command with the ID 0x4f.
116    pub const H4F: VendorCommand = VendorCommand(0x4f);
117    /// The vendor-specific command with the ID 0x50.
118    pub const H50: VendorCommand = VendorCommand(0x50);
119    /// The vendor-specific command with the ID 0x51.
120    pub const H51: VendorCommand = VendorCommand(0x51);
121    /// The vendor-specific command with the ID 0x52.
122    pub const H52: VendorCommand = VendorCommand(0x52);
123    /// The vendor-specific command with the ID 0x53.
124    pub const H53: VendorCommand = VendorCommand(0x53);
125    /// The vendor-specific command with the ID 0x54.
126    pub const H54: VendorCommand = VendorCommand(0x54);
127    /// The vendor-specific command with the ID 0x55.
128    pub const H55: VendorCommand = VendorCommand(0x55);
129    /// The vendor-specific command with the ID 0x56.
130    pub const H56: VendorCommand = VendorCommand(0x56);
131    /// The vendor-specific command with the ID 0x57.
132    pub const H57: VendorCommand = VendorCommand(0x57);
133    /// The vendor-specific command with the ID 0x58.
134    pub const H58: VendorCommand = VendorCommand(0x58);
135    /// The vendor-specific command with the ID 0x59.
136    pub const H59: VendorCommand = VendorCommand(0x59);
137    /// The vendor-specific command with the ID 0x5a.
138    pub const H5A: VendorCommand = VendorCommand(0x5a);
139    /// The vendor-specific command with the ID 0x5b.
140    pub const H5B: VendorCommand = VendorCommand(0x5b);
141    /// The vendor-specific command with the ID 0x5c.
142    pub const H5C: VendorCommand = VendorCommand(0x5c);
143    /// The vendor-specific command with the ID 0x5d.
144    pub const H5D: VendorCommand = VendorCommand(0x5d);
145    /// The vendor-specific command with the ID 0x5e.
146    pub const H5E: VendorCommand = VendorCommand(0x5e);
147    /// The vendor-specific command with the ID 0x5f.
148    pub const H5F: VendorCommand = VendorCommand(0x5f);
149    /// The vendor-specific command with the ID 0x60.
150    pub const H60: VendorCommand = VendorCommand(0x60);
151    /// The vendor-specific command with the ID 0x61.
152    pub const H61: VendorCommand = VendorCommand(0x61);
153    /// The vendor-specific command with the ID 0x62.
154    pub const H62: VendorCommand = VendorCommand(0x62);
155    /// The vendor-specific command with the ID 0x63.
156    pub const H63: VendorCommand = VendorCommand(0x63);
157    /// The vendor-specific command with the ID 0x64.
158    pub const H64: VendorCommand = VendorCommand(0x64);
159    /// The vendor-specific command with the ID 0x65.
160    pub const H65: VendorCommand = VendorCommand(0x65);
161    /// The vendor-specific command with the ID 0x66.
162    pub const H66: VendorCommand = VendorCommand(0x66);
163    /// The vendor-specific command with the ID 0x67.
164    pub const H67: VendorCommand = VendorCommand(0x67);
165    /// The vendor-specific command with the ID 0x68.
166    pub const H68: VendorCommand = VendorCommand(0x68);
167    /// The vendor-specific command with the ID 0x69.
168    pub const H69: VendorCommand = VendorCommand(0x69);
169    /// The vendor-specific command with the ID 0x6a.
170    pub const H6A: VendorCommand = VendorCommand(0x6a);
171    /// The vendor-specific command with the ID 0x6b.
172    pub const H6B: VendorCommand = VendorCommand(0x6b);
173    /// The vendor-specific command with the ID 0x6c.
174    pub const H6C: VendorCommand = VendorCommand(0x6c);
175    /// The vendor-specific command with the ID 0x6d.
176    pub const H6D: VendorCommand = VendorCommand(0x6d);
177    /// The vendor-specific command with the ID 0x6e.
178    pub const H6E: VendorCommand = VendorCommand(0x6e);
179    /// The vendor-specific command with the ID 0x6f.
180    pub const H6F: VendorCommand = VendorCommand(0x6f);
181    /// The vendor-specific command with the ID 0x70.
182    pub const H70: VendorCommand = VendorCommand(0x70);
183    /// The vendor-specific command with the ID 0x71.
184    pub const H71: VendorCommand = VendorCommand(0x71);
185    /// The vendor-specific command with the ID 0x72.
186    pub const H72: VendorCommand = VendorCommand(0x72);
187    /// The vendor-specific command with the ID 0x73.
188    pub const H73: VendorCommand = VendorCommand(0x73);
189    /// The vendor-specific command with the ID 0x74.
190    pub const H74: VendorCommand = VendorCommand(0x74);
191    /// The vendor-specific command with the ID 0x75.
192    pub const H75: VendorCommand = VendorCommand(0x75);
193    /// The vendor-specific command with the ID 0x76.
194    pub const H76: VendorCommand = VendorCommand(0x76);
195    /// The vendor-specific command with the ID 0x77.
196    pub const H77: VendorCommand = VendorCommand(0x77);
197    /// The vendor-specific command with the ID 0x78.
198    pub const H78: VendorCommand = VendorCommand(0x78);
199    /// The vendor-specific command with the ID 0x79.
200    pub const H79: VendorCommand = VendorCommand(0x79);
201    /// The vendor-specific command with the ID 0x7a.
202    pub const H7A: VendorCommand = VendorCommand(0x7a);
203    /// The vendor-specific command with the ID 0x7b.
204    pub const H7B: VendorCommand = VendorCommand(0x7b);
205    /// The vendor-specific command with the ID 0x7c.
206    pub const H7C: VendorCommand = VendorCommand(0x7c);
207    /// The vendor-specific command with the ID 0x7d.
208    pub const H7D: VendorCommand = VendorCommand(0x7d);
209    /// The vendor-specific command with the ID 0x7e.
210    pub const H7E: VendorCommand = VendorCommand(0x7e);
211    /// The vendor-specific command with the ID 0x7f.
212    pub const H7F: VendorCommand = VendorCommand(0x7f);
213
214    /// Creates a new `VendorCommand` from the given command ID if it is within [`Self::RANGE`][].
215    pub fn new(id: u8) -> Option<Self> {
216        if Self::RANGE.contains(&id) {
217            Some(Self(id))
218        } else {
219            None
220        }
221    }
222}
223
224impl From<VendorCommand> for u8 {
225    fn from(command: VendorCommand) -> u8 {
226        command.0
227    }
228}
229
230#[cfg(test)]
231mod test {
232    use super::{Command, VendorCommand};
233
234    impl quickcheck::Arbitrary for Command {
235        fn arbitrary(g: &mut quickcheck::Gen) -> Self {
236            u8::arbitrary(g).into()
237        }
238
239        fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
240            Box::new(u8::from(*self).shrink().map(From::from))
241        }
242    }
243
244    impl quickcheck::Arbitrary for VendorCommand {
245        fn arbitrary(g: &mut quickcheck::Gen) -> Self {
246            let n = VendorCommand::RANGE.end() - VendorCommand::RANGE.start() + 1;
247            let command = u8::arbitrary(g) % n + VendorCommand::RANGE.start();
248            VendorCommand::new(command).unwrap()
249        }
250    }
251}