1use crate::context::PathPart;
6use crate::value::Value;
7use crate::Schema;
8
9#[derive(Clone, Debug)]
11pub struct StandardSchema<'s> {
12 pub version: u32,
14 pub vendor: &'static str,
16 schema: &'s Schema,
17}
18
19#[derive(Clone, Debug, PartialEq)]
21pub struct StandardIssue {
22 pub message: String,
23 pub path: Vec<PathPart>,
24}
25
26#[derive(Clone, Debug, PartialEq)]
29pub struct StandardResult {
30 pub value: Option<Value>,
31 pub issues: Vec<StandardIssue>,
32}
33
34impl<'s> StandardSchema<'s> {
35 pub fn validate(&self, input: Value) -> StandardResult {
37 match self.schema.validate(input) {
38 Ok(value) => StandardResult {
39 value: Some(value),
40 issues: Vec::new(),
41 },
42 Err(e) => StandardResult {
43 value: None,
44 issues: e
45 .issues
46 .into_iter()
47 .map(|i| StandardIssue {
48 message: i.text,
49 path: i.path_arr,
50 })
51 .collect(),
52 },
53 }
54 }
55}
56
57impl Schema {
58 pub fn standard(&self) -> StandardSchema<'_> {
60 StandardSchema {
61 version: 1,
62 vendor: "shape",
63 schema: self,
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use crate::node::Token;
72 use crate::spec::obj;
73 use crate::Spec;
74
75 #[test]
76 fn reports_issues_or_a_value() {
77 let s = Schema::new(obj([("a", Spec::from(Token::Number))]));
78 let std = s.standard();
79 assert_eq!((std.version, std.vendor), (1, "shape"));
80 let ok = std.validate(Value::from(serde_json::json!({"a": 1})));
81 assert!(ok.issues.is_empty() && ok.value.is_some());
82 let bad = std.validate(Value::from(serde_json::json!({"a": "x"})));
83 assert!(bad.value.is_none());
84 assert_eq!(bad.issues[0].path, vec![PathPart::Key("a".into())]);
85 assert!(bad.issues[0].message.contains("not of type number"));
86 }
87}