ssi_data_integrity_core/proof/de/
configuration.rs

1use crate::{
2    suite::bounds::{OptionsOf, VerificationMethodOf},
3    CryptosuiteString, DeserializeCryptographicSuite, ProofConfiguration, Type,
4};
5use serde::{
6    de::{DeserializeSeed, MapAccess},
7    Deserialize,
8};
9use ssi_core::de::WithType;
10use std::{collections::BTreeMap, marker::PhantomData};
11
12use super::{Field, FlatMapDeserializer, RefOrValue, ReplayMap, TypeField};
13
14impl<'de, T: DeserializeCryptographicSuite<'de>> ProofConfiguration<T> {
15    fn deserialize_with_type<S>(type_: Type, mut deserializer: S) -> Result<Self, S::Error>
16    where
17        S: serde::de::MapAccess<'de>,
18    {
19        let suite: T = type_
20            .try_into()
21            .map_err(|_| serde::de::Error::custom("unexpected cryptosuite"))?;
22
23        let mut context = None;
24        let mut created = None;
25        let mut verification_method = None;
26        let mut proof_purpose = None;
27        let mut expires = None;
28        let mut domains = None;
29        let mut challenge = None;
30        let mut nonce = None;
31
32        let mut other = Vec::new();
33
34        while let Some(key) = deserializer.next_key::<Field>()? {
35            match key {
36                Field::Context => context = Some(deserializer.next_value()?),
37                Field::Created => created = Some(deserializer.next_value()?),
38                Field::VerificationMethod => {
39                    verification_method = Some({
40                        deserializer
41                            .next_value_seed(
42                                WithType::<T, RefOrValue<VerificationMethodOf<T>>>::new(&suite),
43                            )?
44                    })
45                }
46                Field::ProofPurpose => proof_purpose = Some(deserializer.next_value()?),
47                Field::Expires => expires = Some(deserializer.next_value()?),
48                Field::Domains => domains = Some(deserializer.next_value()?),
49                Field::Challenge => challenge = Some(deserializer.next_value()?),
50                Field::Nonce => nonce = Some(deserializer.next_value()?),
51                Field::Other(key) => other.push(Some((key, deserializer.next_value()?))),
52            }
53        }
54
55        let options = WithType::<T, OptionsOf<T>>::new(&suite)
56            .deserialize(FlatMapDeserializer::new(&mut other))?
57            .0;
58
59        Ok(Self {
60            context,
61            type_: suite,
62            created,
63            verification_method: verification_method
64                .map(|v| v.map(VerificationMethodOf::unwrap).into())
65                .ok_or_else(|| serde::de::Error::custom("missing `verificationMethod` property"))?,
66            proof_purpose: proof_purpose
67                .ok_or_else(|| serde::de::Error::custom("missing `proofPurpose` property"))?,
68            expires,
69            domains: domains.unwrap_or_default(),
70            challenge,
71            nonce,
72            options,
73            extra_properties: BTreeMap::deserialize(FlatMapDeserializer::new(&mut other))?,
74        })
75    }
76}
77
78impl<'de, T: DeserializeCryptographicSuite<'de>> serde::Deserialize<'de> for ProofConfiguration<T> {
79    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
80    where
81        D: serde::Deserializer<'de>,
82    {
83        deserializer.deserialize_map(ProofConfigurationVisitor(PhantomData))
84    }
85}
86
87struct ProofConfigurationVisitor<T>(PhantomData<T>);
88
89impl<'de, T: DeserializeCryptographicSuite<'de>> serde::de::Visitor<'de>
90    for ProofConfigurationVisitor<T>
91{
92    type Value = ProofConfiguration<T>;
93
94    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
95        write!(formatter, "Data-Integrity proof")
96    }
97
98    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
99    where
100        A: MapAccess<'de>,
101    {
102        let mut keep = Vec::new();
103        let mut cryptosuite = None;
104        let mut data_integrity_proof = false;
105
106        while let Some(key) = map.next_key::<TypeField>()? {
107            match key {
108                TypeField::Type => {
109                    let name = map.next_value::<String>()?;
110
111                    if name == "DataIntegrityProof" {
112                        match cryptosuite.take() {
113                            Some(c) => {
114                                return ProofConfiguration::<T>::deserialize_with_type(
115                                    Type::DataIntegrityProof(c),
116                                    ReplayMap::new(keep, map),
117                                );
118                            }
119                            None => {
120                                data_integrity_proof = true;
121                            }
122                        }
123                    } else {
124                        return ProofConfiguration::<T>::deserialize_with_type(
125                            Type::Other(name),
126                            ReplayMap::new(keep, map),
127                        );
128                    }
129                }
130                TypeField::Cryptosuite => {
131                    let name = map.next_value::<CryptosuiteString>()?;
132                    if data_integrity_proof {
133                        return ProofConfiguration::<T>::deserialize_with_type(
134                            Type::DataIntegrityProof(name),
135                            ReplayMap::new(keep, map),
136                        );
137                    } else {
138                        cryptosuite = Some(name)
139                    }
140                }
141                TypeField::Other(key) => {
142                    keep.push((key, map.next_value()?));
143                }
144            }
145        }
146
147        Err(serde::de::Error::custom("missing type"))
148    }
149}