use crate::error::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum FunctionCode {
ContactStatus = 1,
OutputControl = 2,
CardDataFormat = 3,
LedControl = 4,
AudibleOutput = 5,
TextOutput = 6,
TimeKeeping = 7,
CheckCharacter = 8,
CommunicationSecurity = 9,
ReceiveBufferSize = 10,
LargestCombinedSize = 11,
SmartCardSupport = 12,
Readers = 13,
Biometrics = 14,
SecurePinEntry = 15,
OsdpVersion = 16,
}
impl FunctionCode {
pub const fn from_byte(b: u8) -> Result<Self, Error> {
Ok(match b {
1 => Self::ContactStatus,
2 => Self::OutputControl,
3 => Self::CardDataFormat,
4 => Self::LedControl,
5 => Self::AudibleOutput,
6 => Self::TextOutput,
7 => Self::TimeKeeping,
8 => Self::CheckCharacter,
9 => Self::CommunicationSecurity,
10 => Self::ReceiveBufferSize,
11 => Self::LargestCombinedSize,
12 => Self::SmartCardSupport,
13 => Self::Readers,
14 => Self::Biometrics,
15 => Self::SecurePinEntry,
16 => Self::OsdpVersion,
other => {
return Err(Error::MalformedPayload {
code: other,
reason: "unknown PDCAP function code",
});
}
})
}
pub const fn as_byte(self) -> u8 {
self as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Capability {
pub code: u8,
pub compliance: u8,
pub number_of: u8,
}
impl Capability {
pub const WIRE_LEN: usize = 3;
pub const fn encode(self) -> [u8; 3] {
[self.code, self.compliance, self.number_of]
}
pub const fn decode(bytes: [u8; 3]) -> Self {
Self {
code: bytes[0],
compliance: bytes[1],
number_of: bytes[2],
}
}
pub fn function(self) -> Option<FunctionCode> {
FunctionCode::from_byte(self.code).ok()
}
pub const fn u16_value(self) -> u16 {
u16::from_le_bytes([self.compliance, self.number_of])
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rx_size_combined() {
let c = Capability {
code: FunctionCode::ReceiveBufferSize.as_byte(),
compliance: 0x80, number_of: 0x00,
};
assert_eq!(c.u16_value(), 128);
}
#[test]
fn function_roundtrip() {
for raw in 1u8..=16 {
let f = FunctionCode::from_byte(raw).unwrap();
assert_eq!(f.as_byte(), raw);
}
}
}