platform_value/converter/
ciborium.rs

1use crate::value_map::ValueMap;
2use crate::{Error, Value, ValueMapHelper};
3use ciborium::value::Integer;
4use ciborium::Value as CborValue;
5
6impl Value {
7    pub fn convert_from_cbor_map<I, R>(map: I) -> Result<R, Error>
8    where
9        I: IntoIterator<Item = (String, CborValue)>,
10        R: FromIterator<(String, Value)>,
11    {
12        map.into_iter()
13            .map(|(key, cbor_value)| Ok((key, cbor_value.try_into()?)))
14            .collect()
15    }
16
17    pub fn convert_to_cbor_map<I, R>(map: I) -> Result<R, Error>
18    where
19        I: IntoIterator<Item = (String, Value)>,
20        R: FromIterator<(String, CborValue)>,
21    {
22        map.into_iter()
23            .map(|(key, value)| Ok((key, value.try_into()?)))
24            .collect()
25    }
26
27    pub fn to_cbor_buffer(&self) -> Result<Vec<u8>, Error> {
28        let mut buffer: Vec<u8> = Vec::new();
29        ciborium::ser::into_writer(self, &mut buffer)
30            .map_err(|e| Error::CborSerializationError(e.to_string()))?;
31
32        Ok(buffer)
33    }
34}
35
36impl TryFrom<CborValue> for Value {
37    type Error = Error;
38
39    fn try_from(value: CborValue) -> Result<Self, Error> {
40        Ok(match value {
41            CborValue::Integer(integer) => Self::I128(integer.into()),
42            CborValue::Bytes(bytes) => Self::Bytes(bytes),
43            CborValue::Float(float) => Self::Float(float),
44            CborValue::Text(string) => Self::Text(string),
45            CborValue::Bool(value) => Self::Bool(value),
46            CborValue::Null => Self::Null,
47            CborValue::Tag(_, _) => {
48                return Err(Error::Unsupported(
49                    "conversion from cbor tags are currently not supported".to_string(),
50                ))
51            }
52            CborValue::Array(array) => {
53                let len = array.len();
54                if len > 10
55                    && array.iter().all(|v| {
56                        let Some(int) = v.as_integer() else {
57                            return false;
58                        };
59                        int.le(&Integer::from(u8::MAX)) && int.ge(&Integer::from(0))
60                    })
61                {
62                    //this is an array of bytes
63                    Self::Bytes(
64                        array
65                            .into_iter()
66                            .map(|v| v.into_integer().unwrap().try_into().unwrap())
67                            .collect(),
68                    )
69                } else {
70                    Self::Array(
71                        array
72                            .into_iter()
73                            .map(|v| v.try_into())
74                            .collect::<Result<Vec<Value>, Error>>()?,
75                    )
76                }
77            }
78            CborValue::Map(map) => Self::Map(
79                map.into_iter()
80                    .map(|(k, v)| Ok((k.try_into()?, v.try_into()?)))
81                    .collect::<Result<ValueMap, Error>>()?,
82            ),
83            _ => panic!("unsupported"),
84        })
85    }
86}
87
88impl TryInto<CborValue> for Value {
89    type Error = Error;
90
91    fn try_into(self) -> Result<CborValue, Self::Error> {
92        Ok(match self {
93            Value::U128(i) => CborValue::Integer((i as u64).into()),
94            Value::I128(i) => CborValue::Integer((i as i64).into()),
95            Value::U64(i) => CborValue::Integer(i.into()),
96            Value::I64(i) => CborValue::Integer(i.into()),
97            Value::U32(i) => CborValue::Integer(i.into()),
98            Value::I32(i) => CborValue::Integer(i.into()),
99            Value::U16(i) => CborValue::Integer(i.into()),
100            Value::I16(i) => CborValue::Integer(i.into()),
101            Value::U8(i) => CborValue::Integer(i.into()),
102            Value::I8(i) => CborValue::Integer(i.into()),
103            Value::Bytes(bytes) => CborValue::Bytes(bytes),
104            Value::Bytes20(bytes) => CborValue::Bytes(bytes.to_vec()),
105            Value::Bytes32(bytes) => CborValue::Bytes(bytes.to_vec()),
106            Value::Bytes36(bytes) => CborValue::Bytes(bytes.to_vec()),
107            Value::Float(float) => CborValue::Float(float),
108            Value::Text(string) => CborValue::Text(string),
109            Value::Bool(value) => CborValue::Bool(value),
110            Value::Null => CborValue::Null,
111            Value::Array(array) => CborValue::Array(
112                array
113                    .into_iter()
114                    .map(|value| value.try_into())
115                    .collect::<Result<Vec<CborValue>, Error>>()?,
116            ),
117            Value::Map(mut map) => {
118                map.sort_by_keys();
119                CborValue::Map(
120                    map.into_iter()
121                        .map(|(k, v)| Ok((k.try_into()?, v.try_into()?)))
122                        .collect::<Result<Vec<(CborValue, CborValue)>, Error>>()?,
123                )
124            }
125            Value::Identifier(bytes) => CborValue::Bytes(bytes.to_vec()),
126            Value::EnumU8(_) => {
127                return Err(Error::Unsupported(
128                    "No support for conversion of EnumU8 to JSONValue".to_string(),
129                ))
130            }
131            Value::EnumString(_) => {
132                return Err(Error::Unsupported(
133                    "No support for conversion of EnumString to JSONValue".to_string(),
134                ))
135            }
136        })
137    }
138}
139
140impl TryInto<Box<CborValue>> for Box<Value> {
141    type Error = Error;
142    fn try_into(self) -> Result<Box<CborValue>, Self::Error> {
143        (*self).try_into().map(Box::new)
144    }
145}