#![cfg(feature = "serde_cbor")]
use crate::context::{BasicContext, LookupContext};
use crate::flatten::flatten_from_str;
use crate::ivt::RuleDef;
use crate::util::{ValidateError, ValidateResult};
use crate::validate::do_validate;
use crate::value::Value;
use serde_cbor::Value as CBOR_Value;
use std::collections::BTreeMap;
use std::convert::TryFrom;
impl TryFrom<&CBOR_Value> for Value {
type Error = ValidateError;
fn try_from(value: &CBOR_Value) -> Result<Self, Self::Error> {
let result = match value {
CBOR_Value::Null => Value::Null,
CBOR_Value::Bool(b) => Value::Bool(*b),
CBOR_Value::Integer(i) => Value::Integer(*i),
CBOR_Value::Float(f) => Value::from_float(*f),
CBOR_Value::Bytes(b) => Value::Bytes(b.clone()),
CBOR_Value::Text(t) => Value::Text(t.clone()),
CBOR_Value::Array(a) => {
let array: Result<_, _> = a.iter().map(Value::try_from).collect();
Value::Array(array?)
}
CBOR_Value::Map(m) => {
type MapTree = BTreeMap<Value, Value>;
let map: Result<MapTree, _> = m
.iter()
.map(|(k, v)| {
Ok((Value::try_from(k)?, Value::try_from(v)?))
})
.collect();
Value::Map(map?)
}
_ => {
return Err(ValidateError::ValueError(
"can't handle hidden cbor Value".into(),
));
}
};
Ok(result)
}
}
impl TryFrom<CBOR_Value> for Value {
type Error = ValidateError;
fn try_from(value: CBOR_Value) -> Result<Self, Self::Error> {
Value::try_from(&value)
}
}
pub fn validate_cbor(
rule_def: &RuleDef,
value: &CBOR_Value,
ctx: &dyn LookupContext,
) -> ValidateResult {
let value = Value::try_from(value)?;
do_validate(&value, rule_def, ctx)
}
pub fn validate_cbor_bytes(name: &str, cddl: &str, cbor: &[u8]) -> ValidateResult {
let flat_cddl = flatten_from_str(cddl)?;
let ctx = BasicContext::new(flat_cddl);
let rule_def: &RuleDef = ctx
.rules
.get(name)
.ok_or_else(|| ValidateError::MissingRule(name.into()))?;
let cbor_value: CBOR_Value =
serde_cbor::from_slice(cbor).map_err(|e| ValidateError::ValueError(format!("{}", e)))?;
let value = Value::try_from(cbor_value)?;
do_validate(&value, rule_def, &ctx)
}