1 //! This module defines a helper for parsing fields in a CBOR map.
2
3 use coset::{cbor::value::Value, AsCborValue, CoseEncrypt, CoseError, CoseMac0, CoseSign1};
4 use thiserror::Error;
5
6 #[derive(Error, Debug)]
7 pub enum FieldValueError {
8 #[error("expected a value for field {0}, but none was found")]
9 Missing(&'static str),
10 #[error("expected bytes for field {0}, but found `{1:?}`")]
11 NotBytes(&'static str, Value),
12 #[error("expected string for field {0}, but found `{1:?}`")]
13 NotString(&'static str, Value),
14 #[error("expected null for field {0}, but found `{1:?}`")]
15 NotNull(&'static str, Value),
16 #[error("expected u32 for field {0}, but found `{1:?}`")]
17 NotU32(&'static str, Value),
18 #[error("expected i64 for field {0}, but found `{1:?}`")]
19 NotI64(&'static str, Value),
20 #[error("expected u64 for field {0}, but found `{1:?}`")]
21 NotU64(&'static str, Value),
22 #[error("expected boolean for field {0}, but found `{1:?}`")]
23 NotBool(&'static str, Value),
24 #[error("expected map for field {0}, but found `{1:?}`")]
25 NotMap(&'static str, Value),
26 #[error("expected array for field {0}, but found `{1:?}`")]
27 NotArray(&'static str, Value),
28 #[error("unable to parse field {0} as COSE_Sign1: `{1:?}`")]
29 CoseSign1ParseError(&'static str, CoseError),
30 #[error("unable to parse field {0} as COSE_Encrypt: `{1:?}`")]
31 CoseEncryptParseError(&'static str, CoseError),
32 #[error("unable to parse field {0} as COSE_Mac0: `{1:?}`")]
33 CoseMac0ParseError(&'static str, CoseError),
34 #[error("field {0} may be set only once; encountered multiple values: `{1:?}`, `{2:?}`")]
35 DuplicateField(&'static str, Value, Value),
36 }
37
38 pub(super) struct FieldValue {
39 name: &'static str,
40 value: Option<Value>,
41 }
42
43 impl FieldValue {
new(name: &'static str) -> Self44 pub fn new(name: &'static str) -> Self {
45 Self { name, value: None }
46 }
47
from_optional_value(name: &'static str, value: Option<Value>) -> Self48 pub fn from_optional_value(name: &'static str, value: Option<Value>) -> Self {
49 Self { name, value }
50 }
51
set_once(&mut self, value: Value) -> Result<(), FieldValueError>52 pub fn set_once(&mut self, value: Value) -> Result<(), FieldValueError> {
53 match &self.value {
54 None => {
55 self.value = Some(value);
56 Ok(())
57 }
58 Some(previous) => {
59 Err(FieldValueError::DuplicateField(self.name, previous.clone(), value))
60 }
61 }
62 }
63
is_bytes(&self) -> bool64 pub fn is_bytes(&self) -> bool {
65 self.value.as_ref().map_or(false, |v| v.is_bytes())
66 }
67
into_optional_bytes(self) -> Result<Option<Vec<u8>>, FieldValueError>68 pub fn into_optional_bytes(self) -> Result<Option<Vec<u8>>, FieldValueError> {
69 self.value
70 .map(|v| match v {
71 Value::Bytes(b) => Ok(b),
72 _ => Err(FieldValueError::NotBytes(self.name, v)),
73 })
74 .transpose()
75 }
76
into_bytes(self) -> Result<Vec<u8>, FieldValueError>77 pub fn into_bytes(self) -> Result<Vec<u8>, FieldValueError> {
78 require_present(self.name, self.into_optional_bytes())
79 }
80
into_optional_string(self) -> Result<Option<String>, FieldValueError>81 pub fn into_optional_string(self) -> Result<Option<String>, FieldValueError> {
82 self.value
83 .map(|v| match v {
84 Value::Text(s) => Ok(s),
85 _ => Err(FieldValueError::NotString(self.name, v)),
86 })
87 .transpose()
88 }
89
into_string(self) -> Result<String, FieldValueError>90 pub fn into_string(self) -> Result<String, FieldValueError> {
91 require_present(self.name, self.into_optional_string())
92 }
93
into_cose_encrypt(self) -> Result<CoseEncrypt, FieldValueError>94 pub fn into_cose_encrypt(self) -> Result<CoseEncrypt, FieldValueError> {
95 require_present(self.name, self.into_optional_cose_encrypt())
96 }
97
into_optional_cose_encrypt(self) -> Result<Option<CoseEncrypt>, FieldValueError>98 pub fn into_optional_cose_encrypt(self) -> Result<Option<CoseEncrypt>, FieldValueError> {
99 self.value
100 .map(|v| match v {
101 Value::Array(_) => CoseEncrypt::from_cbor_value(v)
102 .map_err(|e| FieldValueError::CoseEncryptParseError(self.name, e)),
103 _ => Err(FieldValueError::NotArray(self.name, v)),
104 })
105 .transpose()
106 }
107
into_cose_mac0(self) -> Result<CoseMac0, FieldValueError>108 pub fn into_cose_mac0(self) -> Result<CoseMac0, FieldValueError> {
109 require_present(self.name, self.into_optional_cose_mac0())
110 }
111
into_optional_cose_mac0(self) -> Result<Option<CoseMac0>, FieldValueError>112 pub fn into_optional_cose_mac0(self) -> Result<Option<CoseMac0>, FieldValueError> {
113 self.value
114 .map(|v| match v {
115 Value::Array(_) => CoseMac0::from_cbor_value(v)
116 .map_err(|e| FieldValueError::CoseMac0ParseError(self.name, e)),
117 _ => Err(FieldValueError::NotArray(self.name, v)),
118 })
119 .transpose()
120 }
121
into_cose_sign1(self) -> Result<CoseSign1, FieldValueError>122 pub fn into_cose_sign1(self) -> Result<CoseSign1, FieldValueError> {
123 require_present(self.name, self.into_optional_cose_sign1())
124 }
125
into_optional_cose_sign1(self) -> Result<Option<CoseSign1>, FieldValueError>126 pub fn into_optional_cose_sign1(self) -> Result<Option<CoseSign1>, FieldValueError> {
127 self.value
128 .map(|v| match v {
129 Value::Array(_) => CoseSign1::from_cbor_value(v)
130 .map_err(|e| FieldValueError::CoseSign1ParseError(self.name, e)),
131 _ => Err(FieldValueError::NotArray(self.name, v)),
132 })
133 .transpose()
134 }
135
into_array(self) -> Result<Vec<Value>, FieldValueError>136 pub fn into_array(self) -> Result<Vec<Value>, FieldValueError> {
137 require_present(self.name, self.into_optional_array())
138 }
139
into_optional_array(self) -> Result<Option<Vec<Value>>, FieldValueError>140 pub fn into_optional_array(self) -> Result<Option<Vec<Value>>, FieldValueError> {
141 self.value
142 .map(|v| match v {
143 Value::Array(v) => Ok(v),
144 _ => Err(FieldValueError::NotArray(self.name, v)),
145 })
146 .transpose()
147 }
148
into_map(self) -> Result<Vec<(Value, Value)>, FieldValueError>149 pub fn into_map(self) -> Result<Vec<(Value, Value)>, FieldValueError> {
150 require_present(self.name, self.into_optional_map())
151 }
152
into_optional_map(self) -> Result<Option<Vec<(Value, Value)>>, FieldValueError>153 pub fn into_optional_map(self) -> Result<Option<Vec<(Value, Value)>>, FieldValueError> {
154 self.value
155 .map(|v| match v {
156 Value::Map(v) => Ok(v),
157 _ => Err(FieldValueError::NotMap(self.name, v)),
158 })
159 .transpose()
160 }
161
into_bool(self) -> Result<bool, FieldValueError>162 pub fn into_bool(self) -> Result<bool, FieldValueError> {
163 require_present(self.name, self.into_optional_bool())
164 }
165
into_optional_bool(self) -> Result<Option<bool>, FieldValueError>166 pub fn into_optional_bool(self) -> Result<Option<bool>, FieldValueError> {
167 self.value
168 .map(|v| match v {
169 Value::Bool(b) => Ok(b),
170 Value::Integer(i) if i == 0.into() => Ok(false),
171 Value::Integer(i) if i == 1.into() => Ok(true),
172 _ => Err(FieldValueError::NotBool(self.name, v)),
173 })
174 .transpose()
175 }
176
is_null(&self) -> Result<bool, FieldValueError>177 pub fn is_null(&self) -> Result<bool, FieldValueError> {
178 // If there's no value, return false; if there is a null value, return true; anything else
179 // is an error.
180 self.value
181 .as_ref()
182 .map(|v| match *v {
183 Value::Null => Ok(true),
184 _ => Err(FieldValueError::NotNull(self.name, v.clone())),
185 })
186 .unwrap_or(Ok(false))
187 }
188
is_integer(&self) -> bool189 pub fn is_integer(&self) -> bool {
190 self.value.as_ref().map_or(false, |v| v.is_integer())
191 }
192
into_u32(self) -> Result<u32, FieldValueError>193 pub fn into_u32(self) -> Result<u32, FieldValueError> {
194 require_present(self.name, self.into_optional_u32())
195 }
196
into_optional_u32(self) -> Result<Option<u32>, FieldValueError>197 pub fn into_optional_u32(self) -> Result<Option<u32>, FieldValueError> {
198 self.value
199 .map(|v| {
200 let value =
201 if let Value::Integer(i) = v { i128::from(i).try_into().ok() } else { None };
202 value.ok_or_else(|| FieldValueError::NotU32(self.name, v))
203 })
204 .transpose()
205 }
206
into_optional_i64(self) -> Result<Option<i64>, FieldValueError>207 pub fn into_optional_i64(self) -> Result<Option<i64>, FieldValueError> {
208 self.value
209 .map(|v| {
210 let value =
211 if let Value::Integer(i) = v { i128::from(i).try_into().ok() } else { None };
212 value.ok_or_else(|| FieldValueError::NotI64(self.name, v))
213 })
214 .transpose()
215 }
216
into_u64(self) -> Result<u64, FieldValueError>217 pub fn into_u64(self) -> Result<u64, FieldValueError> {
218 require_present(self.name, self.into_optional_u64())
219 }
220
into_optional_u64(self) -> Result<Option<u64>, FieldValueError>221 pub fn into_optional_u64(self) -> Result<Option<u64>, FieldValueError> {
222 self.value
223 .map(|v| {
224 let value =
225 if let Value::Integer(i) = v { i128::from(i).try_into().ok() } else { None };
226 value.ok_or_else(|| FieldValueError::NotU64(self.name, v))
227 })
228 .transpose()
229 }
230 }
231
require_present<T>( name: &'static str, value: Result<Option<T>, FieldValueError>, ) -> Result<T, FieldValueError>232 fn require_present<T>(
233 name: &'static str,
234 value: Result<Option<T>, FieldValueError>,
235 ) -> Result<T, FieldValueError> {
236 value.and_then(|opt| opt.ok_or(FieldValueError::Missing(name)))
237 }
238