ssi_data_integrity_core/proof/de/
mod.rs1use crate::{
10 suite::bounds::{OptionsOf, SignatureOf, VerificationMethodOf},
11 CryptosuiteString, DeserializeCryptographicSuite, Proof, Type,
12};
13use serde::{
14 de::{DeserializeSeed, MapAccess},
15 Deserialize,
16};
17use ssi_core::{de::WithType, Lexical, OneOrMany};
18use std::{collections::BTreeMap, marker::PhantomData};
19
20mod field;
21pub use field::*;
22
23mod ref_or_value;
24pub use ref_or_value::*;
25
26mod replay_map;
27pub use replay_map::*;
28
29mod configuration;
30
31fn datetime_to_utc_datetimestamp(
36 value: Option<Lexical<xsd_types::DateTime>>,
37) -> Option<Lexical<xsd_types::DateTimeStamp>> {
38 value.map(|lexical_dt| {
39 let (dt, mut representation) = lexical_dt.into_parts();
40
41 let dts = xsd_types::DateTimeStamp::new(
42 dt.date_time,
43 dt.offset.unwrap_or_else(|| {
44 if let Some(r) = &mut representation {
45 r.push('Z');
48 }
49
50 chrono::FixedOffset::east_opt(0).unwrap()
51 }),
52 );
53
54 Lexical::from_parts(dts, representation)
55 })
56}
57
58impl<'de, T: DeserializeCryptographicSuite<'de>> Proof<T> {
59 fn deserialize_with_type<S>(type_: Type, mut deserializer: S) -> Result<Self, S::Error>
60 where
61 S: serde::de::MapAccess<'de>,
62 {
63 let suite: T = type_
64 .try_into()
65 .map_err(|_| serde::de::Error::custom("unexpected cryptosuite"))?;
66
67 let mut context = None;
68 let mut created: Option<Lexical<xsd_types::DateTime>> = None;
69 let mut verification_method = None;
70 let mut proof_purpose = None;
71 let mut expires: Option<Lexical<xsd_types::DateTime>> = None;
72 let mut domains: Option<OneOrMany<String>> = None;
73 let mut challenge = None;
74 let mut nonce = None;
75
76 let mut other = Vec::new();
77
78 while let Some(key) = deserializer.next_key::<Field>()? {
79 match key {
80 Field::Context => context = Some(deserializer.next_value()?),
81 Field::Created => created = Some(deserializer.next_value()?),
82 Field::VerificationMethod => {
83 verification_method = Some({
84 deserializer
85 .next_value_seed(
86 WithType::<T, RefOrValue<VerificationMethodOf<T>>>::new(&suite),
87 )?
88 })
89 }
90 Field::ProofPurpose => proof_purpose = Some(deserializer.next_value()?),
91 Field::Expires => expires = Some(deserializer.next_value()?),
92 Field::Domains => domains = Some(deserializer.next_value()?),
93 Field::Challenge => challenge = Some(deserializer.next_value()?),
94 Field::Nonce => nonce = Some(deserializer.next_value()?),
95 Field::Other(key) => other.push(Some((key, deserializer.next_value()?))),
96 }
97 }
98
99 let options = WithType::<T, OptionsOf<T>>::new(&suite)
100 .deserialize(serde::__private::de::FlatMapDeserializer(
101 &mut other,
102 PhantomData,
103 ))?
104 .0;
105
106 let signature = WithType::<T, SignatureOf<T>>::new(&suite)
107 .deserialize(serde::__private::de::FlatMapDeserializer(
108 &mut other,
109 PhantomData,
110 ))?
111 .0;
112
113 Ok(Self {
114 context,
115 type_: suite,
116 created: datetime_to_utc_datetimestamp(created),
117 verification_method: verification_method
118 .map(|v| v.map(VerificationMethodOf::unwrap).into())
119 .ok_or_else(|| serde::de::Error::custom("missing `verificationMethod` property"))?,
120 proof_purpose: proof_purpose
121 .ok_or_else(|| serde::de::Error::custom("missing `proofPurpose` property"))?,
122 expires: datetime_to_utc_datetimestamp(expires),
123 domains: domains.map(|d| d.into_vec()).unwrap_or_default(),
124 challenge,
125 nonce,
126 options,
127 signature,
128 extra_properties: BTreeMap::deserialize(serde::__private::de::FlatMapDeserializer(
129 &mut other,
130 PhantomData,
131 ))?,
132 })
133 }
134}
135
136impl<'de, T: DeserializeCryptographicSuite<'de>> serde::Deserialize<'de> for Proof<T> {
137 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
138 where
139 D: serde::Deserializer<'de>,
140 {
141 deserializer.deserialize_map(ProofVisitor(PhantomData))
142 }
143}
144
145struct ProofVisitor<T>(PhantomData<T>);
146
147impl<'de, T: DeserializeCryptographicSuite<'de>> serde::de::Visitor<'de> for ProofVisitor<T> {
148 type Value = Proof<T>;
149
150 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
151 write!(formatter, "Data-Integrity proof")
152 }
153
154 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
155 where
156 A: MapAccess<'de>,
157 {
158 let mut keep = Vec::new();
159 let mut cryptosuite = None;
160 let mut data_integrity_proof = false;
161
162 while let Some(key) = map.next_key::<TypeField>()? {
163 match key {
164 TypeField::Type => {
165 let name = map.next_value::<String>()?;
166
167 if name == "DataIntegrityProof" {
168 match cryptosuite.take() {
169 Some(c) => {
170 return Proof::<T>::deserialize_with_type(
171 Type::DataIntegrityProof(c),
172 ReplayMap::new(keep, map),
173 );
174 }
175 None => {
176 data_integrity_proof = true;
177 }
178 }
179 } else {
180 return Proof::<T>::deserialize_with_type(
181 Type::Other(name),
182 ReplayMap::new(keep, map),
183 );
184 }
185 }
186 TypeField::Cryptosuite => {
187 let name = map.next_value::<CryptosuiteString>()?;
188 if data_integrity_proof {
189 return Proof::<T>::deserialize_with_type(
190 Type::DataIntegrityProof(name),
191 ReplayMap::new(keep, map),
192 );
193 } else {
194 cryptosuite = Some(name)
195 }
196 }
197 TypeField::Other(key) => {
198 keep.push((key, map.next_value()?));
199 }
200 }
201 }
202
203 Err(serde::de::Error::custom("missing type"))
204 }
205}