1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#![cfg(feature = "serde_json")]
use crate::context::{BasicContext, Context};
use crate::flatten::flatten_from_str;
use crate::ivt::Node;
use crate::util::{ValidateError, ValidateResult};
use crate::validate::validate;
use crate::value::Value;
use serde_json::Value as JSON_Value;
use std::collections::BTreeMap;
use std::convert::TryFrom;
impl TryFrom<&JSON_Value> for Value {
type Error = ValidateError;
fn try_from(value: &JSON_Value) -> Result<Self, Self::Error> {
let result = match value {
JSON_Value::Null => Value::Null,
JSON_Value::Bool(b) => Value::Bool(*b),
JSON_Value::Number(num) => {
if let Some(u) = num.as_u64() {
Value::Integer(u as i128)
} else if let Some(i) = num.as_i64() {
Value::Integer(i as i128)
} else if let Some(f) = num.as_f64() {
Value::from_float(f)
} else {
return Err(ValidateError::ValueError(
"JSON Value::Number conversion failure".into(),
));
}
}
JSON_Value::String(t) => Value::Text(t.clone()),
JSON_Value::Array(a) => {
let array: Result<_, _> = a.iter().map(Value::try_from).collect();
Value::Array(array?)
}
JSON_Value::Object(m) => {
type MapTree = BTreeMap<Value, Value>;
let map: Result<MapTree, _> = m
.iter()
.map(|(k, v)| {
Ok((Value::Text(k.clone()), Value::try_from(v)?))
})
.collect();
Value::Map(map?)
}
};
Ok(result)
}
}
#[test]
fn test_json_number_behavior() {
let json_value: JSON_Value = serde_json::from_str("1").unwrap();
assert!(json_value.as_u64().is_some());
let json_value: JSON_Value = serde_json::from_str("-1").unwrap();
assert!(json_value.as_u64().is_none());
assert!(json_value.as_i64().is_some());
let json_value: JSON_Value = serde_json::from_str("1.0").unwrap();
assert!(json_value.as_u64().is_none());
assert!(json_value.as_i64().is_none());
assert!(json_value.as_f64().is_some());
}
impl TryFrom<JSON_Value> for Value {
type Error = ValidateError;
fn try_from(value: JSON_Value) -> Result<Self, Self::Error> {
Value::try_from(&value)
}
}
pub fn validate_json(node: &Node, value: &JSON_Value, ctx: &dyn Context) -> ValidateResult {
let value = Value::try_from(value)?;
validate(&value, node, ctx)
}
pub fn validate_json_str(name: &str, cddl: &str, json: &str) -> ValidateResult {
let flat_cddl = flatten_from_str(cddl)?;
let ctx = BasicContext::new(flat_cddl);
let rule_node: &Node = ctx
.rules
.get(name)
.ok_or_else(|| ValidateError::MissingRule(name.into()))?;
let json_value: JSON_Value =
serde_json::from_str(json).map_err(|e| ValidateError::ValueError(format!("{}", e)))?;
let value = Value::try_from(json_value)?;
validate(&value, rule_node, &ctx)
}