use serde_json::Value;
use crate::combinators::{
ZCatch, ZDescribe, ZIntersection, ZPipe, ZRefine, ZSuperRefine, ZTransform, ZUnion2,
};
use crate::error::VldError;
use crate::modifiers::{ZDefault, ZNullable, ZNullish, ZOptional};
mod coerced;
mod dyn_schema;
pub mod input;
mod nested;
pub(crate) use dyn_schema::to_json_value;
pub use coerced::parse_coerced;
pub use dyn_schema::DynSchema;
pub use input::VldInput;
pub use nested::{NestedSchema, NestedSchemaCollectFn, NestedSchemaEntry};
#[cfg(feature = "openapi")]
pub trait Schema:
VldSchema + crate::openapi::JsonSchema + crate::openapi::CollectNestedSchemas
{
}
#[cfg(feature = "openapi")]
impl<T> Schema for T where
T: VldSchema + crate::openapi::JsonSchema + crate::openapi::CollectNestedSchemas
{
}
#[cfg(not(feature = "openapi"))]
pub trait Schema: VldSchema {}
#[cfg(not(feature = "openapi"))]
impl<T: VldSchema> Schema for T {}
pub trait VldSchema: Sized {
type Output;
fn parse_value(&self, value: &Value) -> Result<Self::Output, VldError>;
#[doc(hidden)]
fn output_json(&self, _output: &Self::Output) -> Option<Value> {
None
}
fn parse_missing(&self) -> Result<Self::Output, VldError> {
self.parse_value(&Value::Null)
}
fn parse<I: VldInput + ?Sized>(&self, input: &I) -> Result<Self::Output, VldError> {
let json = input.to_json_value()?;
self.parse_value(&json)
}
fn validate<T: serde::Serialize>(&self, value: &T) -> Result<Self::Output, VldError> {
self.parse_value(&to_json_value(value)?)
}
fn is_valid<T: serde::Serialize>(&self, value: &T) -> bool {
self.validate(value).is_ok()
}
fn optional(self) -> ZOptional<Self> {
ZOptional::new(self)
}
fn nullable(self) -> ZNullable<Self> {
ZNullable::new(self)
}
fn with_default(self, value: Self::Output) -> ZDefault<Self>
where
Self::Output: Clone,
{
ZDefault::new(self, value)
}
fn refine<F>(self, check: F, message: &str) -> ZRefine<Self, F>
where
F: Fn(&Self::Output) -> bool,
{
ZRefine::new(self, check, message)
}
fn rule<R>(self, rule: R) -> crate::rules::ZRule<Self, R>
where
Self: Sized,
R: crate::rules::Rule<Self::Output>,
{
crate::rules::ZRule::new(self, rule, None)
}
fn rule_msg<R>(self, rule: R, msg: impl Into<String>) -> crate::rules::ZRule<Self, R>
where
Self: Sized,
R: crate::rules::Rule<Self::Output>,
{
crate::rules::ZRule::new(self, rule, Some(msg.into()))
}
fn try_transform<F, U, E>(self, f: F) -> crate::combinators::ZTryTransform<Self, F, U>
where
F: Fn(Self::Output) -> Result<U, E>,
E: std::fmt::Display,
{
crate::combinators::ZTryTransform::new(self, f)
}
fn transform<F, U>(self, f: F) -> ZTransform<Self, F, U>
where
F: Fn(Self::Output) -> U,
{
ZTransform::new(self, f)
}
fn nullish(self) -> ZNullish<Self> {
ZNullish::new(self)
}
fn catch(self, fallback: Self::Output) -> ZCatch<Self>
where
Self::Output: Clone,
{
ZCatch::new(self, fallback)
}
fn pipe<S: VldSchema>(self, next: S) -> ZPipe<Self, S>
where
Self::Output: serde::Serialize,
{
ZPipe::new(self, next)
}
fn describe(self, description: &str) -> ZDescribe<Self> {
ZDescribe::new(self, description)
}
fn super_refine<F>(self, check: F) -> ZSuperRefine<Self, F>
where
F: Fn(&Self::Output, &mut VldError),
{
ZSuperRefine::new(self, check)
}
fn or<B: VldSchema>(self, other: B) -> ZUnion2<Self, B> {
ZUnion2::new(self, other)
}
fn and<B: VldSchema>(self, other: B) -> ZIntersection<Self, B> {
ZIntersection::new(self, other)
}
fn message(self, msg: impl Into<String>) -> crate::combinators::ZMessage<Self> {
crate::combinators::ZMessage::new(self, msg)
}
}
pub trait VldParse: Sized {
fn vld_parse_value(value: &serde_json::Value) -> Result<Self, crate::error::VldError>;
}