extern crate self as rydantic;
mod asynchronous;
mod borrowed;
#[cfg(feature = "capnp")]
pub mod capnp_support;
#[cfg(feature = "chrono")]
mod dates;
#[cfg(feature = "decimal")]
mod decimal;
mod direct;
#[cfg(feature = "capnp")]
pub use capnp;
#[cfg(feature = "capnp")]
pub use capnp_support::{CapnpEnum, CapnpModel};
#[cfg(feature = "dynamic")]
mod dynamic;
mod error;
mod object;
pub mod rules;
pub mod schema;
pub mod stream;
mod types;
pub use asynchronous::{AsyncCheck, AsyncValidated, BoxFuture};
pub use borrowed::{BorrowModel, BorrowType, BorrowValidated, Input};
#[cfg(feature = "chrono")]
pub use chrono;
#[cfg(feature = "dynamic")]
pub use dynamic::{DynamicModel, SchemaError};
pub use error::{Context, PathSegment, Stage, ValidationError, ValidationErrors};
pub use object::{ExtraFields, ObjectType};
#[cfg(feature = "decimal")]
pub use rust_decimal;
#[cfg(feature = "derive")]
pub use rydantic_derive::Model;
pub use schema::{LocalRule, SchemaContext, SchemaMode, SchemaReport};
pub use serde_json::value::RawValue;
pub use serde_json::{json, Value};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TypeKind {
String,
Number,
Boolean,
Array,
Object,
Any,
Decimal,
}
pub trait JsonType: Sized {
fn decode(value: Value, ctx: &mut Context, coerce: bool) -> Option<Self>;
fn decode_input(input: Input<'_>, ctx: &mut Context, coerce: bool) -> Option<Self> {
Self::decode(input.into_value(ctx)?, ctx, coerce)
}
fn prepare_default(self, ctx: &mut Context) -> Option<Self> {
let value = self.encode_input(ctx);
Self::decode(value, ctx, false)
}
fn encode(&self, ctx: &mut Context) -> Value;
fn encode_input(&self, ctx: &mut Context) -> Value {
self.encode(ctx)
}
fn schema(ctx: &mut SchemaContext, coerce: bool) -> Value;
fn validate_into(&self, _ctx: &mut Context) {}
fn normalize(self, rules: &rules::Rules, ctx: &mut Context) -> Option<Self> {
if !rules.normalizes() {
return Some(self);
}
let mut value = self.encode_input(ctx);
rules.prepare(&mut value);
Self::decode(value, ctx, false)
}
fn validate_rules(&self, rules: &rules::Rules, ctx: &mut Context) {
rules.validate(&self.encode(ctx), ctx);
}
fn async_required(_seen: &mut std::collections::HashSet<&'static str>) -> bool {
false
}
fn missing() -> Option<Self> {
None
}
fn allows_missing() -> bool {
false
}
fn kind() -> TypeKind {
TypeKind::Any
}
}
pub trait StringType {}
pub trait NumericType {}
pub trait LengthType {}
pub trait Model: JsonType {
fn parse_json(input: &str) -> Result<Self, ValidationErrors> {
let raw = serde_json::from_str::<&RawValue>(input).map_err(borrowed::json_error)?;
Self::parse_raw(raw)
}
fn parse_slice(input: &[u8]) -> Result<Self, ValidationErrors> {
let raw = serde_json::from_slice::<&RawValue>(input).map_err(borrowed::json_error)?;
Self::parse_raw(raw)
}
fn parse_raw(raw: &RawValue) -> Result<Self, ValidationErrors> {
asynchronous::sync_guard(Self::async_required(&mut std::collections::HashSet::new()))?;
let mut ctx = Context::new();
let model = Self::decode_input(Input::Borrowed(raw), &mut ctx, false);
ctx.finish(model)
}
fn parse_value(value: Value) -> Result<Self, ValidationErrors> {
asynchronous::sync_guard(Self::async_required(&mut std::collections::HashSet::new()))?;
let mut ctx = Context::new();
let model = Self::decode(value, &mut ctx, false);
ctx.finish(model)
}
fn validate(&self) -> Result<(), ValidationErrors> {
asynchronous::sync_guard(Self::async_required(&mut std::collections::HashSet::new()))?;
let mut ctx = Context::new();
self.validate_into(&mut ctx);
ctx.result()
}
fn dump(&self) -> Result<Value, ValidationErrors> {
self.validate()?;
let mut ctx = Context::new();
let value = self.encode(&mut ctx);
ctx.finish(Some(value))
}
fn dump_json(&self) -> Result<String, ValidationErrors> {
let value = self.dump()?;
serde_json::to_string(&value).map_err(|error| {
ValidationError::new("serialization", error.to_string())
.with_stage(Stage::Serialize)
.into()
})
}
fn json_schema(mode: SchemaMode) -> Value {
let mut ctx = SchemaContext::new(mode);
let root = Self::schema(&mut ctx, false);
ctx.finish(root)
}
fn schema_report(mode: SchemaMode) -> SchemaReport {
SchemaReport::new(Self::json_schema(mode))
}
fn parse_reader<R: std::io::Read>(reader: R) -> Result<Self, ValidationErrors> {
let raw =
serde_json::from_reader::<_, Box<RawValue>>(reader).map_err(borrowed::json_error)?;
Self::parse_raw(&raw)
}
fn parse_json_async(
input: &str,
) -> impl std::future::Future<Output = Result<Self, ValidationErrors>> + Send
where
Self: AsyncCheck + Send,
{
async move {
let raw = serde_json::from_str::<&RawValue>(input).map_err(borrowed::json_error)?;
Self::parse_raw_async(raw).await
}
}
fn parse_raw_async(
raw: &RawValue,
) -> impl std::future::Future<Output = Result<Self, ValidationErrors>> + Send
where
Self: AsyncCheck + Send,
{
async move {
let mut ctx = Context::new();
let model = Self::decode_input(Input::Borrowed(raw), &mut ctx, false);
let model = ctx.finish(model)?;
let mut ctx = Context::new();
model.check_async(&mut ctx).await;
ctx.result()?;
Ok(model)
}
}
fn parse_value_async(
value: Value,
) -> impl std::future::Future<Output = Result<Self, ValidationErrors>> + Send
where
Self: AsyncCheck + Send,
{
async move {
let mut ctx = Context::new();
let model = Self::decode(value, &mut ctx, false);
let model = ctx.finish(model)?;
let mut ctx = Context::new();
model.check_async(&mut ctx).await;
ctx.result()?;
Ok(model)
}
}
fn validate_async(
&self,
) -> impl std::future::Future<Output = Result<(), ValidationErrors>> + Send
where
Self: AsyncCheck,
{
async move {
let mut ctx = Context::new();
self.validate_into(&mut ctx);
ctx.result()?;
let mut ctx = Context::new();
self.check_async(&mut ctx).await;
ctx.result()
}
}
fn dump_async(
&self,
) -> impl std::future::Future<Output = Result<Value, ValidationErrors>> + Send
where
Self: AsyncCheck,
{
async move {
self.validate_async().await?;
let mut ctx = Context::new();
let value = self.encode(&mut ctx);
ctx.finish(Some(value))
}
}
fn dump_json_async(
&self,
) -> impl std::future::Future<Output = Result<String, ValidationErrors>> + Send
where
Self: AsyncCheck,
{
async move { Ok(self.dump_async().await?.to_string()) }
}
fn parse_validated_json_async(
input: &str,
) -> impl std::future::Future<Output = Result<AsyncValidated<Self>, ValidationErrors>> + Send
where
Self: AsyncCheck + Send,
{
async move {
Self::parse_json_async(input)
.await
.map(AsyncValidated::checked)
}
}
fn parse_validated_json(input: &str) -> Result<Validated<Self>, ValidationErrors> {
Self::parse_json(input).map(Validated)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Validated<T: Model>(T);
impl<T: Model> Validated<T> {
pub fn new(value: T) -> Result<Self, ValidationErrors> {
value.validate()?;
Ok(Self(value))
}
pub fn get(&self) -> &T {
&self.0
}
pub fn into_inner(self) -> T {
self.0
}
}
impl<T: Model> std::ops::Deref for Validated<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T: Model> serde::Serialize for Validated<T> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let value = self.0.dump().map_err(serde::ser::Error::custom)?;
serde::Serialize::serialize(&value, serializer)
}
}
impl<'de, T: Model> serde::Deserialize<'de> for Validated<T> {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let raw = <Box<RawValue> as serde::Deserialize>::deserialize(deserializer)?;
T::parse_raw(&raw)
.map(Self)
.map_err(serde::de::Error::custom)
}
}
#[doc(hidden)]
pub mod __private {
pub use crate::object::{check_names, flatten_schema, merge};
pub use regex;
pub use serde;
pub use serde_json;
pub fn number(literal: &str) -> serde_json::Number {
literal
.parse()
.expect("numeric literal checked by the derive macro")
}
}