use std::convert::TryFrom;
use chrono::{DateTime, NaiveDateTime, Utc};
use nom::{combinator, number::complete as number, sequence};
use crate::card_do::{KeyGenerationTime, KeySet};
use crate::Error;
impl From<KeyGenerationTime> for DateTime<Utc> {
fn from(kg: KeyGenerationTime) -> Self {
let naive_datetime = NaiveDateTime::from_timestamp_opt(kg.0 as i64, 0)
.expect("invalid or out-of-range datetime");
DateTime::from_naive_utc_and_offset(naive_datetime, Utc)
}
}
impl From<&KeyGenerationTime> for u32 {
fn from(kg: &KeyGenerationTime) -> Self {
kg.0
}
}
impl From<u32> for KeyGenerationTime {
fn from(data: u32) -> Self {
Self(data)
}
}
fn gen_time(input: &[u8]) -> nom::IResult<&[u8], u32> {
(number::be_u32)(input)
}
fn key_generation(input: &[u8]) -> nom::IResult<&[u8], Option<KeyGenerationTime>> {
combinator::map(gen_time, |kg| match kg {
0 => None,
kg => Some(KeyGenerationTime(kg)),
})(input)
}
fn key_generation_set(input: &[u8]) -> nom::IResult<&[u8], KeySet<KeyGenerationTime>> {
combinator::into(sequence::tuple((
key_generation,
key_generation,
key_generation,
)))(input)
}
impl TryFrom<&[u8]> for KeySet<KeyGenerationTime> {
type Error = Error;
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
log::trace!(
"Key generation times from input: {:x?}, len {}",
input,
input.len()
);
self::key_generation_set(input)
.map(|res| res.1)
.map_err(|_err| Error::ParseError("Parsing failed".to_string()))
}
}
#[cfg(test)]
mod test {
use std::convert::TryInto;
use super::*;
#[test]
fn test() {
let data3 = [
0x60, 0xf3, 0xff, 0x71, 0x60, 0xf3, 0xff, 0x72, 0x60, 0xf3, 0xff, 0x83,
];
let fp_set: KeySet<KeyGenerationTime> = (&data3[..])
.try_into()
.expect("failed to parse KeyGenerationTime set");
assert_eq!(fp_set.signature().unwrap().get(), 0x60f3ff71);
assert_eq!(fp_set.decryption().unwrap().get(), 0x60f3ff72);
assert_eq!(fp_set.authentication().unwrap().get(), 0x60f3ff83);
}
}