dcbor_parse/compose.rs
1use dcbor::prelude::*;
2use thiserror::Error;
3
4use crate::{ParseError, parse_dcbor_item};
5
6#[derive(Debug, Error, Clone, PartialEq)]
7#[rustfmt::skip]
8pub enum Error {
9 #[error("Invalid odd map length")]
10 OddMapLength,
11 #[error("Duplicate map key")]
12 DuplicateMapKey,
13 #[error("Invalid CBOR item: {0}")]
14 ParseError(#[from] ParseError),
15}
16
17pub type Result<T> = std::result::Result<T, Error>;
18
19/// Composes a dCBOR array from a slice of string slices, and returns a CBOR
20/// object representing the array.
21///
22/// Each string slice is parsed as a dCBOR item.
23///
24/// # Example
25///
26/// ```rust
27/// # use dcbor_parse::compose_dcbor_array;
28/// let cbor = compose_dcbor_array(&["1", "2", "3"]).unwrap();
29/// assert_eq!(cbor.diagnostic(), "[1, 2, 3]");
30/// ```
31pub fn compose_dcbor_array(array: &[&str]) -> Result<CBOR> {
32 let mut result = Vec::new();
33 for item in array {
34 let cbor = parse_dcbor_item(item)?;
35 result.push(cbor);
36 }
37 Ok(result.into())
38}
39
40/// Composes a dCBOR map from a slice of string slices, and returns a CBOR
41/// object representing the map.
42///
43/// The length of the slice must be even, as each key must have a corresponding
44/// value.
45///
46/// Each string slice is parsed as a dCBOR item.
47///
48/// # Example
49///
50/// ```rust
51/// # use dcbor_parse::compose_dcbor_map;
52/// let cbor = compose_dcbor_map(&["1", "2", "3", "4"]).unwrap();
53/// assert_eq!(cbor.diagnostic(), "{1: 2, 3: 4}");
54/// ```
55pub fn compose_dcbor_map(array: &[&str]) -> Result<CBOR> {
56 if array.len() % 2 != 0 {
57 return Err(Error::OddMapLength);
58 }
59
60 let mut map = Map::new();
61
62 for i in (0..array.len()).step_by(2) {
63 let key = parse_dcbor_item(array[i])?;
64 let value = parse_dcbor_item(array[i + 1])?;
65
66 // Check for duplicate key
67 if map.contains_key(key.clone()) {
68 return Err(Error::DuplicateMapKey);
69 }
70
71 map.insert(key, value);
72 }
73
74 Ok(map.into())
75}