picky_asn1_x509/
validity.rs

1use picky_asn1::date::{GeneralizedTime, UTCTime};
2use picky_asn1::tag::TagPeeker;
3use picky_asn1::wrapper::{GeneralizedTimeAsn1, UtcTimeAsn1};
4use picky_asn1::Asn1Type;
5use serde::{de, ser, Deserialize, Serialize};
6use std::fmt;
7
8#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
9pub struct Validity {
10    pub not_before: Time,
11    pub not_after: Time,
12}
13
14#[derive(Debug, PartialEq, Eq, Clone)]
15pub enum Time {
16    Utc(UtcTimeAsn1),
17    Generalized(GeneralizedTimeAsn1),
18}
19
20impl From<UtcTimeAsn1> for Time {
21    fn from(time: UtcTimeAsn1) -> Self {
22        Self::Utc(time)
23    }
24}
25
26impl From<UTCTime> for Time {
27    fn from(time: UTCTime) -> Self {
28        Self::Utc(time.into())
29    }
30}
31
32impl From<GeneralizedTimeAsn1> for Time {
33    fn from(time: GeneralizedTimeAsn1) -> Self {
34        Self::Generalized(time)
35    }
36}
37
38impl From<GeneralizedTime> for Time {
39    fn from(time: GeneralizedTime) -> Self {
40        Self::Generalized(time.into())
41    }
42}
43
44impl ser::Serialize for Time {
45    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
46    where
47        S: ser::Serializer,
48    {
49        match &self {
50            Time::Utc(time) => time.serialize(serializer),
51            Time::Generalized(time) => time.serialize(serializer),
52        }
53    }
54}
55
56impl<'de> de::Deserialize<'de> for Time {
57    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
58    where
59        D: de::Deserializer<'de>,
60    {
61        struct Visitor;
62
63        impl<'de> de::Visitor<'de> for Visitor {
64            type Value = Time;
65
66            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
67                formatter.write_str("a valid DER-encoded Time")
68            }
69
70            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
71            where
72                A: de::SeqAccess<'de>,
73            {
74                let tag_peeker: TagPeeker = seq_next_element!(seq, Time, "choice tag");
75                match tag_peeker.next_tag {
76                    UtcTimeAsn1::TAG => Ok(Time::Utc(seq_next_element!(seq, Time, "UTCTime"))),
77                    GeneralizedTimeAsn1::TAG => Ok(Time::Generalized(seq_next_element!(seq, Time, "GeneralizedTime"))),
78                    _ => Err(serde_invalid_value!(
79                        Time,
80                        "invalid variant",
81                        "either UTCTime or GeneralizedTime"
82                    )),
83                }
84            }
85        }
86
87        deserializer.deserialize_enum("Time", &["UTC", "Generalized"], Visitor)
88    }
89}