use ciborium::Value;
macro_rules! cbor_map {
($($key:expr => $value:expr),* $(,)?) => {
ciborium::Value::Map(vec![
$((
ciborium::Value::Text(String::from($key)),
ciborium::Value::from($value),
)),*
])
};
}
macro_rules! cbor_array {
($($value:expr),* $(,)?) => {
ciborium::Value::Array(vec![$($value),*])
};
}
pub(crate) use cbor_array;
pub(crate) use cbor_map;
pub fn map_get<'a>(value: &'a Value, key: &str) -> Option<&'a Value> {
let Value::Map(entries) = value else {
panic!("expected Value::Map, got {value:?}"); };
for (k, v) in entries {
let Value::Text(s) = k else {
panic!("expected Value::Text, got {k:?}"); };
if s == key {
return Some(v);
}
}
None
}
pub fn map_insert(value: &mut Value, key: &str, val: impl Into<Value>) {
let Value::Map(entries) = value else {
panic!("expected Value::Map, got {value:?}"); };
let val = val.into();
for (k, v) in entries.iter_mut() {
let Value::Text(s) = k else {
panic!("expected Value::Text, got {k:?}"); };
if s == key {
*v = val;
return;
}
}
entries.push((Value::Text(String::from(key)), val));
}
pub fn as_text(value: &Value) -> Option<&str> {
match value {
Value::Text(s) => Some(s),
_ => None, }
}
pub fn as_u64(value: &Value) -> Option<u64> {
match value {
Value::Integer(i) => u64::try_from(i128::from(*i)).ok(),
_ => None, }
}
pub fn as_bool(value: &Value) -> Option<bool> {
match value {
Value::Bool(b) => Some(*b),
_ => None,
}
}
pub fn cbor_serialize<T: serde::Serialize>(value: &T) -> Value {
let mut bytes = Vec::new();
ciborium::into_writer(value, &mut bytes).expect("CBOR serialization failed");
ciborium::from_reader(&bytes[..]).expect("CBOR deserialization failed")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cbor_map_macro() {
let m = cbor_map! {
"type" => "integer",
"min_value" => 0
};
assert_eq!(as_text(map_get(&m, "type").unwrap()), Some("integer"));
assert_eq!(as_u64(map_get(&m, "min_value").unwrap()), Some(0));
}
#[test]
fn test_cbor_array_macro() {
let a = cbor_array![Value::from("a"), Value::from("b")];
if let Value::Array(items) = &a {
assert_eq!(items.len(), 2);
} else {
panic!("expected array"); }
}
#[test]
fn test_map_insert() {
let mut m = cbor_map! { "a" => 1 };
map_insert(&mut m, "b", 2);
assert_eq!(as_u64(map_get(&m, "b").unwrap()), Some(2));
map_insert(&mut m, "a", 10);
assert_eq!(as_u64(map_get(&m, "a").unwrap()), Some(10));
}
#[test]
fn test_as_bool() {
assert_eq!(as_bool(&Value::Bool(true)), Some(true));
assert_eq!(as_bool(&Value::Bool(false)), Some(false));
assert_eq!(as_bool(&Value::from(42)), None);
}
#[test]
fn test_cbor_serialize() {
let v = cbor_serialize(&42i32);
assert_eq!(as_u64(&v), Some(42));
let v = cbor_serialize(&"hello");
assert_eq!(as_text(&v), Some("hello"));
}
}