memphis_rust_community/schemaverse/schema/
json.rs

1use bytes::Bytes;
2use std::borrow::Cow;
3
4use jsonschema::{Draft, JSONSchema, ValidationError};
5use thiserror::Error;
6
7use crate::schemaverse::schema::{ErrorData, SchemaValidationError, SchemaValidator};
8
9pub struct JsonSchemaValidator {
10    schema: JSONSchema,
11}
12
13impl JsonSchemaValidator {
14    pub fn new(value: serde_json::Value) -> Result<Self, JsonSchemaError> {
15        let schema = JSONSchema::options()
16            .with_draft(Draft::Draft7)
17            .compile(&value)
18            .map_err(|e| JsonSchemaError::SchemaFileError(validation_error_to_owned(e)))?;
19
20        Ok(Self { schema })
21    }
22}
23
24impl SchemaValidator for JsonSchemaValidator {
25    fn validate(&self, message: &Bytes) -> Result<(), SchemaValidationError> {
26        let deserialized = serde_json::from_slice(message).map_err(JsonSchemaError::from)?;
27
28        if let Err(mut e) = self.schema.validate(&deserialized) {
29            let Some(error) = e.next() else {
30                return Err(JsonSchemaError::UnknownError.into());
31            };
32
33            return Err(JsonSchemaError::ValidationError(validation_error_to_owned(error)).into());
34        }
35
36        Ok(())
37    }
38
39    fn from_bytes(bytes: &Bytes) -> Result<Self, SchemaValidationError> {
40        let deserialized = serde_json::from_slice(bytes).map_err(JsonSchemaError::from)?;
41
42        Ok(Self::new(deserialized)?)
43    }
44}
45
46fn validation_error_to_owned(e: ValidationError) -> ValidationError<'static> {
47    ValidationError {
48        instance: Cow::Owned(e.instance.into_owned()),
49        kind: e.kind,
50        instance_path: e.instance_path.to_owned(),
51        schema_path: e.schema_path,
52    }
53}
54
55#[derive(Debug, Error)]
56pub enum JsonSchemaError {
57    #[error("IO Error: {0}")]
58    IoError(#[from] std::io::Error),
59
60    #[error("Error while parsing schema: {0}")]
61    SchemaFileError(ValidationError<'static>),
62
63    #[error("Serde Error: {0}")]
64    SerdeError(#[from] serde_json::Error),
65
66    #[error("Error while validating message: {0}")]
67    ValidationError(ValidationError<'static>),
68
69    #[error("Unknown Error")]
70    UnknownError,
71}
72
73impl ErrorData for JsonSchemaError {}