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
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use crate::DgcCert;
use serde::{
    de::{MapAccess, Visitor},
    Deserialize, Serialize,
};
use std::collections::HashMap;

const ISSUER: i64 = 1;
const ISSUED_AT: i64 = 6;
const EXPIRATION_TIME: i64 = 4;
const CERTS: i64 = -260;

#[derive(Serialize, Debug, Clone, PartialEq)]
pub struct DgcCertContainer {
    #[serde(alias = "1")]
    #[serde(rename(serialize = "1"))]
    pub issuer: String,
    #[serde(alias = "6")]
    #[serde(rename(serialize = "6"))]
    pub issued_at: IntegerOrFloat,
    #[serde(alias = "4")]
    #[serde(rename(serialize = "4"))]
    pub expiration_time: IntegerOrFloat,
    #[serde(alias = "-260")]
    #[serde(rename(serialize = "-260"))]
    pub certs: HashMap<usize, DgcCert>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum IntegerOrFloat {
    Float(f64),
    Integer(u64),
}

impl DgcCertContainer {
    pub fn expand_values(&mut self) {
        self.certs.iter_mut().for_each(|(_, t)| t.expand_values());
    }
}

struct DgcCertContainerVisitor;

impl<'de> Visitor<'de> for DgcCertContainerVisitor {
    type Value = DgcCertContainer;

    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        formatter.write_str("struct DgcCertContainer")
    }

    fn visit_map<V>(self, mut map: V) -> Result<DgcCertContainer, V::Error>
    where
        V: MapAccess<'de>,
    {
        let mut issuer = None;
        let mut issued_at = None;
        let mut expiration_time = None;
        let mut certs = None;

        while let Some(key) = map.next_key()? {
            match key {
                ISSUER => {
                    if issuer.is_some() {
                        return Err(serde::de::Error::duplicate_field("issuer"));
                    }
                    issuer = Some(map.next_value()?);
                }
                ISSUED_AT => {
                    if issued_at.is_some() {
                        return Err(serde::de::Error::duplicate_field("issued_at"));
                    }
                    issued_at = Some(map.next_value()?);
                }
                EXPIRATION_TIME => {
                    if expiration_time.is_some() {
                        return Err(serde::de::Error::duplicate_field("expiration_time"));
                    }
                    expiration_time = Some(map.next_value()?);
                }
                CERTS => {
                    if certs.is_some() {
                        return Err(serde::de::Error::duplicate_field("certs"));
                    }
                    certs = Some(map.next_value()?);
                }
                _ => {
                    // ignore other fields
                }
            }
        }
        let issuer = issuer.ok_or_else(|| serde::de::Error::missing_field("issuer"))?;
        let issued_at = issued_at.ok_or_else(|| serde::de::Error::missing_field("issued_at"))?;
        let expiration_time =
            expiration_time.ok_or_else(|| serde::de::Error::missing_field("expiration_time"))?;
        let certs = certs.ok_or_else(|| serde::de::Error::missing_field("certs"))?;

        Ok(DgcCertContainer {
            issuer,
            issued_at,
            expiration_time,
            certs,
        })
    }
}

/// Needs a specialized deserializer to be able to deal with keys as integers
impl<'de> Deserialize<'de> for DgcCertContainer {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        deserializer.deserialize_map(DgcCertContainerVisitor)
    }
}