1use std::convert::TryInto;
2
3use anyhow::anyhow;
4use ciborium::value::Value as CborValue;
5use serde_json::{Map, Value as JsonValue};
6
7use crate::ProtocolError;
8mod convert;
9pub use convert::FieldType;
10
11mod value;
12pub use value::*;
13
14mod canonical;
15pub use canonical::*;
16
17mod map;
18pub use map::*;
19
20pub trait ValuesCollection {
21 type Key;
22 type Value;
23
24 fn get_mut(&mut self, key: &Self::Key) -> Option<&mut Self::Value>;
25 fn get(&self, key: &Self::Key) -> Option<&Self::Value>;
26 fn remove(&mut self, key_to_remove: impl Into<Self::Key>) -> Option<Self::Value>;
27}
28
29pub trait ReplacePaths: ValuesCollection {
30 type Value;
31
32 fn replace_paths<I, C>(&mut self, paths: I, from: FieldType, to: FieldType)
33 where
34 I: IntoIterator<Item = C>,
35 C: AsRef<str>;
36
37 fn replace_path(&mut self, path: &str, from: FieldType, to: FieldType) -> Option<()>;
38 fn get_path_mut(&mut self, path: &str) -> Option<&mut <Self as ReplacePaths>::Value>;
39}
40
41pub fn get_key_from_cbor_map<'a>(
42 cbor_map: &'a [(CborValue, CborValue)],
43 key: &'a str,
44) -> Option<&'a CborValue> {
45 for (cbor_key, cbor_value) in cbor_map.iter() {
46 if !cbor_key.is_text() {
47 continue;
48 }
49
50 if cbor_key.as_text().expect("confirmed as text") == key {
51 return Some(cbor_value);
52 }
53 }
54 None
55}
56
57impl CborMapExtension for &Vec<(CborValue, CborValue)> {
58 fn as_u16(&self, key: &str, error_message: &str) -> Result<u16, ProtocolError> {
59 let key_value = get_key_from_cbor_map(self, key)
60 .ok_or_else(|| ProtocolError::DecodingError(String::from(error_message)))?;
61 if let CborValue::Integer(integer_value) = key_value {
62 return Ok(i128::from(*integer_value) as u16);
63 }
64 Err(ProtocolError::DecodingError(String::from(error_message)))
65 }
66
67 fn as_u8(&self, key: &str, error_message: &str) -> Result<u8, ProtocolError> {
68 let key_value = get_key_from_cbor_map(self, key)
69 .ok_or_else(|| ProtocolError::DecodingError(String::from(error_message)))?;
70 if let CborValue::Integer(integer_value) = key_value {
71 return Ok(i128::from(*integer_value) as u8);
72 }
73 Err(ProtocolError::DecodingError(String::from(error_message)))
74 }
75
76 fn as_bool(&self, key: &str, error_message: &str) -> Result<bool, ProtocolError> {
77 let key_value = get_key_from_cbor_map(self, key)
78 .ok_or_else(|| ProtocolError::DecodingError(String::from(error_message)))?;
79 if let CborValue::Bool(bool_value) = key_value {
80 return Ok(*bool_value);
81 }
82 Err(ProtocolError::DecodingError(String::from(error_message)))
83 }
84
85 fn as_bytes(&self, key: &str, error_message: &str) -> Result<Vec<u8>, ProtocolError> {
86 let key_value = get_key_from_cbor_map(self, key)
87 .ok_or_else(|| ProtocolError::DecodingError(String::from(error_message)))?;
88 match key_value {
89 CborValue::Bytes(bytes) => Ok(bytes.clone()),
90 CborValue::Array(array) => array
91 .iter()
92 .map(|byte| match byte {
93 CborValue::Integer(int) => {
94 let value_as_u8: u8 = (*int).try_into().map_err(|_| {
95 ProtocolError::DecodingError(String::from("expected u8 value"))
96 })?;
97 Ok(value_as_u8)
98 }
99 _ => Err(ProtocolError::DecodingError(String::from(
100 "not an array of integers",
101 ))),
102 })
103 .collect::<Result<Vec<u8>, ProtocolError>>(),
104 _ => Err(ProtocolError::DecodingError(String::from(error_message))),
105 }
106 }
107
108 fn as_string(&self, key: &str, error_message: &str) -> Result<String, ProtocolError> {
109 let key_value = get_key_from_cbor_map(self, key)
110 .ok_or_else(|| ProtocolError::DecodingError(String::from(error_message)))?;
111 if let CborValue::Text(string_value) = key_value {
112 return Ok(string_value.clone());
113 }
114 Err(ProtocolError::DecodingError(String::from(error_message)))
115 }
116
117 fn as_u64(&self, key: &str, error_message: &str) -> Result<u64, ProtocolError> {
118 let key_value = get_key_from_cbor_map(self, key)
119 .ok_or_else(|| ProtocolError::DecodingError(String::from(error_message)))?;
120 if let CborValue::Integer(integer_value) = key_value {
121 return Ok(i128::from(*integer_value) as u64);
122 }
123 Err(ProtocolError::DecodingError(String::from(error_message)))
124 }
125}
126
127pub fn cbor_value_to_json_value(cbor: &CborValue) -> Result<serde_json::Value, anyhow::Error> {
129 match cbor {
130 CborValue::Integer(num) => Ok(JsonValue::from(i128::from(*num) as i64)),
131 CborValue::Bytes(bytes) => Ok(JsonValue::Array(
132 bytes.iter().map(|byte| JsonValue::from(*byte)).collect(),
133 )),
134 CborValue::Float(float) => Ok(JsonValue::from(*float)),
135 CborValue::Text(text) => Ok(JsonValue::from(text.clone())),
136 CborValue::Bool(boolean) => Ok(JsonValue::from(*boolean)),
137 CborValue::Null => Ok(JsonValue::Null),
138 CborValue::Array(arr) => Ok(JsonValue::Array(
139 arr.iter()
140 .map(cbor_value_to_json_value)
141 .collect::<Result<Vec<JsonValue>, anyhow::Error>>()?,
142 )),
143 CborValue::Map(map) => cbor_map_to_json_map(map),
144 _ => Err(anyhow!("Can't convert CBOR to JSON: unknown type")),
145 }
146}
147
148pub fn cbor_value_into_json_value(cbor: CborValue) -> Result<serde_json::Value, anyhow::Error> {
149 match cbor {
150 CborValue::Integer(num) => Ok(JsonValue::from(i128::from(num) as i64)),
151 CborValue::Bytes(bytes) => Ok(JsonValue::Array(
152 bytes.into_iter().map(JsonValue::from).collect(),
153 )),
154 CborValue::Float(float) => Ok(JsonValue::from(float)),
155 CborValue::Text(text) => Ok(JsonValue::from(text)),
156 CborValue::Bool(boolean) => Ok(JsonValue::from(boolean)),
157 CborValue::Null => Ok(JsonValue::Null),
158 CborValue::Array(arr) => Ok(JsonValue::Array(
159 arr.into_iter()
160 .map(cbor_value_into_json_value)
161 .collect::<Result<Vec<JsonValue>, anyhow::Error>>()?,
162 )),
163 CborValue::Map(map) => cbor_map_into_json_map(map),
164 _ => Err(anyhow!("Can't convert CBOR to JSON: unknown type")),
165 }
166}
167
168pub fn cbor_map_to_json_map(
169 cbor_map: &[(CborValue, CborValue)],
170) -> Result<serde_json::Value, anyhow::Error> {
171 let mut json_vec = cbor_map
172 .iter()
173 .map(|(key, value)| {
174 Ok((
175 key.as_text()
176 .ok_or_else(|| anyhow!("Expect key to be a string"))?
177 .to_string(),
178 cbor_value_to_json_value(value)?,
179 ))
180 })
181 .collect::<Result<Vec<(String, JsonValue)>, anyhow::Error>>()?;
182
183 let mut json_map = Map::new();
184
185 for (key, value) in json_vec.drain(..) {
186 json_map.insert(key, value);
187 }
188
189 Ok(serde_json::Value::Object(json_map))
190}
191
192pub fn cbor_map_into_json_map(
193 cbor_map: Vec<(CborValue, CborValue)>,
194) -> Result<serde_json::Value, anyhow::Error> {
195 let mut json_vec = cbor_map
196 .into_iter()
197 .map(|(key, value)| {
198 Ok((
199 key.into_text()
200 .map_err(|_| anyhow!("Expect key to be a string"))?,
201 cbor_value_into_json_value(value)?,
202 ))
203 })
204 .collect::<Result<Vec<(String, JsonValue)>, anyhow::Error>>()?;
205
206 let mut json_map = Map::new();
207
208 for (key, value) in json_vec.drain(..) {
209 json_map.insert(key, value);
210 }
211
212 Ok(serde_json::Value::Object(json_map))
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218 use ciborium::value::Value as CborValue;
219 use serde_json::json;
220
221 #[test]
224 fn get_key_from_cbor_map_found() {
225 let map = vec![
226 (
227 CborValue::Text("name".to_string()),
228 CborValue::Text("Alice".to_string()),
229 ),
230 (
231 CborValue::Text("age".to_string()),
232 CborValue::Integer(30.into()),
233 ),
234 ];
235 let result = get_key_from_cbor_map(&map, "name");
236 assert_eq!(result, Some(&CborValue::Text("Alice".to_string())));
237 }
238
239 #[test]
240 fn get_key_from_cbor_map_not_found() {
241 let map = vec![(
242 CborValue::Text("name".to_string()),
243 CborValue::Text("Alice".to_string()),
244 )];
245 let result = get_key_from_cbor_map(&map, "missing");
246 assert!(result.is_none());
247 }
248
249 #[test]
250 fn get_key_from_cbor_map_skips_non_text_keys() {
251 let map = vec![
252 (CborValue::Integer(1.into()), CborValue::Bool(true)),
253 (CborValue::Text("key".to_string()), CborValue::Bool(false)),
254 ];
255 let result = get_key_from_cbor_map(&map, "key");
256 assert_eq!(result, Some(&CborValue::Bool(false)));
257 }
258
259 fn make_cbor_map(pairs: Vec<(&str, CborValue)>) -> Vec<(CborValue, CborValue)> {
262 pairs
263 .into_iter()
264 .map(|(k, v)| (CborValue::Text(k.to_string()), v))
265 .collect()
266 }
267
268 #[test]
269 fn cbor_map_extension_as_u16() {
270 let map = make_cbor_map(vec![("val", CborValue::Integer(1234.into()))]);
271 let result = (&map).as_u16("val", "err");
272 assert_eq!(result.unwrap(), 1234);
273 }
274
275 #[test]
276 fn cbor_map_extension_as_u16_missing() {
277 let map = make_cbor_map(vec![]);
278 let result = (&map).as_u16("val", "missing");
279 assert!(result.is_err());
280 }
281
282 #[test]
283 fn cbor_map_extension_as_u16_wrong_type() {
284 let map = make_cbor_map(vec![("val", CborValue::Text("hello".to_string()))]);
285 let result = (&map).as_u16("val", "err");
286 assert!(result.is_err());
287 }
288
289 #[test]
290 fn cbor_map_extension_as_u8() {
291 let map = make_cbor_map(vec![("val", CborValue::Integer(255.into()))]);
292 let result = (&map).as_u8("val", "err");
293 assert_eq!(result.unwrap(), 255);
294 }
295
296 #[test]
297 fn cbor_map_extension_as_bool() {
298 let map = make_cbor_map(vec![("flag", CborValue::Bool(true))]);
299 let result = (&map).as_bool("flag", "err");
300 assert!(result.unwrap());
301 }
302
303 #[test]
304 fn cbor_map_extension_as_bool_missing() {
305 let map = make_cbor_map(vec![]);
306 let result = (&map).as_bool("flag", "missing");
307 assert!(result.is_err());
308 }
309
310 #[test]
311 fn cbor_map_extension_as_bool_wrong_type() {
312 let map = make_cbor_map(vec![("flag", CborValue::Integer(1.into()))]);
313 let result = (&map).as_bool("flag", "err");
314 assert!(result.is_err());
315 }
316
317 #[test]
318 fn cbor_map_extension_as_bytes_from_bytes() {
319 let data = vec![1u8, 2, 3, 4];
320 let map = make_cbor_map(vec![("data", CborValue::Bytes(data.clone()))]);
321 let result = (&map).as_bytes("data", "err");
322 assert_eq!(result.unwrap(), data);
323 }
324
325 #[test]
326 fn cbor_map_extension_as_bytes_from_array() {
327 let array = vec![CborValue::Integer(10.into()), CborValue::Integer(20.into())];
328 let map = make_cbor_map(vec![("data", CborValue::Array(array))]);
329 let result = (&map).as_bytes("data", "err");
330 assert_eq!(result.unwrap(), vec![10u8, 20]);
331 }
332
333 #[test]
334 fn cbor_map_extension_as_bytes_wrong_type() {
335 let map = make_cbor_map(vec![("data", CborValue::Bool(true))]);
336 let result = (&map).as_bytes("data", "err");
337 assert!(result.is_err());
338 }
339
340 #[test]
341 fn cbor_map_extension_as_string() {
342 let map = make_cbor_map(vec![("s", CborValue::Text("hello".to_string()))]);
343 let result = (&map).as_string("s", "err");
344 assert_eq!(result.unwrap(), "hello");
345 }
346
347 #[test]
348 fn cbor_map_extension_as_string_wrong_type() {
349 let map = make_cbor_map(vec![("s", CborValue::Integer(1.into()))]);
350 let result = (&map).as_string("s", "err");
351 assert!(result.is_err());
352 }
353
354 #[test]
355 fn cbor_map_extension_as_u64() {
356 let map = make_cbor_map(vec![("n", CborValue::Integer(999999.into()))]);
357 let result = (&map).as_u64("n", "err");
358 assert_eq!(result.unwrap(), 999999);
359 }
360
361 #[test]
364 fn cbor_integer_to_json() {
365 let result = cbor_value_to_json_value(&CborValue::Integer(42.into())).unwrap();
366 assert_eq!(result, json!(42));
367 }
368
369 #[test]
370 fn cbor_text_to_json() {
371 let result = cbor_value_to_json_value(&CborValue::Text("hello".to_string())).unwrap();
372 assert_eq!(result, json!("hello"));
373 }
374
375 #[test]
376 fn cbor_bool_to_json() {
377 let result = cbor_value_to_json_value(&CborValue::Bool(true)).unwrap();
378 assert_eq!(result, json!(true));
379 }
380
381 #[test]
382 fn cbor_null_to_json() {
383 let result = cbor_value_to_json_value(&CborValue::Null).unwrap();
384 assert!(result.is_null());
385 }
386
387 #[test]
388 fn cbor_float_to_json() {
389 let result = cbor_value_to_json_value(&CborValue::Float(3.14)).unwrap();
390 assert_eq!(result, json!(3.14));
391 }
392
393 #[test]
394 fn cbor_bytes_to_json_array() {
395 let result = cbor_value_to_json_value(&CborValue::Bytes(vec![1, 2, 3])).unwrap();
396 assert_eq!(result, json!([1, 2, 3]));
397 }
398
399 #[test]
400 fn cbor_array_to_json_array() {
401 let cbor = CborValue::Array(vec![
402 CborValue::Integer(1.into()),
403 CborValue::Text("two".to_string()),
404 ]);
405 let result = cbor_value_to_json_value(&cbor).unwrap();
406 assert_eq!(result, json!([1, "two"]));
407 }
408
409 #[test]
410 fn cbor_map_to_json_object() {
411 let cbor = CborValue::Map(vec![(
412 CborValue::Text("key".to_string()),
413 CborValue::Integer(10.into()),
414 )]);
415 let result = cbor_value_to_json_value(&cbor).unwrap();
416 assert_eq!(result, json!({"key": 10}));
417 }
418
419 #[test]
422 fn cbor_into_json_integer() {
423 let result = cbor_value_into_json_value(CborValue::Integer(99.into())).unwrap();
424 assert_eq!(result, json!(99));
425 }
426
427 #[test]
428 fn cbor_into_json_text() {
429 let result = cbor_value_into_json_value(CborValue::Text("world".to_string())).unwrap();
430 assert_eq!(result, json!("world"));
431 }
432
433 #[test]
434 fn cbor_into_json_null() {
435 let result = cbor_value_into_json_value(CborValue::Null).unwrap();
436 assert!(result.is_null());
437 }
438
439 #[test]
440 fn cbor_into_json_nested_array() {
441 let cbor = CborValue::Array(vec![CborValue::Array(vec![CborValue::Integer(1.into())])]);
442 let result = cbor_value_into_json_value(cbor).unwrap();
443 assert_eq!(result, json!([[1]]));
444 }
445
446 #[test]
449 fn test_cbor_map_to_json_map_valid() {
450 let map = vec![
451 (
452 CborValue::Text("a".to_string()),
453 CborValue::Integer(1.into()),
454 ),
455 (CborValue::Text("b".to_string()), CborValue::Bool(false)),
456 ];
457 let result = cbor_map_to_json_map(&map).unwrap();
458 assert_eq!(result, json!({"a": 1, "b": false}));
459 }
460
461 #[test]
462 fn test_cbor_map_to_json_map_non_string_key() {
463 let map = vec![(CborValue::Integer(1.into()), CborValue::Bool(true))];
464 let result = cbor_map_to_json_map(&map);
465 assert!(result.is_err());
466 }
467
468 #[test]
471 fn test_cbor_map_into_json_map_valid() {
472 let map = vec![(
473 CborValue::Text("x".to_string()),
474 CborValue::Text("y".to_string()),
475 )];
476 let result = cbor_map_into_json_map(map).unwrap();
477 assert_eq!(result, json!({"x": "y"}));
478 }
479
480 #[test]
481 fn test_cbor_map_into_json_map_non_string_key() {
482 let map = vec![(CborValue::Integer(1.into()), CborValue::Bool(true))];
483 let result = cbor_map_into_json_map(map);
484 assert!(result.is_err());
485 }
486}