memphis_rust_community/schemaverse/schema/
json.rs1use 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 {}