1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use crate::{Result, Tag};

#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum ASN1TimeZone {
    /// No timezone provided
    Undefined,
    /// Coordinated universal time
    Z,
    /// Local zone, with offset to coordinated universal time
    Offset(i8, u16, u16),
}

#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ASN1DateTime {
    pub year: u32,
    pub month: u16,
    pub day: u16,
    pub hour: u16,
    pub minute: u16,
    pub second: u16,
    pub millisecond: Option<u32>,
    pub tz: ASN1TimeZone,
}

impl ASN1DateTime {
    #[allow(clippy::too_many_arguments)]
    pub const fn new(
        year: u32,
        month: u16,
        day: u16,
        hour: u16,
        minute: u16,
        second: u16,
        millisecond: Option<u32>,
        tz: ASN1TimeZone,
    ) -> Self {
        ASN1DateTime {
            year,
            month,
            day,
            hour,
            minute,
            second,
            millisecond,
            tz,
        }
    }
}

/// Decode 2-digit decimal value
pub(crate) fn decode_decimal(tag: Tag, hi: u8, lo: u8) -> Result<u16> {
    if (b'0'..=b'9').contains(&hi) && (b'0'..=b'9').contains(&lo) {
        Ok((hi - b'0') as u16 * 10 + (lo - b'0') as u16)
    } else {
        Err(tag.invalid_value("expected digit"))
    }
}