diff --git a/schemars/src/json_schema_impls.rs b/schemars/src/json_schema_impls.rs deleted file mode 100644 index 6d9e8f1..0000000 --- a/schemars/src/json_schema_impls.rs +++ /dev/null @@ -1,354 +0,0 @@ -use crate::gen::{BoolSchemas, SchemaGenerator}; -use crate::schema::*; -use crate::{JsonSchema, Map, Result}; -use serde_json::json; - -// TODO any other serde/json types other than serde_json value? -// TODO serde yaml value/map under feature flag -// TODO add some inline attributes -// https://github.com/serde-rs/serde/blob/ce75418e40a593fc5c0902cbf4a45305a4178dd7/serde/src/ser/impls.rs -// Cell, RefCell, Mutex, RwLock, Result?, Duration, SystemTime, -// IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6, SocketAddrV6, -// Path, PathBuf, OsStr, OsString, Wrapping, Reverse, AtomicBool, AtomixI8 etc., -// NonZeroU8 etc., ArcWeak, RcWeak, BTreeMap, HashMap, (!)?, Bound?, Range?, RangeInclusive?, -// PhantomData?, CString?, CStr?, fmt::Arguments? - -macro_rules! no_ref_schema { - () => { - fn is_referenceable() -> bool { - false - } - }; -} - -////////// PRIMITIVES ////////// - -macro_rules! simple_impl { - ($type:tt => $instance_type:ident) => { - impl JsonSchema for $type { - no_ref_schema!(); - - fn schema_name() -> String { - stringify!($instance_type).to_owned() - } - - fn json_schema(_: &mut SchemaGenerator) -> Result { - Ok(SchemaObject { - instance_type: Some(InstanceType::$instance_type.into()), - ..Default::default() - } - .into()) - } - } - }; -} - -simple_impl!(str => String); -simple_impl!(String => String); -simple_impl!(bool => Boolean); -simple_impl!(f32 => Number); -simple_impl!(f64 => Number); -simple_impl!(i8 => Integer); -simple_impl!(i16 => Integer); -simple_impl!(i32 => Integer); -simple_impl!(i64 => Integer); -simple_impl!(i128 => Integer); -simple_impl!(isize => Integer); -simple_impl!(u8 => Integer); -simple_impl!(u16 => Integer); -simple_impl!(u32 => Integer); -simple_impl!(u64 => Integer); -simple_impl!(u128 => Integer); -simple_impl!(usize => Integer); -simple_impl!(() => Null); - -impl JsonSchema for char { - no_ref_schema!(); - - fn schema_name() -> String { - "Character".to_owned() - } - - fn json_schema(_: &mut SchemaGenerator) -> Result { - let mut extensions = Map::new(); - extensions.insert("minLength".to_owned(), json!(1)); - extensions.insert("maxLength".to_owned(), json!(1)); - Ok(SchemaObject { - instance_type: Some(InstanceType::String.into()), - extensions, - ..Default::default() - } - .into()) - } -} - -////////// ARRAYS ////////// - -// Does not require T: JsonSchema. -impl JsonSchema for [T; 0] { - no_ref_schema!(); - - fn schema_name() -> String { - "Empty_Array".to_owned() - } - - fn json_schema(_: &mut SchemaGenerator) -> Result { - let mut extensions = Map::new(); - extensions.insert("maxItems".to_owned(), json!(0)); - Ok(SchemaObject { - instance_type: Some(InstanceType::Array.into()), - extensions, - ..Default::default() - } - .into()) - } -} - -macro_rules! array_impls { - ($($len:tt)+) => { - $( - impl JsonSchema for [T; $len] { - no_ref_schema!(); - - fn schema_name() -> String { - format!("Array_Size_{}_Of_{}", $len, T::schema_name()) - } - - fn json_schema(gen: &mut SchemaGenerator) -> Result { - let mut extensions = Map::new(); - extensions.insert("minItems".to_owned(), json!($len)); - extensions.insert("maxItems".to_owned(), json!($len)); - Ok(SchemaObject { - instance_type: Some(InstanceType::Array.into()), - items: Some(gen.subschema_for::()?.into()), - extensions, - ..Default::default() - }.into()) - } - } - )+ - } -} - -array_impls! { - 1 2 3 4 5 6 7 8 9 10 - 11 12 13 14 15 16 17 18 19 20 - 21 22 23 24 25 26 27 28 29 30 - 31 32 -} - -////////// TUPLES ////////// - -macro_rules! tuple_impls { - ($($len:expr => ($($name:ident)+))+) => { - $( - impl<$($name: JsonSchema),+> JsonSchema for ($($name,)+) { - no_ref_schema!(); - - fn schema_name() -> String { - ["Tuple_Of".to_owned()$(, $name::schema_name())+].join("_And_") - } - - fn json_schema(gen: &mut SchemaGenerator) -> Result { - let mut extensions = Map::new(); - extensions.insert("minItems".to_owned(), json!($len)); - extensions.insert("maxItems".to_owned(), json!($len)); - let items = vec![ - $(gen.subschema_for::<$name>()?),+ - ]; - Ok(SchemaObject { - instance_type: Some(InstanceType::Array.into()), - items: Some(items.into()), - extensions, - ..Default::default() - }.into()) - } - } - )+ - } -} - -tuple_impls! { - 1 => (T0) - 2 => (T0 T1) - 3 => (T0 T1 T2) - 4 => (T0 T1 T2 T3) - 5 => (T0 T1 T2 T3 T4) - 6 => (T0 T1 T2 T3 T4 T5) - 7 => (T0 T1 T2 T3 T4 T5 T6) - 8 => (T0 T1 T2 T3 T4 T5 T6 T7) - 9 => (T0 T1 T2 T3 T4 T5 T6 T7 T8) - 10 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9) - 11 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10) - 12 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11) - 13 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12) - 14 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13) - 15 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14) - 16 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15) -} - -////////// SEQUENCES ///////// - -macro_rules! seq_impl { - ($($desc:tt)+) => { - impl $($desc)+ - where - T: JsonSchema, - { - no_ref_schema!(); - - fn schema_name() -> String { - format!("Array_Of_{}", T::schema_name()) - } - - fn json_schema(gen: &mut SchemaGenerator) -> Result { - Ok(SchemaObject { - instance_type: Some(InstanceType::Array.into()), - items: Some(gen.subschema_for::()?.into()), - ..Default::default() - }.into()) - } - } - }; -} - -seq_impl!( JsonSchema for std::collections::BinaryHeap); -seq_impl!( JsonSchema for std::collections::BTreeSet); -seq_impl!( JsonSchema for std::collections::HashSet); -seq_impl!( JsonSchema for std::collections::LinkedList); -seq_impl!( JsonSchema for Vec); -seq_impl!( JsonSchema for std::collections::VecDeque); - -////////// MAPS ///////// - -macro_rules! map_impl { - ($($desc:tt)+) => { - impl $($desc)+ - where - K: Into, - V: JsonSchema, - { - no_ref_schema!(); - - fn schema_name() -> String { - format!("Map_Of_{}", V::schema_name()) - } - - fn json_schema(gen: &mut SchemaGenerator) -> Result { - let subschema = gen.subschema_for::()?; - let json_schema_bool = gen.settings().bool_schemas == BoolSchemas::AdditionalPropertiesOnly - && subschema == gen.schema_for_any(); - let mut extensions = Map::new(); - extensions.insert( - "additionalProperties".to_owned(), - if json_schema_bool { - json!(true) - } else { - json!(subschema) - } - ); - Ok(SchemaObject { - instance_type: Some(InstanceType::Object.into()), - extensions, - ..Default::default() - }.into()) - } - } - }; -} - -map_impl!( JsonSchema for std::collections::BTreeMap); -map_impl!( JsonSchema for std::collections::HashMap); - -////////// OPTION ////////// - -// TODO should a field with a default set also be considered nullable? - -impl JsonSchema for Option { - no_ref_schema!(); - - fn schema_name() -> String { - format!("Nullable_{}", T::schema_name()) - } - - fn json_schema(gen: &mut SchemaGenerator) -> Result { - let mut schema = if gen.settings().option_nullable { - T::json_schema(gen)? - } else { - gen.subschema_for::()? - }; - if gen.settings().option_add_null_type { - schema = match schema { - Schema::Bool(true) => Schema::Bool(true), - Schema::Bool(false) => <()>::json_schema(gen)?, - schema => SchemaObject { - any_of: Some(vec![schema, <()>::json_schema(gen)?]), - ..Default::default() - } - .into(), - } - } - if gen.settings().option_nullable { - let mut deref = gen.get_schema_object(&schema)?; - deref.extensions.insert("nullable".to_owned(), json!(true)); - schema = Schema::Object(deref); - }; - Ok(schema) - } -} - -impl JsonSchema for std::marker::PhantomData { - no_ref_schema!(); - - fn schema_name() -> String { - <()>::schema_name() - } - - fn json_schema(gen: &mut SchemaGenerator) -> Result { - <()>::json_schema(gen) - } -} - -////////// DEREF ////////// - -macro_rules! deref_impl { - ($($desc:tt)+) => { - impl $($desc)+ - where - T: ?Sized + JsonSchema, - { - fn is_referenceable() -> bool { - T::is_referenceable() - } - - fn schema_name() -> String { - T::schema_name() - } - - fn json_schema(gen: &mut SchemaGenerator) -> Result { - T::json_schema(gen) - } - } - }; -} - -deref_impl!(<'a, T> JsonSchema for &'a T); -deref_impl!(<'a, T> JsonSchema for &'a mut T); -deref_impl!( JsonSchema for Box); -deref_impl!( JsonSchema for std::rc::Rc); -deref_impl!( JsonSchema for std::sync::Arc); -deref_impl!(<'a, T: ToOwned> JsonSchema for std::borrow::Cow<'a, T>); - -////////// SERDE_JSON ////////// - -impl JsonSchema for serde_json::Value { - no_ref_schema!(); - - fn schema_name() -> String { - "Any_Value".to_owned() - } - - fn json_schema(gen: &mut SchemaGenerator) -> Result { - Ok(gen.schema_for_any()) - } -} diff --git a/schemars/src/json_schema_impls/array.rs b/schemars/src/json_schema_impls/array.rs new file mode 100644 index 0000000..8ea11cc --- /dev/null +++ b/schemars/src/json_schema_impls/array.rs @@ -0,0 +1,76 @@ +use crate::gen::SchemaGenerator; +use crate::schema::*; +use crate::{JsonSchema, Map, Result}; +use serde_json::json; + +// Does not require T: JsonSchema. +impl JsonSchema for [T; 0] { + no_ref_schema!(); + + fn schema_name() -> String { + "Empty_Array".to_owned() + } + + fn json_schema(_: &mut SchemaGenerator) -> Result { + let mut extensions = Map::new(); + extensions.insert("maxItems".to_owned(), json!(0)); + Ok(SchemaObject { + instance_type: Some(InstanceType::Array.into()), + extensions, + ..Default::default() + } + .into()) + } +} + +macro_rules! array_impls { + ($($len:tt)+) => { + $( + impl JsonSchema for [T; $len] { + no_ref_schema!(); + + fn schema_name() -> String { + format!("Array_Size_{}_Of_{}", $len, T::schema_name()) + } + + fn json_schema(gen: &mut SchemaGenerator) -> Result { + let mut extensions = Map::new(); + extensions.insert("minItems".to_owned(), json!($len)); + extensions.insert("maxItems".to_owned(), json!($len)); + Ok(SchemaObject { + instance_type: Some(InstanceType::Array.into()), + items: Some(gen.subschema_for::()?.into()), + extensions, + ..Default::default() + }.into()) + } + } + )+ + } +} + +array_impls! { + 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 + 31 32 +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{schema_for, schema_object_for}; + use pretty_assertions::assert_eq; + + #[test] + fn schema_for_array() { + let schema = schema_object_for::<[i32; 8]>(); + assert_eq!( + schema.instance_type, + Some(SingleOrVec::from(InstanceType::Array)) + ); + assert_eq!(schema.extensions.get("minItems"), Some(&json!(8))); + assert_eq!(schema.extensions.get("maxItems"), Some(&json!(8))); + assert_eq!(schema.items, Some(SingleOrVec::from(schema_for::()))); + } +} diff --git a/schemars/src/json_schema_impls/core.rs b/schemars/src/json_schema_impls/core.rs new file mode 100644 index 0000000..eb2e48e --- /dev/null +++ b/schemars/src/json_schema_impls/core.rs @@ -0,0 +1,49 @@ +use crate::gen::SchemaGenerator; +use crate::schema::*; +use crate::{JsonSchema, Result}; +use serde_json::json; + +impl JsonSchema for Option { + no_ref_schema!(); + + fn schema_name() -> String { + format!("Nullable_{}", T::schema_name()) + } + + fn json_schema(gen: &mut SchemaGenerator) -> Result { + let mut schema = if gen.settings().option_nullable { + T::json_schema(gen)? + } else { + gen.subschema_for::()? + }; + if gen.settings().option_add_null_type { + schema = match schema { + Schema::Bool(true) => Schema::Bool(true), + Schema::Bool(false) => <()>::json_schema(gen)?, + schema => SchemaObject { + any_of: Some(vec![schema, <()>::json_schema(gen)?]), + ..Default::default() + } + .into(), + } + } + if gen.settings().option_nullable { + let mut deref = gen.get_schema_object(&schema)?; + deref.extensions.insert("nullable".to_owned(), json!(true)); + schema = Schema::Object(deref); + }; + Ok(schema) + } +} + +impl JsonSchema for std::marker::PhantomData { + no_ref_schema!(); + + fn schema_name() -> String { + <()>::schema_name() + } + + fn json_schema(gen: &mut SchemaGenerator) -> Result { + <()>::json_schema(gen) + } +} diff --git a/schemars/src/json_schema_impls/deref.rs b/schemars/src/json_schema_impls/deref.rs new file mode 100644 index 0000000..fea8799 --- /dev/null +++ b/schemars/src/json_schema_impls/deref.rs @@ -0,0 +1,30 @@ +use crate::gen::SchemaGenerator; +use crate::{JsonSchema, Result}; + +macro_rules! deref_impl { + ($($desc:tt)+) => { + impl $($desc)+ + where + T: ?Sized + JsonSchema, + { + fn is_referenceable() -> bool { + T::is_referenceable() + } + + fn schema_name() -> String { + T::schema_name() + } + + fn json_schema(gen: &mut SchemaGenerator) -> Result { + T::json_schema(gen) + } + } + }; +} + +deref_impl!(<'a, T> JsonSchema for &'a T); +deref_impl!(<'a, T> JsonSchema for &'a mut T); +deref_impl!( JsonSchema for Box); +deref_impl!( JsonSchema for std::rc::Rc); +deref_impl!( JsonSchema for std::sync::Arc); +deref_impl!(<'a, T: ToOwned> JsonSchema for std::borrow::Cow<'a, T>); diff --git a/schemars/src/json_schema_impls/maps.rs b/schemars/src/json_schema_impls/maps.rs new file mode 100644 index 0000000..f1f376a --- /dev/null +++ b/schemars/src/json_schema_impls/maps.rs @@ -0,0 +1,43 @@ +use crate::gen::{BoolSchemas, SchemaGenerator}; +use crate::schema::*; +use crate::{JsonSchema, Map, Result}; +use serde_json::json; + +macro_rules! map_impl { + ($($desc:tt)+) => { + impl $($desc)+ + where + K: Into, + V: JsonSchema, + { + no_ref_schema!(); + + fn schema_name() -> String { + format!("Map_Of_{}", V::schema_name()) + } + + fn json_schema(gen: &mut SchemaGenerator) -> Result { + let subschema = gen.subschema_for::()?; + let json_schema_bool = gen.settings().bool_schemas == BoolSchemas::AdditionalPropertiesOnly + && subschema == gen.schema_for_any(); + let mut extensions = Map::new(); + extensions.insert( + "additionalProperties".to_owned(), + if json_schema_bool { + json!(true) + } else { + json!(subschema) + } + ); + Ok(SchemaObject { + instance_type: Some(InstanceType::Object.into()), + extensions, + ..Default::default() + }.into()) + } + } + }; +} + +map_impl!( JsonSchema for std::collections::BTreeMap); +map_impl!( JsonSchema for std::collections::HashMap); diff --git a/schemars/src/json_schema_impls/mod.rs b/schemars/src/json_schema_impls/mod.rs new file mode 100644 index 0000000..af5ba60 --- /dev/null +++ b/schemars/src/json_schema_impls/mod.rs @@ -0,0 +1,25 @@ +macro_rules! no_ref_schema { + () => { + fn is_referenceable() -> bool { + false + } + }; +} + +mod array; +mod core; +mod deref; +mod maps; +mod primitives; +mod sequences; +mod serdejson; +mod tuple; + +// TODO chrono types under feature flag +// TODO serde yaml value/map under feature flag +// https://github.com/serde-rs/serde/blob/ce75418e40a593fc5c0902cbf4a45305a4178dd7/serde/src/ser/impls.rs +// Cell, RefCell, Mutex, RwLock, Result?, Duration, SystemTime, +// IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6, SocketAddrV6, +// Path, PathBuf, OsStr, OsString, Wrapping, Reverse, AtomicBool, AtomixI8 etc., +// NonZeroU8 etc., ArcWeak, RcWeak, (!)?, Bound?, Range?, RangeInclusive?, +// CString?, CStr?, fmt::Arguments? diff --git a/schemars/src/json_schema_impls/primitives.rs b/schemars/src/json_schema_impls/primitives.rs new file mode 100644 index 0000000..7f5457d --- /dev/null +++ b/schemars/src/json_schema_impls/primitives.rs @@ -0,0 +1,63 @@ +use crate::gen::SchemaGenerator; +use crate::schema::*; +use crate::{JsonSchema, Map, Result}; +use serde_json::json; + +macro_rules! simple_impl { + ($type:tt => $instance_type:ident) => { + impl JsonSchema for $type { + no_ref_schema!(); + + fn schema_name() -> String { + stringify!($instance_type).to_owned() + } + + fn json_schema(_: &mut SchemaGenerator) -> Result { + Ok(SchemaObject { + instance_type: Some(InstanceType::$instance_type.into()), + ..Default::default() + } + .into()) + } + } + }; +} + +simple_impl!(str => String); +simple_impl!(String => String); +simple_impl!(bool => Boolean); +simple_impl!(f32 => Number); +simple_impl!(f64 => Number); +simple_impl!(i8 => Integer); +simple_impl!(i16 => Integer); +simple_impl!(i32 => Integer); +simple_impl!(i64 => Integer); +simple_impl!(i128 => Integer); +simple_impl!(isize => Integer); +simple_impl!(u8 => Integer); +simple_impl!(u16 => Integer); +simple_impl!(u32 => Integer); +simple_impl!(u64 => Integer); +simple_impl!(u128 => Integer); +simple_impl!(usize => Integer); +simple_impl!(() => Null); + +impl JsonSchema for char { + no_ref_schema!(); + + fn schema_name() -> String { + "Character".to_owned() + } + + fn json_schema(_: &mut SchemaGenerator) -> Result { + let mut extensions = Map::new(); + extensions.insert("minLength".to_owned(), json!(1)); + extensions.insert("maxLength".to_owned(), json!(1)); + Ok(SchemaObject { + instance_type: Some(InstanceType::String.into()), + extensions, + ..Default::default() + } + .into()) + } +} diff --git a/schemars/src/json_schema_impls/sequences.rs b/schemars/src/json_schema_impls/sequences.rs new file mode 100644 index 0000000..b5d493f --- /dev/null +++ b/schemars/src/json_schema_impls/sequences.rs @@ -0,0 +1,33 @@ +use crate::gen::SchemaGenerator; +use crate::schema::*; +use crate::{JsonSchema, Result}; + +macro_rules! seq_impl { + ($($desc:tt)+) => { + impl $($desc)+ + where + T: JsonSchema, + { + no_ref_schema!(); + + fn schema_name() -> String { + format!("Array_Of_{}", T::schema_name()) + } + + fn json_schema(gen: &mut SchemaGenerator) -> Result { + Ok(SchemaObject { + instance_type: Some(InstanceType::Array.into()), + items: Some(gen.subschema_for::()?.into()), + ..Default::default() + }.into()) + } + } + }; +} + +seq_impl!( JsonSchema for std::collections::BinaryHeap); +seq_impl!( JsonSchema for std::collections::BTreeSet); +seq_impl!( JsonSchema for std::collections::HashSet); +seq_impl!( JsonSchema for std::collections::LinkedList); +seq_impl!( JsonSchema for Vec); +seq_impl!( JsonSchema for std::collections::VecDeque); diff --git a/schemars/src/json_schema_impls/serdejson.rs b/schemars/src/json_schema_impls/serdejson.rs new file mode 100644 index 0000000..9fcce37 --- /dev/null +++ b/schemars/src/json_schema_impls/serdejson.rs @@ -0,0 +1,45 @@ +use crate::gen::SchemaGenerator; +use crate::schema::*; +use crate::{JsonSchema, Result}; +use serde_json::{Map, Number, Value}; +use std::collections::BTreeMap; + +impl JsonSchema for Value { + no_ref_schema!(); + + fn schema_name() -> String { + "Any_Value".to_owned() + } + + fn json_schema(gen: &mut SchemaGenerator) -> Result { + Ok(gen.schema_for_any()) + } +} + +impl JsonSchema for Map { + no_ref_schema!(); + + fn schema_name() -> String { + BTreeMap::::schema_name() + } + + fn json_schema(gen: &mut SchemaGenerator) -> Result { + BTreeMap::::json_schema(gen) + } +} + +impl JsonSchema for Number { + no_ref_schema!(); + + fn schema_name() -> String { + "Number".to_owned() + } + + fn json_schema(_: &mut SchemaGenerator) -> Result { + Ok(SchemaObject { + instance_type: Some(InstanceType::Number.into()), + ..Default::default() + } + .into()) + } +} diff --git a/schemars/src/json_schema_impls/tuple.rs b/schemars/src/json_schema_impls/tuple.rs new file mode 100644 index 0000000..a5cd969 --- /dev/null +++ b/schemars/src/json_schema_impls/tuple.rs @@ -0,0 +1,52 @@ +use crate::gen::SchemaGenerator; +use crate::schema::*; +use crate::{JsonSchema, Map, Result}; +use serde_json::json; + +macro_rules! tuple_impls { + ($($len:expr => ($($name:ident)+))+) => { + $( + impl<$($name: JsonSchema),+> JsonSchema for ($($name,)+) { + no_ref_schema!(); + + fn schema_name() -> String { + ["Tuple_Of".to_owned()$(, $name::schema_name())+].join("_And_") + } + + fn json_schema(gen: &mut SchemaGenerator) -> Result { + let mut extensions = Map::new(); + extensions.insert("minItems".to_owned(), json!($len)); + extensions.insert("maxItems".to_owned(), json!($len)); + let items = vec![ + $(gen.subschema_for::<$name>()?),+ + ]; + Ok(SchemaObject { + instance_type: Some(InstanceType::Array.into()), + items: Some(items.into()), + extensions, + ..Default::default() + }.into()) + } + } + )+ + } +} + +tuple_impls! { + 1 => (T0) + 2 => (T0 T1) + 3 => (T0 T1 T2) + 4 => (T0 T1 T2 T3) + 5 => (T0 T1 T2 T3 T4) + 6 => (T0 T1 T2 T3 T4 T5) + 7 => (T0 T1 T2 T3 T4 T5 T6) + 8 => (T0 T1 T2 T3 T4 T5 T6 T7) + 9 => (T0 T1 T2 T3 T4 T5 T6 T7 T8) + 10 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9) + 11 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10) + 12 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11) + 13 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12) + 14 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13) + 15 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14) + 16 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15) +} diff --git a/schemars/src/lib.rs b/schemars/src/lib.rs index 99987f5..06b166c 100644 --- a/schemars/src/lib.rs +++ b/schemars/src/lib.rs @@ -23,3 +23,26 @@ pub trait JsonSchema { fn json_schema(gen: &mut gen::SchemaGenerator) -> Result; } + +#[cfg(test)] +pub mod tests { + use super::*; + + pub fn schema_for() -> schema::Schema { + match T::json_schema(&mut gen::SchemaGenerator::default()) { + Ok(s) => s, + Err(e) => panic!( + "Couldn't generate schema object for {}: {}", + T::schema_name(), + e + ), + } + } + + pub fn schema_object_for() -> schema::SchemaObject { + match schema_for::() { + schema::Schema::Object(o) => o, + s => panic!("Schema for {} was not an object: {:?}", T::schema_name(), s), + } + } +}