use super::status::SW;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response {
pub data: Vec<u8>,
pub sw1: u8,
pub sw2: u8,
}
impl Response {
pub fn new(data: Vec<u8>, sw: u16) -> Self {
Self {
data,
sw1: (sw >> 8) as u8,
sw2: sw as u8,
}
}
pub fn success(data: Vec<u8>) -> Self {
Self::new(data, SW::SUCCESS)
}
pub fn ok() -> Self {
Self::success(Vec::new())
}
pub fn error(sw: u16) -> Self {
Self::new(Vec::new(), sw)
}
pub fn more_data(data: Vec<u8>, remaining: u8) -> Self {
Self::new(data, SW::bytes_remaining(remaining))
}
pub fn counter_warning(retries: u8) -> Self {
Self::error(SW::counter_warning(retries))
}
pub fn is_okay(&self) -> bool {
(self.sw1 == 0x90 && self.sw2 == 0x00) || self.sw1 == 0x61
}
pub fn sw(&self) -> u16 {
((self.sw1 as u16) << 8) | (self.sw2 as u16)
}
pub fn available_response(&self) -> Option<u8> {
if self.sw1 == 0x61 {
Some(self.sw2)
} else {
None
}
}
pub fn get_data(&self) -> Vec<u8> {
self.data.clone()
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::with_capacity(self.data.len() + 2);
result.extend_from_slice(&self.data);
result.push(self.sw1);
result.push(self.sw2);
result
}
pub fn len(&self) -> usize {
self.data.len() + 2
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
impl Default for Response {
fn default() -> Self {
Self::ok()
}
}
impl From<u16> for Response {
fn from(sw: u16) -> Self {
Self::error(sw)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_success_response() {
let resp = Response::success(vec![0xDE, 0xAD, 0xBE, 0xEF]);
assert!(resp.is_okay());
assert_eq!(resp.sw(), 0x9000);
assert_eq!(resp.get_data(), vec![0xDE, 0xAD, 0xBE, 0xEF]);
assert_eq!(resp.to_bytes(), vec![0xDE, 0xAD, 0xBE, 0xEF, 0x90, 0x00]);
}
#[test]
fn test_ok_response() {
let resp = Response::ok();
assert!(resp.is_okay());
assert!(resp.is_empty());
assert_eq!(resp.to_bytes(), vec![0x90, 0x00]);
}
#[test]
fn test_error_response() {
let resp = Response::error(SW::SECURITY_STATUS_NOT_SATISFIED);
assert!(!resp.is_okay());
assert_eq!(resp.sw(), 0x6982);
assert_eq!(resp.to_bytes(), vec![0x69, 0x82]);
}
#[test]
fn test_more_data_response() {
let resp = Response::more_data(vec![0xAB], 16);
assert!(resp.is_okay()); assert_eq!(resp.available_response(), Some(16));
assert_eq!(resp.get_data(), vec![0xAB]);
}
#[test]
fn test_no_more_data() {
let resp = Response::ok();
assert_eq!(resp.available_response(), None);
}
#[test]
fn test_counter_warning() {
let resp = Response::counter_warning(2);
assert!(!resp.is_okay());
assert_eq!(resp.sw(), 0x63C2);
}
#[test]
fn test_from_sw() {
let resp: Response = 0x6A82.into();
assert_eq!(resp.sw(), SW::FILE_NOT_FOUND);
assert!(!resp.is_okay());
}
}