use crate::{
formats::Separator,
prelude::{Schema as WrapSchema, *},
};
use ::schemars_0_8::{
gen::SchemaGenerator,
schema::{ArrayValidation, InstanceType, Schema, SchemaObject},
JsonSchema,
};
use std::borrow::Cow;
pub trait JsonSchemaAs<T: ?Sized> {
fn is_referenceable() -> bool {
true
}
fn schema_name() -> String;
fn schema_id() -> Cow<'static, str> {
Cow::Owned(Self::schema_name())
}
fn json_schema(gen: &mut SchemaGenerator) -> Schema;
}
impl<T, TA> JsonSchema for WrapSchema<T, TA>
where
T: ?Sized,
TA: JsonSchemaAs<T>,
{
fn schema_name() -> String {
TA::schema_name()
}
fn schema_id() -> Cow<'static, str> {
TA::schema_id()
}
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
TA::json_schema(gen)
}
fn is_referenceable() -> bool {
TA::is_referenceable()
}
}
macro_rules! forward_schema {
($fwd:ty) => {
fn schema_name() -> String {
<$fwd as JsonSchema>::schema_name()
}
fn schema_id() -> Cow<'static, str> {
<$fwd as JsonSchema>::schema_id()
}
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
<$fwd as JsonSchema>::json_schema(gen)
}
fn is_referenceable() -> bool {
<$fwd as JsonSchema>::is_referenceable()
}
};
}
impl<'a, T: 'a, TA: 'a> JsonSchemaAs<&'a T> for &'a TA
where
T: ?Sized,
TA: JsonSchemaAs<T>,
{
forward_schema!(&'a WrapSchema<T, TA>);
}
impl<'a, T: 'a, TA: 'a> JsonSchemaAs<&'a mut T> for &'a mut TA
where
T: ?Sized,
TA: JsonSchemaAs<T>,
{
forward_schema!(&'a mut WrapSchema<T, TA>);
}
impl<T, TA> JsonSchemaAs<Option<T>> for Option<TA>
where
TA: JsonSchemaAs<T>,
{
forward_schema!(Option<WrapSchema<T, TA>>);
}
impl<T, TA> JsonSchemaAs<Box<T>> for Box<TA>
where
T: ?Sized,
TA: JsonSchemaAs<T>,
{
forward_schema!(Box<WrapSchema<T, TA>>);
}
impl<T, TA> JsonSchemaAs<Rc<T>> for Rc<TA>
where
T: ?Sized,
TA: JsonSchemaAs<T>,
{
forward_schema!(Rc<WrapSchema<T, TA>>);
}
impl<T, TA> JsonSchemaAs<Arc<T>> for Arc<TA>
where
T: ?Sized,
TA: JsonSchemaAs<T>,
{
forward_schema!(Arc<WrapSchema<T, TA>>);
}
impl<T, TA> JsonSchemaAs<Vec<T>> for Vec<TA>
where
TA: JsonSchemaAs<T>,
{
forward_schema!(Vec<WrapSchema<T, TA>>);
}
impl<T, TA> JsonSchemaAs<VecDeque<T>> for VecDeque<TA>
where
TA: JsonSchemaAs<T>,
{
forward_schema!(VecDeque<WrapSchema<T, TA>>);
}
impl<K, V, KA, VA> JsonSchemaAs<BTreeMap<K, V>> for BTreeMap<KA, VA>
where
VA: JsonSchemaAs<V>,
{
forward_schema!(BTreeMap<WrapSchema<K, KA>, WrapSchema<V, VA>>);
}
impl<K, V, S, KA, VA> JsonSchemaAs<HashMap<K, V, S>> for HashMap<KA, VA, S>
where
VA: JsonSchemaAs<V>,
{
forward_schema!(HashMap<WrapSchema<K, KA>, WrapSchema<V, VA>, S>);
}
impl<T, TA> JsonSchemaAs<BTreeSet<T>> for BTreeSet<TA>
where
TA: JsonSchemaAs<T>,
{
forward_schema!(BTreeSet<WrapSchema<T, TA>>);
}
impl<T, TA, S> JsonSchemaAs<T> for HashSet<TA, S>
where
TA: JsonSchemaAs<T>,
{
forward_schema!(HashSet<WrapSchema<T, TA>, S>);
}
impl<T, TA, const N: usize> JsonSchemaAs<[T; N]> for [TA; N]
where
TA: JsonSchemaAs<T>,
{
fn schema_name() -> String {
std::format!("[{}; {}]", <WrapSchema<T, TA>>::schema_name(), N)
}
fn schema_id() -> Cow<'static, str> {
std::format!("[{}; {}]", <WrapSchema<T, TA>>::schema_id(), N).into()
}
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
let (max, min) = match N.try_into() {
Ok(len) => (Some(len), Some(len)),
Err(_) => (None, Some(u32::MAX)),
};
SchemaObject {
instance_type: Some(InstanceType::Array.into()),
array: Some(Box::new(ArrayValidation {
items: Some(gen.subschema_for::<WrapSchema<T, TA>>().into()),
max_items: max,
min_items: min,
..Default::default()
})),
..Default::default()
}
.into()
}
fn is_referenceable() -> bool {
false
}
}
macro_rules! schema_for_tuple {
(
( $( $ts:ident )+ )
( $( $as:ident )+ )
) => {
impl<$($ts,)+ $($as,)+> JsonSchemaAs<($($ts,)+)> for ($($as,)+)
where
$( $as: JsonSchemaAs<$ts>, )+
{
forward_schema!(( $( WrapSchema<$ts, $as>, )+ ));
}
}
}
impl JsonSchemaAs<()> for () {
forward_schema!(());
}
schema_for_tuple!((T0)(A0));
schema_for_tuple!((T0 T1) (A0 A1));
schema_for_tuple!((T0 T1 T2) (A0 A1 A2));
schema_for_tuple!((T0 T1 T2 T3) (A0 A1 A2 A3));
schema_for_tuple!((T0 T1 T2 T3 T4) (A0 A1 A2 A3 A4));
schema_for_tuple!((T0 T1 T2 T3 T4 T5) (A0 A1 A2 A3 A4 A5));
schema_for_tuple!((T0 T1 T2 T3 T4 T5 T6) (A0 A1 A2 A3 A4 A5 A6));
schema_for_tuple!((T0 T1 T2 T3 T4 T5 T6 T7) (A0 A1 A2 A3 A4 A5 A6 A7));
schema_for_tuple!((T0 T1 T2 T3 T4 T5 T6 T7 T8) (A0 A1 A2 A3 A4 A5 A6 A7 A8));
schema_for_tuple!((T0 T1 T2 T3 T4 T5 T6 T7 T8 T9) (A0 A1 A2 A3 A4 A5 A6 A7 A8 A9));
schema_for_tuple!((T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10) (A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10));
schema_for_tuple!((T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11) (A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11));
schema_for_tuple!(
(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12)
(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12)
);
schema_for_tuple!(
(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13)
(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13)
);
schema_for_tuple!(
(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14)
(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14)
);
schema_for_tuple!(
(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15)
(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15)
);
impl<T: JsonSchema> JsonSchemaAs<T> for Same {
forward_schema!(T);
}
impl<T> JsonSchemaAs<T> for DisplayFromStr {
forward_schema!(String);
}
impl<'a, T: 'a> JsonSchemaAs<Cow<'a, T>> for BorrowCow
where
T: ?Sized + ToOwned,
Cow<'a, T>: JsonSchema,
{
forward_schema!(Cow<'a, T>);
}
impl<T> JsonSchemaAs<T> for Bytes {
forward_schema!(Vec<u8>);
}
impl<T, TA> JsonSchemaAs<T> for DefaultOnError<TA>
where
TA: JsonSchemaAs<T>,
{
forward_schema!(WrapSchema<T, TA>);
}
impl<T, TA> JsonSchemaAs<T> for DefaultOnNull<TA>
where
TA: JsonSchemaAs<T>,
{
forward_schema!(Option<WrapSchema<T, TA>>);
}
impl<O, T: JsonSchema> JsonSchemaAs<O> for FromInto<T> {
forward_schema!(T);
}
impl<O, T: JsonSchema> JsonSchemaAs<O> for FromIntoRef<T> {
forward_schema!(T);
}
impl<T, U: JsonSchema> JsonSchemaAs<T> for TryFromInto<U> {
forward_schema!(U);
}
impl<T, U: JsonSchema> JsonSchemaAs<T> for TryFromIntoRef<U> {
forward_schema!(U);
}
macro_rules! schema_for_map {
($type:ty) => {
impl<K, V, KA, VA> JsonSchemaAs<$type> for Map<KA, VA>
where
VA: JsonSchemaAs<V>,
{
forward_schema!(WrapSchema<BTreeMap<K, V>, BTreeMap<KA, VA>>);
}
};
}
schema_for_map!([(K, V)]);
schema_for_map!(BTreeSet<(K, V)>);
schema_for_map!(BinaryHeap<(K, V)>);
schema_for_map!(Box<[(K, V)]>);
schema_for_map!(LinkedList<(K, V)>);
schema_for_map!(Vec<(K, V)>);
schema_for_map!(VecDeque<(K, V)>);
impl<K, V, S, KA, VA> JsonSchemaAs<HashSet<(K, V), S>> for Map<KA, VA>
where
VA: JsonSchemaAs<V>,
{
forward_schema!(WrapSchema<BTreeMap<K, V>, BTreeMap<KA, VA>>);
}
impl<K, V, KA, VA, const N: usize> JsonSchemaAs<[(K, V); N]> for Map<KA, VA>
where
VA: JsonSchemaAs<V>,
{
forward_schema!(WrapSchema<BTreeMap<K, V>, BTreeMap<KA, VA>>);
}
macro_rules! map_first_last_wins_schema {
($(=> $extra:ident)? $type:ty) => {
impl<K, V, $($extra,)? KA, VA> JsonSchemaAs<$type> for MapFirstKeyWins<KA, VA>
where
VA: JsonSchemaAs<V>,
{
forward_schema!(BTreeMap<WrapSchema<K, KA>, WrapSchema<V, VA>>);
}
impl<K, V, $($extra,)? KA, VA> JsonSchemaAs<$type> for MapPreventDuplicates<KA, VA>
where
VA: JsonSchemaAs<V>,
{
forward_schema!(BTreeMap<WrapSchema<K, KA>, WrapSchema<V, VA>>);
}
}
}
map_first_last_wins_schema!(BTreeMap<K, V>);
map_first_last_wins_schema!(=> S HashMap<K, V, S>);
#[cfg(feature = "hashbrown_0_14")]
map_first_last_wins_schema!(=> S hashbrown_0_14::HashMap<K, V, S>);
#[cfg(feature = "indexmap_1")]
map_first_last_wins_schema!(=> S indexmap_1::IndexMap<K, V, S>);
#[cfg(feature = "indexmap_2")]
map_first_last_wins_schema!(=> S indexmap_2::IndexMap<K, V, S>);
impl<T, TA> JsonSchemaAs<T> for SetLastValueWins<TA>
where
TA: JsonSchemaAs<T>,
{
fn schema_id() -> Cow<'static, str> {
std::format!(
"serde_with::SetLastValueWins<{}>",
<WrapSchema<T, TA> as JsonSchema>::schema_id()
)
.into()
}
fn schema_name() -> String {
std::format!(
"SetLastValueWins<{}>",
<WrapSchema<T, TA> as JsonSchema>::schema_name()
)
}
fn json_schema(gen: &mut ::schemars_0_8::gen::SchemaGenerator) -> Schema {
let schema = <WrapSchema<T, TA> as JsonSchema>::json_schema(gen);
let mut schema = schema.into_object();
if let Some(array) = &mut schema.array {
array.unique_items = None;
}
schema.into()
}
fn is_referenceable() -> bool {
false
}
}
impl<T, TA> JsonSchemaAs<T> for SetPreventDuplicates<TA>
where
TA: JsonSchemaAs<T>,
{
forward_schema!(WrapSchema<T, TA>);
}
impl<SEP, T, TA> JsonSchemaAs<T> for StringWithSeparator<SEP, TA>
where
SEP: Separator,
{
forward_schema!(String);
}
impl<T, TA> JsonSchemaAs<Vec<T>> for VecSkipError<TA>
where
TA: JsonSchemaAs<T>,
{
forward_schema!(Vec<WrapSchema<T, TA>>);
}