lottie_tools/validator/
schema.rs

1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Representation of a JSON Schema. Note that this is built to be used for
16//! Lottie schema. As a result some assumptions have been made and features that
17//! are not used by Lottie schema specification might not be implemented.
18
19use pointer::RefResolver;
20use serde_json::Value;
21use subschema::{SchemaKeyword, Subschema};
22use thiserror::Error;
23
24mod applicator;
25mod assertion;
26mod pointer;
27mod subschema;
28mod utils;
29
30#[derive(Debug, Error)]
31pub enum SchemaError<'a> {
32    #[error("Unkown instance type <{0}>.")]
33    UnkownInstanceType(&'a str),
34    #[error("Expected {expected}, but received <{value}>.")]
35    UnexpectedValue { expected: &'a str, value: &'a Value },
36    #[error("Unknown keyword <{0}>.")]
37    UnkownKeyword(&'a str),
38    #[error(transparent)]
39    RegexError(#[from] regex::Error),
40    #[error("Failed to resolve pointer <{0}>")]
41    UnresolvableRef(&'a str),
42}
43
44#[derive(Debug, Error)]
45#[error("Node {instance} failed to validate against subschema {subschema:?}")]
46pub struct ValidationError<'i, 's> {
47    instance: &'i Value,
48    subschema: &'s Subschema<'s>,
49}
50
51/// Represents a schema file.
52pub struct Schema<'a> {
53    // ref_resolver: Rc<RefResolver<'a>>,
54    root_subschema: Subschema<'a>,
55}
56
57impl<'a> Schema<'a> {
58    /// Creates a new [Schema] from a root [Value]. The result can be later to
59    /// validate JSON instances against this schema.
60    ///
61    /// ```
62    /// # use serde_json::json;
63    /// # use lottie_tools::validator::Schema;
64    /// let s = Schema::from_json(&json!(true)).unwrap();
65    /// assert!(s.validate(&json!(42)).is_ok());
66    /// ```
67    pub fn from_json(input: &'a Value) -> Result<Self, SchemaError<'a>> {
68        let ref_resolver = RefResolver::new(input);
69        let root_subschema = Subschema::from_json(input, &ref_resolver)?;
70
71        Ok(Schema { root_subschema })
72    }
73
74    /// Validates a JSON [Value] against this [Schema].
75    ///
76    /// ```
77    /// # use serde_json::json;
78    /// # use lottie_tools::validator::Schema;
79    /// let s = Schema::from_json(&json!(true)).unwrap();
80    /// assert!(s.validate(&json!(42)).is_ok());
81    /// ```
82    pub fn validate<'i>(&'a self, instance: &'i Value) -> Result<(), ValidationError<'i, 'a>> {
83        self.root_subschema.validate(instance)
84    }
85}