1use crate::error::Error;
6use crate::payload_util::require_at_least;
7use alloc::vec::Vec;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Keypad {
12 pub reader: u8,
14 pub digit_count: u8,
16 pub digits: Vec<u8>,
18}
19
20impl Keypad {
21 pub fn encode(&self) -> Result<Vec<u8>, Error> {
23 if self.digits.len() != self.digit_count as usize {
24 return Err(Error::MalformedPayload {
25 code: 0x53,
26 reason: "KEYPAD digit_count disagrees with digits",
27 });
28 }
29 let mut out = Vec::with_capacity(2 + self.digits.len());
30 out.push(self.reader);
31 out.push(self.digit_count);
32 out.extend_from_slice(&self.digits);
33 Ok(out)
34 }
35
36 pub fn decode(data: &[u8]) -> Result<Self, Error> {
38 require_at_least(data, 2, 0x53)?;
39 let digit_count = data[1];
40 if data.len() != 2 + digit_count as usize {
41 return Err(Error::MalformedPayload {
42 code: 0x53,
43 reason: "KEYPAD digit count disagrees with payload",
44 });
45 }
46 Ok(Self {
47 reader: data[0],
48 digit_count,
49 digits: data[2..].to_vec(),
50 })
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn roundtrip() {
60 let body = Keypad {
61 reader: 0x00,
62 digit_count: 3,
63 digits: alloc::vec![b'1', b'2', b'3'],
64 };
65 let bytes = body.encode().unwrap();
66 assert_eq!(bytes, [0x00, 3, b'1', b'2', b'3']);
67 assert_eq!(Keypad::decode(&bytes).unwrap(), body);
68 }
69
70 #[test]
71 fn encode_rejects_count_disagreement() {
72 let body = Keypad {
73 reader: 0,
74 digit_count: 5, digits: alloc::vec![b'1', b'2'], };
77 assert!(matches!(
78 body.encode(),
79 Err(Error::MalformedPayload { code: 0x53, .. })
80 ));
81 }
82
83 #[test]
84 fn decode_rejects_count_disagreement() {
85 assert!(matches!(
87 Keypad::decode(&[0x00, 4, b'1']),
88 Err(Error::MalformedPayload { code: 0x53, .. })
89 ));
90 }
91}