use serde::{Deserialize, Serialize};
use crate::{Error, Result};
#[derive(Debug, Serialize, Deserialize)]
pub struct OctetString<'a>(&'a str);
impl<'a> OctetString<'a> {
pub fn parse(body: &'a str, length: usize) -> Result<OctetString<'a>> {
Ok(OctetString(
body.get(1..=length).ok_or(Error::InvalidFormat)?,
))
}
pub fn parse_max(body: &'a str, max_length: usize) -> Result<OctetString<'a>> {
let end = body.find(')').ok_or(Error::InvalidFormat)? - 1;
if end > max_length {
return Err(Error::InvalidFormat);
}
OctetString::parse(body, end)
}
pub fn as_octets(&'a self) -> impl core::iter::Iterator<Item = Result<u8>> + 'a {
(0..self.0.len() / 2).map(move |i| {
u8::from_str_radix(&self.0[i * 2..=i * 2 + 1], 16).map_err(|_| Error::InvalidFormat)
})
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct TST {
pub year: u8,
pub month: u8,
pub day: u8,
pub hour: u8,
pub minute: u8,
pub second: u8,
pub dst: bool,
}
impl TST {
pub fn parse(body: &str) -> Result<TST> {
if body.len() < 15 {
return Err(Error::InvalidFormat);
}
let parsetwo = |i| body[i..=(i + 1)].parse().map_err(|_| Error::InvalidFormat);
Ok(TST {
year: parsetwo(1)?,
month: parsetwo(3)?,
day: parsetwo(5)?,
hour: parsetwo(7)?,
minute: parsetwo(9)?,
second: parsetwo(11)?,
dst: match &body[13..=13] {
"S" => Ok(true),
"W" => Ok(false),
_ => Err(Error::InvalidFormat),
}?,
})
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UFixedDouble {
buffer: u64,
point: u8,
}
impl UFixedDouble {
pub fn parse(body: &str, length: usize, point: u8) -> Result<UFixedDouble> {
let buffer = body.get(1..length + 2).ok_or(Error::InvalidFormat)?;
let (upper, lower) = buffer.split_at(length - point as usize);
let upper: u64 = upper.parse().map_err(|_| Error::InvalidFormat)?;
let lower: u64 = lower[1..].parse().map_err(|_| Error::InvalidFormat)?;
Ok(UFixedDouble {
buffer: upper * 10u64.pow(u32::from(point)) + lower,
point,
})
}
}
impl core::convert::From<&UFixedDouble> for f64 {
fn from(other: &UFixedDouble) -> Self {
other.buffer as f64 / (10u64.pow(u32::from(other.point)) as f64)
}
}
#[derive(Debug)]
pub struct UFixedInteger(pub u64);
impl UFixedInteger {
pub fn parse(body: &str, length: usize) -> Result<UFixedInteger> {
let buffer = body.get(1..=length).ok_or(Error::InvalidFormat)?;
let number = buffer.parse().map_err(|_| Error::InvalidFormat)?;
Ok(UFixedInteger(number))
}
}