#[doc(hidden)]
#[macro_export]
macro_rules! __vld_resolve_key {
($default:expr) => {
$default
};
($default:expr, $override:expr) => {
$override
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __vld_struct_attrs {
( attrs: $(#[ $($attr:tt)* ])*
body: { $($body:tt)* }
) => {
$crate::__vld_struct_attrs!(@filter [] $(#[ $($attr)* ])*
body: { $($body)* }
);
};
(
@filter [$($acc:tt)*]
#[ into_params ( $($p:tt)* ) ]
$(#[ $($rest:tt)* ])*
body: { $($body:tt)* }
) => {
$crate::__vld_struct_attrs!(@filter [$($acc)*]
$(#[ $($rest)* ])*
body: { $($body)* }
);
};
(
@filter [$($acc:tt)*]
#[ $($attr:tt)* ]
$(#[ $($rest:tt)* ])*
body: { $($body:tt)* }
) => {
$crate::__vld_struct_attrs!(@filter [$($acc)* #[ $($attr)* ]]
$(#[ $($rest)* ])*
body: { $($body)* }
);
};
(
@filter [$($acc:tt)*]
body: { $($body:tt)* }
) => {
$($acc)*
$($body)*
};
}
#[macro_export]
macro_rules! schema {
(
$(#[ $($struct_attr:tt)* ])*
$vis:vis struct $name:ident {
$(
$(#[$field_meta:meta])*
$field_vis:vis $field_name:ident : $field_type:ty $(as $rename:literal)? => $schema:expr
),* $(,)?
}
) => {
$crate::__vld_struct_attrs! {
attrs: $(#[ $($struct_attr)* ])*
body: {
$vis struct $name {
$(
$(#[$field_meta])*
$field_vis $field_name: $field_type,
)*
}
impl $name {
pub fn parse<__VldInputT: $crate::schema::VldInput + ?Sized>(
input: &__VldInputT,
) -> ::std::result::Result<$name, $crate::error::VldError> {
let __vld_json = <__VldInputT as $crate::schema::VldInput>::to_json_value(input)?;
Self::parse_value(&__vld_json)
}
pub fn parse_value(
__vld_json: &$crate::serde_json::Value,
) -> ::std::result::Result<$name, $crate::error::VldError> {
Self::__vld_parse(__vld_json, false)
}
#[doc(hidden)]
pub fn __vld_key(__vld_field: &str, __vld_ser: bool) -> &'static str {
static __VLD_KEYS: ::std::sync::OnceLock<
::std::vec::Vec<(&'static str, ::std::string::String, ::std::string::String)>,
> = ::std::sync::OnceLock::new();
let __vld_keys = __VLD_KEYS.get_or_init(|| {
#[allow(unused_variables)]
let __vld_struct_attrs: &[&str] = &[$(stringify!($($struct_attr)*)),*];
::std::vec![$(
$crate::__private::serde_keys(
stringify!($field_name),
$crate::__vld_resolve_key!(None $(, Some($rename))?),
&[$(stringify!($field_meta)),*],
__vld_struct_attrs,
)
),*]
});
$crate::__private::key_of(__vld_keys, __vld_field, __vld_ser)
}
#[doc(hidden)]
pub fn __vld_parse(
__vld_json: &$crate::serde_json::Value,
__vld_ser: bool,
) -> ::std::result::Result<$name, $crate::error::VldError> {
#[allow(unused_imports)]
use $crate::schema::VldSchema as _;
let __vld_obj = $crate::__private::expect_object(__vld_json)?;
let mut __vld_errors = $crate::error::VldError::new();
$(
#[allow(non_snake_case)]
let $field_name: ::std::option::Option<$field_type> =
$crate::__private::parse_field(
__vld_obj,
Self::__vld_key(stringify!($field_name), __vld_ser),
$crate::__vld_cached!($schema),
&mut __vld_errors,
);
)*
if !__vld_errors.is_empty() $(|| $field_name.is_none())* {
return ::std::result::Result::Err(__vld_errors);
}
::std::result::Result::Ok($name {
$(
$field_name: $field_name.unwrap(),
)*
})
}
}
impl $crate::schema::VldParse for $name {
fn vld_parse_value(
value: &$crate::serde_json::Value,
) -> ::std::result::Result<Self, $crate::error::VldError> {
Self::parse_value(value)
}
}
impl $name {
pub fn validate<__VldT: $crate::serde::Serialize>(
instance: &__VldT,
) -> ::std::result::Result<(), $crate::error::VldError> {
Self::__vld_parse(&$crate::__private::to_json(instance)?, true).map(|_| ())
}
pub fn is_valid<__VldT: $crate::serde::Serialize>(instance: &__VldT) -> bool {
Self::validate(instance).is_ok()
}
}
$crate::__vld_if_openapi! {
impl $name {
pub fn json_schema() -> $crate::serde_json::Value {
#[allow(unused_imports)]
use $crate::schema::VldSchema as _;
#[allow(unused_imports)]
use $crate::openapi::JsonSchema as _;
static __VLD_JSON_SCHEMA: $crate::__private::JsonSchemaCell =
$crate::__private::JsonSchemaCell::new();
__VLD_JSON_SCHEMA.get_or_init(|| $crate::__private::object_schema(::std::vec![
$(
{
let __vld_field_schema = $schema;
(
Self::__vld_key(stringify!($field_name), false),
__vld_field_schema.json_schema(),
__vld_field_schema.is_required(),
)
}
),*
])).clone()
}
pub fn to_openapi_document() -> $crate::serde_json::Value {
$crate::__private::openapi_document(
stringify!($name),
Self::json_schema(),
Self::__vld_nested_schemas(),
)
}
#[doc(hidden)]
pub fn __vld_collect_nested_schemas(
__vld_out: &mut ::std::vec::Vec<$crate::openapi::NestedSchemaEntry>,
) {
#[allow(unused_imports)]
use $crate::schema::VldSchema as _;
$(
$crate::openapi::CollectNestedSchemas::collect_nested_schemas(
&$schema,
__vld_out,
);
)*
}
#[doc(hidden)]
pub fn __vld_nested_schemas()
-> ::std::vec::Vec<$crate::openapi::NestedSchemaEntry>
{
let mut __vld_out: ::std::vec::Vec<$crate::openapi::NestedSchemaEntry> =
::std::vec::Vec::new();
Self::__vld_collect_nested_schemas(&mut __vld_out);
__vld_out
}
}
impl $crate::openapi::OpenApiParameterIn for $name {
fn parameter_in() -> Option<&'static str> {
$crate::schema!(@param_in $(#[ $($struct_attr)* ])*)
}
}
}
}
}
};
(@param_in) => {
None::<&'static str>
};
(@param_in #[ into_params ( $($p:tt)* ) ] $(#[ $($rest:tt)* ])*) => {
match $crate::schema!(@param_in_args $($p)*) {
Some(__vld_in) => Some(__vld_in),
None => $crate::schema!(@param_in $(#[ $($rest)* ])*),
}
};
(@param_in #[ $($skip:tt)* ] $(#[ $($rest:tt)* ])*) => {
$crate::schema!(@param_in $(#[ $($rest)* ])*)
};
(@param_in_args) => { None::<&'static str> };
(@param_in_args parameter_in = Query $($rest:tt)*) => { Some("query") };
(@param_in_args parameter_in = Path $($rest:tt)*) => { Some("path") };
(@param_in_args parameter_in = Header $($rest:tt)*) => { Some("header") };
(@param_in_args parameter_in = Cookie $($rest:tt)*) => { Some("cookie") };
(@param_in_args $skip:tt $($rest:tt)*) => { $crate::schema!(@param_in_args $($rest)*) };
}
#[macro_export]
macro_rules! schema_validated {
(
$(#[ $($struct_attr:tt)* ])*
$vis:vis struct $name:ident {
$(
$(#[$field_meta:meta])*
$field_vis:vis $field_name:ident : $field_type:ty $(as $rename:literal)? => $schema:expr
),* $(,)?
}
) => {
$crate::schema! {
$(#[ $($struct_attr)* ])*
$vis struct $name {
$(
$(#[$field_meta])*
$field_vis $field_name : $field_type $(as $rename)? => $schema
),*
}
}
$crate::impl_validate_fields!(@keyed $name {
$( $field_name : $field_type => [<$name>::__vld_key(stringify!($field_name), false)] $schema ),*
});
};
}
#[macro_export]
macro_rules! nested {
($ty:ty) => {
$crate::nested_named(
{
static __VLD_NAME: ::std::sync::OnceLock<::std::string::String> =
::std::sync::OnceLock::new();
__VLD_NAME
.get_or_init(|| $crate::__private::component_name(stringify!($ty)))
.as_str()
},
<$ty>::parse_value,
$crate::__vld_nested_schema_fn!($ty),
$crate::__vld_nested_collect_fn!($ty),
)
};
}