|
1 | | -use std::{ |
2 | | - any::{type_name, TypeId}, |
3 | | - cell::RefCell, |
4 | | - collections::{HashMap, VecDeque}, |
5 | | -}; |
| 1 | +mod context; |
6 | 2 |
|
7 | | -use jsonschema::{ |
8 | | - output::{BasicOutput, ErrorDescription, OutputUnit}, |
9 | | - JSONSchema, |
10 | | -}; |
11 | | -use schemars::gen::{SchemaGenerator, SchemaSettings}; |
12 | | -use serde_json::{Map, Value}; |
13 | | - |
14 | | -thread_local! { |
15 | | - static CONTEXT: RefCell<SchemaContext> = RefCell::new(SchemaContext::new()); |
16 | | -} |
17 | | - |
18 | | -pub(crate) struct SchemaContext { |
19 | | - pub generator: SchemaGenerator, |
20 | | - pub schemas: HashMap<TypeId, JSONSchema>, |
21 | | -} |
22 | | - |
23 | | -impl SchemaContext { |
24 | | - pub fn new() -> Self { |
25 | | - Self { |
26 | | - generator: SchemaSettings::draft07() |
27 | | - .with(|settings| settings.inline_subschemas = true) |
28 | | - .into_generator(), |
29 | | - schemas: HashMap::default(), |
30 | | - } |
31 | | - } |
32 | | - |
33 | | - pub fn validate<T>(value: &Value) -> Result<(), VecDeque<OutputUnit<ErrorDescription>>> |
34 | | - where |
35 | | - T: crate::traits::validated::Deserialize + schemars::JsonSchema + 'static, |
36 | | - { |
37 | | - CONTEXT.with(|ctx| { |
38 | | - let ctx = &mut *ctx.borrow_mut(); |
39 | | - let schema = ctx.schemas.entry(TypeId::of::<T>()).or_insert_with(|| { |
40 | | - match jsonschema::JSONSchema::compile( |
41 | | - &serde_json::to_value(ctx.generator.root_schema_for::<T>()).unwrap(), |
42 | | - ) { |
43 | | - Ok(s) => s, |
44 | | - Err(error) => { |
45 | | - tracing::error!( |
46 | | - %error, |
47 | | - type_name = type_name::<T>(), |
48 | | - "invalid JSON schema for type" |
49 | | - ); |
50 | | - JSONSchema::compile(&Value::Object(Map::default())).unwrap() |
51 | | - } |
52 | | - } |
53 | | - }); |
54 | | - |
55 | | - match schema.apply(value).basic() { |
56 | | - BasicOutput::Valid(_) => Ok(()), |
57 | | - BasicOutput::Invalid(v) => Err(v), |
58 | | - } |
59 | | - }) |
60 | | - } |
61 | | -} |
| 3 | +pub(crate) use context::SchemaContext; |
0 commit comments