ssi_data_integrity_core/proof/de/
configuration.rs1use 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}