1use crate::error::Error;
11use crate::payload_util::require_at_least;
12use alloc::vec::Vec;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16#[repr(u8)]
17#[allow(missing_docs)]
18pub enum XwrMode00 {
19 ReadMode = 0x01,
20 SetMode = 0x02,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25#[repr(u8)]
26#[allow(missing_docs)]
27pub enum XwrMode01 {
28 TransmitApdu = 0x01,
29 ConnectionDone = 0x02,
30 SecurePinEntry = 0x03,
31 SmartCardScan = 0x04,
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
38pub struct XWrite {
39 pub mode: u8,
41 pub payload: Vec<u8>,
43}
44
45impl XWrite {
46 pub fn encode(&self) -> Result<Vec<u8>, Error> {
48 let mut out = Vec::with_capacity(1 + self.payload.len());
49 out.push(self.mode);
50 out.extend_from_slice(&self.payload);
51 Ok(out)
52 }
53
54 pub fn decode(data: &[u8]) -> Result<Self, Error> {
56 require_at_least(data, 1, 0xA1)?;
57 Ok(Self {
58 mode: data[0],
59 payload: data[1..].to_vec(),
60 })
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn roundtrip() {
70 let body = XWrite {
71 mode: 0x01,
72 payload: alloc::vec![0x02, 0xDE, 0xAD],
73 };
74 let bytes = body.encode().unwrap();
75 assert_eq!(bytes, [0x01, 0x02, 0xDE, 0xAD]);
76 assert_eq!(XWrite::decode(&bytes).unwrap(), body);
77 }
78
79 #[test]
80 fn mode_only_is_valid() {
81 let body = XWrite {
82 mode: 0x00,
83 payload: Vec::new(),
84 };
85 let bytes = body.encode().unwrap();
86 assert_eq!(bytes, [0x00]);
87 assert_eq!(XWrite::decode(&bytes).unwrap(), body);
88 }
89
90 #[test]
91 fn empty_decode_rejected() {
92 assert!(matches!(
93 XWrite::decode(&[]),
94 Err(Error::PayloadTooShort { code: 0xA1, .. })
95 ));
96 }
97}