1use serde::{Deserialize, Serialize};
6
7use crate::{Error, Result};
8
9#[derive(Debug, Serialize, Deserialize)]
11pub struct OctetString<'a>(&'a str);
12
13impl<'a> OctetString<'a> {
14 pub fn parse(body: &'a str, length: usize) -> Result<OctetString<'a>> {
16 Ok(OctetString(
17 body.get(1..=length).ok_or(Error::InvalidFormat)?,
18 ))
19 }
20
21 pub fn parse_max(body: &'a str, max_length: usize) -> Result<OctetString<'a>> {
23 let end = body.find(')').ok_or(Error::InvalidFormat)? - 1;
24 if end > max_length {
25 return Err(Error::InvalidFormat);
26 }
27
28 OctetString::parse(body, end)
29 }
30
31 pub fn as_octets(&'a self) -> impl core::iter::Iterator<Item = Result<u8>> + 'a {
33 (0..self.0.len() / 2).map(move |i| {
34 u8::from_str_radix(&self.0[i * 2..=i * 2 + 1], 16).map_err(|_| Error::InvalidFormat)
35 })
36 }
37}
38
39#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
41pub struct TST {
42 pub year: u8,
43 pub month: u8,
44 pub day: u8,
45 pub hour: u8,
46 pub minute: u8,
47 pub second: u8,
48
49 pub dst: bool,
51}
52
53impl TST {
54 pub fn parse(body: &str) -> Result<TST> {
55 if body.len() < 15 {
56 return Err(Error::InvalidFormat);
57 }
58
59 let parsetwo = |i| body[i..=(i + 1)].parse().map_err(|_| Error::InvalidFormat);
60
61 Ok(TST {
62 year: parsetwo(1)?,
63 month: parsetwo(3)?,
64 day: parsetwo(5)?,
65 hour: parsetwo(7)?,
66 minute: parsetwo(9)?,
67 second: parsetwo(11)?,
68 dst: match &body[13..=13] {
69 "S" => Ok(true),
70 "W" => Ok(false),
71 _ => Err(Error::InvalidFormat),
72 }?,
73 })
74 }
75}
76
77#[derive(Debug, Serialize, Deserialize)]
79pub struct UFixedDouble {
80 buffer: u64,
81 point: u8,
82}
83
84impl UFixedDouble {
85 pub fn parse(body: &str, length: usize, point: u8) -> Result<UFixedDouble> {
86 let buffer = body.get(1..length + 2).ok_or(Error::InvalidFormat)?;
88 let (upper, lower) = buffer.split_at(length - point as usize);
89
90 let upper: u64 = upper.parse().map_err(|_| Error::InvalidFormat)?;
91 let lower: u64 = lower[1..].parse().map_err(|_| Error::InvalidFormat)?;
92
93 Ok(UFixedDouble {
94 buffer: upper * 10u64.pow(u32::from(point)) + lower,
95 point,
96 })
97 }
98}
99
100impl core::convert::From<&UFixedDouble> for f64 {
101 fn from(other: &UFixedDouble) -> Self {
102 other.buffer as f64 / (10u64.pow(u32::from(other.point)) as f64)
103 }
104}
105
106#[derive(Debug)]
108pub struct UFixedInteger(pub u64);
109
110impl UFixedInteger {
111 pub fn parse(body: &str, length: usize) -> Result<UFixedInteger> {
112 let buffer = body.get(1..=length).ok_or(Error::InvalidFormat)?;
113 let number = buffer.parse().map_err(|_| Error::InvalidFormat)?;
114
115 Ok(UFixedInteger(number))
116 }
117}