Skip to content

Commit

Permalink
refactor:
Browse files Browse the repository at this point in the history
  • Loading branch information
yassun7010 committed Jan 14, 2024
1 parent e90419c commit 7203955
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 97 deletions.
3 changes: 3 additions & 0 deletions axum_serde_valid/src/features.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
#[cfg(feature = "jsonschema")]
pub mod jsonschema;

#[cfg(feature = "fluent")]
pub mod fluent;
62 changes: 61 additions & 1 deletion axum_serde_valid/src/features/jsonschema.rs
Original file line number Diff line number Diff line change
@@ -1 +1,61 @@
pub mod context;
use std::{
any::{type_name, TypeId},
cell::RefCell,
collections::{HashMap, VecDeque},
};

use jsonschema::{
output::{BasicOutput, ErrorDescription, OutputUnit},
JSONSchema,
};
use schemars::gen::{SchemaGenerator, SchemaSettings};
use serde_json::{Map, Value};

thread_local! {
static CONTEXT: RefCell<SchemaContext> = RefCell::new(SchemaContext::new());
}

pub(crate) struct SchemaContext {
pub generator: SchemaGenerator,
pub schemas: HashMap<TypeId, JSONSchema>,
}

impl SchemaContext {
pub fn new() -> Self {
Self {
generator: SchemaSettings::draft07()
.with(|settings| settings.inline_subschemas = true)
.into_generator(),
schemas: HashMap::default(),
}
}

pub fn validate<T>(value: &Value) -> Result<(), VecDeque<OutputUnit<ErrorDescription>>>
where
T: crate::validated::Deserialize + schemars::JsonSchema + 'static,
{
CONTEXT.with(|ctx| {
let ctx = &mut *ctx.borrow_mut();
let schema = ctx.schemas.entry(TypeId::of::<T>()).or_insert_with(|| {
match jsonschema::JSONSchema::compile(
&serde_json::to_value(ctx.generator.root_schema_for::<T>()).unwrap(),
) {
Ok(s) => s,
Err(error) => {
tracing::error!(
%error,
type_name = type_name::<T>(),
"invalid JSON schema for type"
);
JSONSchema::compile(&Value::Object(Map::default())).unwrap()
}
}
});

match schema.apply(value).basic() {
BasicOutput::Valid(_) => Ok(()),
BasicOutput::Invalid(v) => Err(v),
}
})
}
}
61 changes: 0 additions & 61 deletions axum_serde_valid/src/features/jsonschema/context.rs

This file was deleted.

30 changes: 15 additions & 15 deletions axum_serde_valid/src/rejection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,25 @@ impl From<Rejection> for JsonErrorResponse {
Rejection::Json(error) => Self::FormatError(error.to_string()),
Rejection::SerdeJson(error) => Self::FormatError(error.to_string()),
Rejection::SerdeUrlEncoded(error) => Self::FormatError(error.to_string()),
Rejection::SerdeValid(errors) => Self::ValidationError(JsonSchemaErrorResponse {
errors: errors
.into_flat()
.into_iter()
.map(|error| Error {
error: error.error,
instance_location: JsonPointer(error.instance_location.to_string()),
keyword_location: None,
})
.collect::<Vec<_>>(),
}),
Rejection::SerdeValid(errors) => {
let iter = errors.into_flat().into_iter().map(|err| Error {
error: err.error,
instance_location: JsonPointer(err.instance_location.to_string()),
keyword_location: None,
});

Self::ValidationError(JsonSchemaErrorResponse {
errors: iter.collect::<Vec<_>>(),
})
}
#[cfg(feature = "jsonschema")]
Rejection::Jsonschema(errors) => Self::ValidationError(JsonSchemaErrorResponse {
errors: errors
.into_iter()
.map(|error| Error {
error: error.error_description().to_string(),
instance_location: JsonPointer(error.instance_location().to_string()),
keyword_location: Some(JsonPointer(error.keyword_location().to_string())),
.map(|err| Error {
error: err.error_description().to_string(),
instance_location: JsonPointer(err.instance_location().to_string()),
keyword_location: Some(JsonPointer(err.keyword_location().to_string())),
})
.collect::<Vec<_>>(),
}),
Expand Down
2 changes: 1 addition & 1 deletion axum_serde_valid/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ where

#[cfg(feature = "jsonschema")]
{
crate::jsonschema::context::SchemaContext::validate::<T>(&value)
crate::jsonschema::SchemaContext::validate::<T>(&value)
.map_err(crate::rejection::Rejection::Jsonschema)?;
}

Expand Down
2 changes: 1 addition & 1 deletion serde_valid/src/features/fluent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod message;
mod try_localize;

pub use error::LocalizedError;
pub use fluent::FluentValue;
pub use fluent::{FluentBundle, FluentError, FluentResource, FluentValue};
pub use localize::Localize;
pub use message::Message;
pub use try_localize::TryLocalize;
4 changes: 2 additions & 2 deletions serde_valid/src/features/fluent/localize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,11 @@ mod test {
use crate::fluent::Message;

use super::*;
use fluent::{bundle::FluentBundle, FluentResource, FluentValue};
use fluent::{FluentBundle, FluentResource, FluentValue};
use serde_json::json;
use unic_langid::LanguageIdentifier;

fn get_bundle() -> FluentBundle<FluentResource, intl_memoizer::IntlLangMemoizer> {
fn get_bundle() -> FluentBundle<FluentResource> {
let ftl_string = ["hello-world = Hello, world!", "intro = Welcome, { $name }."]
.join("\n")
.to_string();
Expand Down
19 changes: 4 additions & 15 deletions serde_valid/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,23 +559,12 @@ pub use validation::{
ValidateUniqueItems,
};

#[cfg(feature = "flatten")]
pub use features::flatten;

#[cfg(feature = "fluent")]
pub use features::fluent;

#[cfg(feature = "json")]
pub use features::json;

#[cfg(feature = "toml")]
pub use features::toml;

#[cfg(feature = "yaml")]
pub use features::yaml;
#[allow(unused_imports)]
pub use features::*;

pub mod export {
pub use once_cell::sync::OnceCell;
pub use fluent;
pub use once_cell;
}

pub trait Validate {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn inner_extract_string_pattern_validator(
);

Ok(quote!(
static #pattern_ident : ::serde_valid::export::OnceCell<::regex::Regex> = ::serde_valid::export::OnceCell::new();
static #pattern_ident : ::serde_valid::export::once_cell::sync::OnceCell<::regex::Regex> = ::serde_valid::export::once_cell::sync::OnceCell::new();
let __pattern = #pattern_ident.get_or_init(|| ::regex::Regex::new(#pattern).unwrap());
if let Err(__composited_error_params) = ::serde_valid::validation::ValidateCompositedPattern::validate_composited_pattern(
#field_ident,
Expand Down

0 comments on commit 7203955

Please sign in to comment.