use std::rc::Rc;
use crate::ap::open;
use crate::{card, nfc, Card};
const DF_NAME: [u8; 10] = [0xD3, 0x92, 0x10, 0x00, 0x31, 0x00, 0x01, 0x01, 0x04, 0x08];
const EF_MY_NUMBER: [u8; 2] = [0x00, 0x01];
const EF_ATTRIBUTES: [u8; 2] = [0x00, 0x02];
const EF_PIN: [u8; 2] = [0x00, 0x11];
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Sex {
Male,
Female,
NotApplicable,
Unknown,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Attributes {
#[cfg_attr(feature = "serde", serde(skip_serializing))]
_header: Vec<u8>,
pub name: String,
pub address: String,
pub date_of_birth: String,
pub sex: Sex,
}
impl<'a> From<&'a [u8]> for Attributes {
fn from(buf: &'a [u8]) -> Self {
crate::der::Reader::new(buf).in_sequence(|reader| Self {
_header: Vec::from(reader.read_auto()),
name: reader.read_string(),
address: reader.read_string(),
date_of_birth: reader.read_string(),
sex: {
use Sex::*;
match reader.read_str().clone().as_ref() {
"1" => Male,
"2" => Female,
"9" => NotApplicable,
_ => Unknown,
}
},
})
}
}
pub struct SupportAp<T, Ctx>
where
T: nfc::HandlerInCtx<Ctx>,
Ctx: Copy,
{
card: Rc<Card<T, Ctx>>,
}
impl<T, Ctx> SupportAp<T, Ctx>
where
T: nfc::HandlerInCtx<Ctx>,
Ctx: Copy,
{
open!(T, Ctx, DF_NAME);
pub fn read_my_number_raw(&self, ctx: Ctx, pin: Vec<u8>) -> Result<Vec<u8>, card::Error> {
self.verify_pin(ctx, pin)
.and_then(|_| self.card.select_ef(ctx, EF_MY_NUMBER.into()))
.and_then(|_| self.card.read(ctx, Some(17)))
}
pub fn read_my_number(&self, ctx: Ctx, pin: Vec<u8>) -> Result<String, card::Error> {
self.read_my_number_raw(ctx, pin).map(|buf| {
String::from_utf8_lossy(crate::der::Reader::new(&buf).read_auto()).to_string()
})
}
pub fn read_attributes_raw(&self, ctx: Ctx, pin: Vec<u8>) -> Result<Vec<u8>, card::Error> {
self.verify_pin(ctx, pin)
.and_then(|_| self.card.select_ef(ctx, EF_ATTRIBUTES.into()))
.and_then(|_| self.card.read_der_size(ctx))
.and_then(|size| self.card.read(ctx, Some(size)))
}
pub fn read_attributes(&self, ctx: Ctx, pin: Vec<u8>) -> Result<Attributes, card::Error> {
self.read_attributes_raw(ctx, pin)
.map(|attrs| Attributes::from(attrs.as_slice()))
}
pub fn pin_status(&self, ctx: Ctx) -> Result<u8, card::Error> {
self.card.pin_status(ctx, EF_PIN)
}
fn verify_pin(&self, ctx: Ctx, pin: Vec<u8>) -> Result<(), card::Error> {
self.card.verify_pin(ctx, EF_PIN, pin)
}
}