corvus_json_schema/
lib.rs1mod compiler;
23mod dialect;
24mod document;
25mod eval;
26mod formats;
27mod instance;
28mod loader;
29#[rustfmt::skip]
30mod metaschemas;
31mod node;
32mod numbers;
33mod options;
34mod pattern;
35mod results;
36mod uri;
37
38use std::sync::Arc;
39
40use serde_json::Value;
41
42pub use dialect::Dialect;
43pub use document::{JsonDocument, JsonDocumentArray, JsonDocumentObject, JsonDocumentValue, JsonParseError};
44pub use instance::{ArrayView, Instance, Kind, ObjectView, View};
45pub use options::{
46 CompileOptions, DocumentResolver, FormatValidator, SchemaCompilationError, SchemaEvaluationDepthError,
47};
48pub use results::{
49 Annotation, JsonSchemaResultsCollector, ResultsLevel, SchemaResult, collect_annotations, encode_pointer_segment,
50 enumerate_annotations, schema_location_fragment,
51};
52
53pub const VERSION: &str = env!("CARGO_PKG_VERSION");
55
56#[derive(Clone, Debug, PartialEq, Eq)]
58pub enum JsonValidationError {
59 InvalidJson(JsonParseError),
61 DepthExceeded(SchemaEvaluationDepthError),
63}
64
65impl std::fmt::Display for JsonValidationError {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 match self {
68 JsonValidationError::InvalidJson(e) => write!(f, "invalid JSON: {e}"),
69 JsonValidationError::DepthExceeded(e) => e.fmt(f),
70 }
71 }
72}
73
74impl std::error::Error for JsonValidationError {
75 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
76 match self {
77 JsonValidationError::InvalidJson(e) => Some(e),
78 JsonValidationError::DepthExceeded(e) => Some(e),
79 }
80 }
81}
82
83#[derive(Clone)]
85pub struct Validator {
86 program: Arc<eval::Program>,
87}
88
89impl std::fmt::Debug for Validator {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 f.debug_struct("Validator").field("nodes", &self.program.nodes.len()).finish()
92 }
93}
94
95pub fn compile(schema: &Value) -> Result<Validator, SchemaCompilationError> {
98 compile_with(schema, &CompileOptions::default())
99}
100
101pub fn compile_with(schema: &Value, options: &CompileOptions) -> Result<Validator, SchemaCompilationError> {
103 let compiled = compiler::SchemaCompiler::compile(schema.clone(), options)?;
104 Ok(Validator::from_compiled(compiled, options))
105}
106
107pub fn compile_from_uri(uri: &str, options: &CompileOptions) -> Result<Validator, SchemaCompilationError> {
110 let compiled = compiler::SchemaCompiler::compile_from_uri(uri, options)?;
111 Ok(Validator::from_compiled(compiled, options))
112}
113
114impl Validator {
115 fn from_compiled(c: compiler::CompiledSchema, options: &CompileOptions) -> Validator {
116 let program = eval::Program::new(
117 c.nodes,
118 c.root,
119 c.uses_dynamic_scope,
120 options.max_depth,
121 options.formats.clone(),
122 c.documents,
123 c.annotation_sources,
124 options.assert_format.is_some(),
125 );
126 Validator { program: Arc::new(program) }
127 }
128
129 #[inline]
132 pub fn is_valid(&self, instance: &Value) -> bool {
133 eval::Evaluator::new(&self.program, None).validate(instance)
134 }
135
136 pub fn validate(&self, instance: &Value) -> Result<bool, SchemaEvaluationDepthError> {
138 let mut e = eval::Evaluator::new(&self.program, None);
139 let ok = e.validate(instance);
140 if e.depth_exceeded { Err(SchemaEvaluationDepthError) } else { Ok(ok) }
141 }
142
143 pub fn evaluate(
145 &self,
146 instance: &Value,
147 collector: &mut JsonSchemaResultsCollector,
148 ) -> Result<bool, SchemaEvaluationDepthError> {
149 self.evaluate_instance(instance, collector)
150 }
151
152 pub fn validate_instance<'a, I: Instance<'a>>(&self, instance: I) -> Result<bool, SchemaEvaluationDepthError> {
155 let mut e = eval::Evaluator::new(&self.program, None);
156 let ok = e.validate(instance);
157 if e.depth_exceeded { Err(SchemaEvaluationDepthError) } else { Ok(ok) }
158 }
159
160 pub fn validate_json(&self, json: &str) -> Result<bool, JsonValidationError> {
163 JsonDocument::with_document(json, |d| self.validate_instance(d.root()))
164 .map_err(JsonValidationError::InvalidJson)?
165 .map_err(JsonValidationError::DepthExceeded)
166 }
167
168 pub fn evaluate_json(
170 &self,
171 json: &str,
172 collector: &mut JsonSchemaResultsCollector,
173 ) -> Result<bool, JsonValidationError> {
174 JsonDocument::with_document(json, |d| self.evaluate_instance(d.root(), collector))
175 .map_err(JsonValidationError::InvalidJson)?
176 .map_err(JsonValidationError::DepthExceeded)
177 }
178
179 pub fn evaluate_instance<'a, I: Instance<'a>>(
181 &self,
182 instance: I,
183 collector: &mut JsonSchemaResultsCollector,
184 ) -> Result<bool, SchemaEvaluationDepthError> {
185 let mut e = eval::Evaluator::new(&self.program, Some(collector));
186 let ok = e.evaluate(instance);
187 if e.depth_exceeded { Err(SchemaEvaluationDepthError) } else { Ok(ok) }
188 }
189}