mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-04-11 10:37:51 +00:00
redo and test openapi type implementations
This commit is contained in:
parent
2a35e044db
commit
eecd192458
4 changed files with 413 additions and 291 deletions
|
@ -17,6 +17,10 @@ openapi_type_derive = "0.1.0-dev"
|
|||
openapiv3 = "=0.3.2"
|
||||
serde_json = "1.0"
|
||||
|
||||
# optional dependencies / features
|
||||
chrono = { version = "0.4.19", optional = true }
|
||||
uuid = { version = "0.8.2" , optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
paste = "1.0"
|
||||
serde = "1.0"
|
||||
|
|
|
@ -1,321 +1,224 @@
|
|||
use crate::{OpenapiSchema, OpenapiType};
|
||||
use indexmap::IndexMap;
|
||||
#[cfg(feature = "chrono")]
|
||||
use chrono::{offset::TimeZone, Date, DateTime, NaiveDate, NaiveDateTime};
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use openapiv3::{
|
||||
AdditionalProperties, ArrayType, IntegerType, NumberFormat, NumberType, ObjectType, ReferenceOr, SchemaKind, StringType,
|
||||
Type, VariantOrUnknownOrEmpty
|
||||
AdditionalProperties, ArrayType, IntegerType, NumberFormat, NumberType, ObjectType, ReferenceOr, SchemaKind,
|
||||
StringFormat, StringType, Type, VariantOrUnknownOrEmpty
|
||||
};
|
||||
use serde_json::Value;
|
||||
use std::{
|
||||
collections::{BTreeSet, HashMap, HashSet},
|
||||
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
|
||||
hash::BuildHasher,
|
||||
num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}
|
||||
};
|
||||
#[cfg(feature = "uuid")]
|
||||
use uuid::Uuid;
|
||||
|
||||
impl OpenapiType for () {
|
||||
fn schema() -> OpenapiSchema {
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Object(ObjectType {
|
||||
additional_properties: Some(AdditionalProperties::Any(false)),
|
||||
..Default::default()
|
||||
})))
|
||||
macro_rules! impl_openapi_type {
|
||||
($($ty:ident $(<$($generic:ident : $bound:path),+>)*),* => $schema:expr) => {
|
||||
$(
|
||||
impl $(<$($generic : $bound),+>)* OpenapiType for $ty $(<$($generic),+>)* {
|
||||
fn schema() -> OpenapiSchema {
|
||||
$schema
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
type Unit = ();
|
||||
impl_openapi_type!(Unit => {
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Object(ObjectType {
|
||||
additional_properties: Some(AdditionalProperties::Any(false)),
|
||||
..Default::default()
|
||||
})))
|
||||
});
|
||||
|
||||
impl_openapi_type!(Value => {
|
||||
OpenapiSchema {
|
||||
nullable: true,
|
||||
name: None,
|
||||
schema: SchemaKind::Any(Default::default()),
|
||||
dependencies: Default::default()
|
||||
}
|
||||
});
|
||||
|
||||
impl_openapi_type!(bool => OpenapiSchema::new(SchemaKind::Type(Type::Boolean {})));
|
||||
|
||||
#[inline]
|
||||
fn int_schema(minimum: Option<i64>, bits: Option<i64>) -> OpenapiSchema {
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Integer(IntegerType {
|
||||
minimum,
|
||||
format: bits
|
||||
.map(|bits| VariantOrUnknownOrEmpty::Unknown(format!("int{}", bits)))
|
||||
.unwrap_or(VariantOrUnknownOrEmpty::Empty),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
|
||||
impl OpenapiType for bool {
|
||||
fn schema() -> OpenapiSchema {
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Boolean {}))
|
||||
}
|
||||
impl_openapi_type!(isize => int_schema(None, None));
|
||||
impl_openapi_type!(i8 => int_schema(None, Some(8)));
|
||||
impl_openapi_type!(i16 => int_schema(None, Some(16)));
|
||||
impl_openapi_type!(i32 => int_schema(None, Some(32)));
|
||||
impl_openapi_type!(i64 => int_schema(None, Some(64)));
|
||||
impl_openapi_type!(i128 => int_schema(None, Some(128)));
|
||||
|
||||
impl_openapi_type!(usize => int_schema(Some(0), None));
|
||||
impl_openapi_type!(u8 => int_schema(Some(0), Some(8)));
|
||||
impl_openapi_type!(u16 => int_schema(Some(0), Some(16)));
|
||||
impl_openapi_type!(u32 => int_schema(Some(0), Some(32)));
|
||||
impl_openapi_type!(u64 => int_schema(Some(0), Some(64)));
|
||||
impl_openapi_type!(u128 => int_schema(Some(0), Some(128)));
|
||||
|
||||
impl_openapi_type!(NonZeroUsize => int_schema(Some(1), None));
|
||||
impl_openapi_type!(NonZeroU8 => int_schema(Some(1), Some(8)));
|
||||
impl_openapi_type!(NonZeroU16 => int_schema(Some(1), Some(16)));
|
||||
impl_openapi_type!(NonZeroU32 => int_schema(Some(1), Some(32)));
|
||||
impl_openapi_type!(NonZeroU64 => int_schema(Some(1), Some(64)));
|
||||
impl_openapi_type!(NonZeroU128 => int_schema(Some(1), Some(128)));
|
||||
|
||||
#[inline]
|
||||
fn float_schema(format: NumberFormat) -> OpenapiSchema {
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Number(NumberType {
|
||||
format: VariantOrUnknownOrEmpty::Item(format),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
|
||||
macro_rules! int_types {
|
||||
($($int_ty:ty),*) => {$(
|
||||
impl OpenapiType for $int_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Integer(IntegerType::default())))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
impl_openapi_type!(f32 => float_schema(NumberFormat::Float));
|
||||
impl_openapi_type!(f64 => float_schema(NumberFormat::Double));
|
||||
|
||||
(unsigned $($int_ty:ty),*) => {$(
|
||||
impl OpenapiType for $int_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Integer(IntegerType {
|
||||
minimum: Some(0),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
||||
(gtzero $($int_ty:ty),*) => {$(
|
||||
impl OpenapiType for $int_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Integer(IntegerType {
|
||||
minimum: Some(1),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
||||
(bits = $bits:expr, $($int_ty:ty),*) => {$(
|
||||
impl OpenapiType for $int_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Integer(IntegerType {
|
||||
format: VariantOrUnknownOrEmpty::Unknown(format!("int{}", $bits)),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
||||
(unsigned bits = $bits:expr, $($int_ty:ty),*) => {$(
|
||||
impl OpenapiType for $int_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Integer(IntegerType {
|
||||
format: VariantOrUnknownOrEmpty::Unknown(format!("int{}", $bits)),
|
||||
minimum: Some(0),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
||||
(gtzero bits = $bits:expr, $($int_ty:ty),*) => {$(
|
||||
impl OpenapiType for $int_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Integer(IntegerType {
|
||||
format: VariantOrUnknownOrEmpty::Unknown(format!("int{}", $bits)),
|
||||
minimum: Some(1),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
#[inline]
|
||||
fn str_schema(format: VariantOrUnknownOrEmpty<StringFormat>) -> OpenapiSchema {
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType {
|
||||
format,
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
|
||||
int_types!(isize);
|
||||
int_types!(unsigned usize);
|
||||
int_types!(gtzero NonZeroUsize);
|
||||
int_types!(bits = 8, i8);
|
||||
int_types!(unsigned bits = 8, u8);
|
||||
int_types!(gtzero bits = 8, NonZeroU8);
|
||||
int_types!(bits = 16, i16);
|
||||
int_types!(unsigned bits = 16, u16);
|
||||
int_types!(gtzero bits = 16, NonZeroU16);
|
||||
int_types!(bits = 32, i32);
|
||||
int_types!(unsigned bits = 32, u32);
|
||||
int_types!(gtzero bits = 32, NonZeroU32);
|
||||
int_types!(bits = 64, i64);
|
||||
int_types!(unsigned bits = 64, u64);
|
||||
int_types!(gtzero bits = 64, NonZeroU64);
|
||||
int_types!(bits = 128, i128);
|
||||
int_types!(unsigned bits = 128, u128);
|
||||
int_types!(gtzero bits = 128, NonZeroU128);
|
||||
|
||||
macro_rules! num_types {
|
||||
($($num_ty:ty = $num_fmt:ident),*) => {$(
|
||||
impl OpenapiType for $num_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Number(NumberType {
|
||||
format: VariantOrUnknownOrEmpty::Item(NumberFormat::$num_fmt),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
num_types!(f32 = Float, f64 = Double);
|
||||
|
||||
macro_rules! str_types {
|
||||
($($str_ty:ty),*) => {$(
|
||||
impl OpenapiType for $str_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType::default())))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
||||
(format = $format:ident, $($str_ty:ty),*) => {$(
|
||||
impl OpenapiType for $str_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
use openapiv3::StringFormat;
|
||||
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType {
|
||||
format: VariantOrUnknownOrEmpty::Item(StringFormat::$format),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
||||
(format_str = $format:expr, $($str_ty:ty),*) => {$(
|
||||
impl OpenapiType for $str_ty
|
||||
{
|
||||
fn schema() -> OpenapiSchema
|
||||
{
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType {
|
||||
format: VariantOrUnknownOrEmpty::Unknown($format.to_string()),
|
||||
..Default::default()
|
||||
})))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
}
|
||||
|
||||
str_types!(String, &str);
|
||||
impl_openapi_type!(String => str_schema(VariantOrUnknownOrEmpty::Empty));
|
||||
|
||||
#[cfg(feature = "chrono")]
|
||||
str_types!(format = Date, Date<FixedOffset>, Date<Local>, Date<Utc>, NaiveDate);
|
||||
impl_openapi_type!(Date<T: TimeZone>, NaiveDate => {
|
||||
str_schema(VariantOrUnknownOrEmpty::Item(StringFormat::Date))
|
||||
});
|
||||
|
||||
#[cfg(feature = "chrono")]
|
||||
str_types!(
|
||||
format = DateTime,
|
||||
DateTime<FixedOffset>,
|
||||
DateTime<Local>,
|
||||
DateTime<Utc>,
|
||||
NaiveDateTime
|
||||
);
|
||||
impl_openapi_type!(DateTime<T: TimeZone>, NaiveDateTime => {
|
||||
str_schema(VariantOrUnknownOrEmpty::Item(StringFormat::DateTime))
|
||||
});
|
||||
|
||||
#[cfg(feature = "uuid")]
|
||||
str_types!(format_str = "uuid", Uuid);
|
||||
impl_openapi_type!(Uuid => {
|
||||
str_schema(VariantOrUnknownOrEmpty::Unknown("uuid".to_owned()))
|
||||
});
|
||||
|
||||
impl<T: OpenapiType> OpenapiType for Option<T> {
|
||||
fn schema() -> OpenapiSchema {
|
||||
let schema = T::schema();
|
||||
let mut dependencies = schema.dependencies.clone();
|
||||
let schema = match schema.name.clone() {
|
||||
Some(name) => {
|
||||
let reference = ReferenceOr::Reference {
|
||||
reference: format!("#/components/schemas/{}", name)
|
||||
};
|
||||
dependencies.insert(name, schema);
|
||||
SchemaKind::AllOf { all_of: vec![reference] }
|
||||
},
|
||||
None => schema.schema
|
||||
};
|
||||
impl_openapi_type!(Option<T: OpenapiType> => {
|
||||
let schema = T::schema();
|
||||
let mut dependencies = schema.dependencies.clone();
|
||||
let schema = match schema.name.clone() {
|
||||
Some(name) => {
|
||||
let reference = ReferenceOr::Reference {
|
||||
reference: format!("#/components/schemas/{}", name)
|
||||
};
|
||||
dependencies.insert(name, schema);
|
||||
SchemaKind::AllOf { all_of: vec![reference] }
|
||||
},
|
||||
None => schema.schema
|
||||
};
|
||||
|
||||
OpenapiSchema {
|
||||
nullable: true,
|
||||
name: None,
|
||||
schema,
|
||||
dependencies
|
||||
}
|
||||
OpenapiSchema {
|
||||
nullable: true,
|
||||
name: None,
|
||||
schema,
|
||||
dependencies
|
||||
}
|
||||
});
|
||||
|
||||
#[inline]
|
||||
fn array_schema<T: OpenapiType>(unique_items: bool) -> OpenapiSchema {
|
||||
let schema = T::schema();
|
||||
let mut dependencies = schema.dependencies.clone();
|
||||
|
||||
let items = match schema.name.clone() {
|
||||
Some(name) => {
|
||||
let reference = ReferenceOr::Reference {
|
||||
reference: format!("#/components/schemas/{}", name)
|
||||
};
|
||||
dependencies.insert(name, schema);
|
||||
reference
|
||||
},
|
||||
None => ReferenceOr::Item(Box::new(schema.into_schema()))
|
||||
};
|
||||
|
||||
OpenapiSchema {
|
||||
nullable: false,
|
||||
name: None,
|
||||
schema: SchemaKind::Type(Type::Array(ArrayType {
|
||||
items,
|
||||
min_items: None,
|
||||
max_items: None,
|
||||
unique_items
|
||||
})),
|
||||
dependencies
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: OpenapiType> OpenapiType for Vec<T> {
|
||||
fn schema() -> OpenapiSchema {
|
||||
let schema = T::schema();
|
||||
let mut dependencies = schema.dependencies.clone();
|
||||
impl_openapi_type!(Vec<T: OpenapiType> => array_schema::<T>(false));
|
||||
impl_openapi_type!(BTreeSet<T: OpenapiType>, IndexSet<T: OpenapiType>, HashSet<T: OpenapiType, S: BuildHasher> => {
|
||||
array_schema::<T>(true)
|
||||
});
|
||||
|
||||
let items = match schema.name.clone() {
|
||||
Some(name) => {
|
||||
let reference = ReferenceOr::Reference {
|
||||
reference: format!("#/components/schemas/{}", name)
|
||||
};
|
||||
dependencies.insert(name, schema);
|
||||
reference
|
||||
},
|
||||
None => ReferenceOr::Item(Box::new(schema.into_schema()))
|
||||
};
|
||||
#[inline]
|
||||
fn map_schema<K: OpenapiType, T: OpenapiType>() -> OpenapiSchema {
|
||||
let key_schema = K::schema();
|
||||
let mut dependencies = key_schema.dependencies.clone();
|
||||
|
||||
OpenapiSchema {
|
||||
nullable: false,
|
||||
name: None,
|
||||
schema: SchemaKind::Type(Type::Array(ArrayType {
|
||||
items,
|
||||
min_items: None,
|
||||
max_items: None,
|
||||
unique_items: false
|
||||
})),
|
||||
dependencies
|
||||
}
|
||||
let keys = match key_schema.name.clone() {
|
||||
Some(name) => {
|
||||
let reference = ReferenceOr::Reference {
|
||||
reference: format!("#/components/schemas/{}", name)
|
||||
};
|
||||
dependencies.insert(name, key_schema);
|
||||
reference
|
||||
},
|
||||
None => ReferenceOr::Item(Box::new(key_schema.into_schema()))
|
||||
};
|
||||
|
||||
let schema = T::schema();
|
||||
dependencies.extend(schema.dependencies.iter().map(|(k, v)| (k.clone(), v.clone())));
|
||||
|
||||
let items = Box::new(match schema.name.clone() {
|
||||
Some(name) => {
|
||||
let reference = ReferenceOr::Reference {
|
||||
reference: format!("#/components/schemas/{}", name)
|
||||
};
|
||||
dependencies.insert(name, schema);
|
||||
reference
|
||||
},
|
||||
None => ReferenceOr::Item(schema.into_schema())
|
||||
});
|
||||
|
||||
let mut properties = IndexMap::new();
|
||||
properties.insert("default".to_owned(), keys);
|
||||
|
||||
OpenapiSchema {
|
||||
nullable: false,
|
||||
name: None,
|
||||
schema: SchemaKind::Type(Type::Object(ObjectType {
|
||||
properties,
|
||||
required: vec!["default".to_owned()],
|
||||
additional_properties: Some(AdditionalProperties::Schema(items)),
|
||||
..Default::default()
|
||||
})),
|
||||
dependencies
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: OpenapiType> OpenapiType for BTreeSet<T> {
|
||||
fn schema() -> OpenapiSchema {
|
||||
<Vec<T> as OpenapiType>::schema()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: OpenapiType, S: BuildHasher> OpenapiType for HashSet<T, S> {
|
||||
fn schema() -> OpenapiSchema {
|
||||
<Vec<T> as OpenapiType>::schema()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: OpenapiType, T: OpenapiType, S: BuildHasher> OpenapiType for HashMap<K, T, S> {
|
||||
fn schema() -> OpenapiSchema {
|
||||
let key_schema = K::schema();
|
||||
let mut dependencies = key_schema.dependencies.clone();
|
||||
|
||||
let keys = match key_schema.name.clone() {
|
||||
Some(name) => {
|
||||
let reference = ReferenceOr::Reference {
|
||||
reference: format!("#/components/schemas/{}", name)
|
||||
};
|
||||
dependencies.insert(name, key_schema);
|
||||
reference
|
||||
},
|
||||
None => ReferenceOr::Item(Box::new(key_schema.into_schema()))
|
||||
};
|
||||
|
||||
let schema = T::schema();
|
||||
dependencies.extend(schema.dependencies.iter().map(|(k, v)| (k.clone(), v.clone())));
|
||||
|
||||
let items = Box::new(match schema.name.clone() {
|
||||
Some(name) => {
|
||||
let reference = ReferenceOr::Reference {
|
||||
reference: format!("#/components/schemas/{}", name)
|
||||
};
|
||||
dependencies.insert(name, schema);
|
||||
reference
|
||||
},
|
||||
None => ReferenceOr::Item(schema.into_schema())
|
||||
});
|
||||
|
||||
let mut properties = IndexMap::new();
|
||||
properties.insert("default".to_owned(), keys);
|
||||
|
||||
OpenapiSchema {
|
||||
nullable: false,
|
||||
name: None,
|
||||
schema: SchemaKind::Type(Type::Object(ObjectType {
|
||||
properties,
|
||||
required: vec!["default".to_owned()],
|
||||
additional_properties: Some(AdditionalProperties::Schema(items)),
|
||||
..Default::default()
|
||||
})),
|
||||
dependencies
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenapiType for serde_json::Value {
|
||||
fn schema() -> OpenapiSchema {
|
||||
OpenapiSchema {
|
||||
nullable: true,
|
||||
name: None,
|
||||
schema: SchemaKind::Any(Default::default()),
|
||||
dependencies: Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
impl_openapi_type!(
|
||||
BTreeMap<K: OpenapiType, T: OpenapiType>,
|
||||
IndexMap<K: OpenapiType, T: OpenapiType>,
|
||||
HashMap<K: OpenapiType, T: OpenapiType, S: BuildHasher>
|
||||
=> map_schema::<K, T>()
|
||||
);
|
||||
|
|
216
openapi_type/tests/std_types.rs
Normal file
216
openapi_type/tests/std_types.rs
Normal file
|
@ -0,0 +1,216 @@
|
|||
#[cfg(feature = "chrono")]
|
||||
use chrono::{Date, DateTime, FixedOffset, Local, NaiveDate, NaiveDateTime, Utc};
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use openapi_type::OpenapiType;
|
||||
use serde_json::Value;
|
||||
use std::{
|
||||
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
|
||||
num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}
|
||||
};
|
||||
#[cfg(feature = "uuid")]
|
||||
use uuid::Uuid;
|
||||
|
||||
macro_rules! test_type {
|
||||
($($ty:ident $(<$($generic:ident),+>)*),* = $json:tt) => {
|
||||
paste::paste! { $(
|
||||
#[test]
|
||||
fn [< $ty:lower $($(_ $generic:lower)+)* >]() {
|
||||
let schema = <$ty $(<$($generic),+>)* as OpenapiType>::schema();
|
||||
let schema = openapi_type::OpenapiSchema::into_schema(schema);
|
||||
let schema_json = serde_json::to_value(&schema).unwrap();
|
||||
let expected = serde_json::json!($json);
|
||||
assert_eq!(schema_json, expected);
|
||||
}
|
||||
)* }
|
||||
};
|
||||
}
|
||||
|
||||
type Unit = ();
|
||||
test_type!(Unit = {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
});
|
||||
|
||||
test_type!(Value = {
|
||||
"nullable": true
|
||||
});
|
||||
|
||||
test_type!(bool = {
|
||||
"type": "boolean"
|
||||
});
|
||||
|
||||
// ### integer types
|
||||
|
||||
test_type!(isize = {
|
||||
"type": "integer"
|
||||
});
|
||||
|
||||
test_type!(usize = {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
});
|
||||
|
||||
test_type!(i8 = {
|
||||
"type": "integer",
|
||||
"format": "int8"
|
||||
});
|
||||
|
||||
test_type!(u8 = {
|
||||
"type": "integer",
|
||||
"format": "int8",
|
||||
"minimum": 0
|
||||
});
|
||||
|
||||
test_type!(i16 = {
|
||||
"type": "integer",
|
||||
"format": "int16"
|
||||
});
|
||||
|
||||
test_type!(u16 = {
|
||||
"type": "integer",
|
||||
"format": "int16",
|
||||
"minimum": 0
|
||||
});
|
||||
|
||||
test_type!(i32 = {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
});
|
||||
|
||||
test_type!(u32 = {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"minimum": 0
|
||||
});
|
||||
|
||||
test_type!(i64 = {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
});
|
||||
|
||||
test_type!(u64 = {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"minimum": 0
|
||||
});
|
||||
|
||||
test_type!(i128 = {
|
||||
"type": "integer",
|
||||
"format": "int128"
|
||||
});
|
||||
|
||||
test_type!(u128 = {
|
||||
"type": "integer",
|
||||
"format": "int128",
|
||||
"minimum": 0
|
||||
});
|
||||
|
||||
// ### non-zero integer types
|
||||
|
||||
test_type!(NonZeroUsize = {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
});
|
||||
|
||||
test_type!(NonZeroU8 = {
|
||||
"type": "integer",
|
||||
"format": "int8",
|
||||
"minimum": 1
|
||||
});
|
||||
|
||||
test_type!(NonZeroU16 = {
|
||||
"type": "integer",
|
||||
"format": "int16",
|
||||
"minimum": 1
|
||||
});
|
||||
|
||||
test_type!(NonZeroU32 = {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"minimum": 1
|
||||
});
|
||||
|
||||
test_type!(NonZeroU64 = {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"minimum": 1
|
||||
});
|
||||
|
||||
test_type!(NonZeroU128 = {
|
||||
"type": "integer",
|
||||
"format": "int128",
|
||||
"minimum": 1
|
||||
});
|
||||
|
||||
// ### floats
|
||||
|
||||
test_type!(f32 = {
|
||||
"type": "number",
|
||||
"format": "float"
|
||||
});
|
||||
|
||||
test_type!(f64 = {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
});
|
||||
|
||||
// ### string
|
||||
|
||||
test_type!(String = {
|
||||
"type": "string"
|
||||
});
|
||||
|
||||
#[cfg(feature = "uuid")]
|
||||
test_type!(Uuid = {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
});
|
||||
|
||||
// ### date/time
|
||||
|
||||
#[cfg(feature = "chrono")]
|
||||
test_type!(Date<FixedOffset>, Date<Local>, Date<Utc>, NaiveDate = {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
});
|
||||
|
||||
#[cfg(feature = "chrono")]
|
||||
test_type!(DateTime<FixedOffset>, DateTime<Local>, DateTime<Utc>, NaiveDateTime = {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
});
|
||||
|
||||
// ### some std types
|
||||
|
||||
test_type!(Option<String> = {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
});
|
||||
|
||||
test_type!(Vec<String> = {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
});
|
||||
|
||||
test_type!(BTreeSet<String>, IndexSet<String>, HashSet<String> = {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
});
|
||||
|
||||
test_type!(BTreeMap<isize, String>, IndexMap<isize, String>, HashMap<isize, String> = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"default": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": ["default"],
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
});
|
|
@ -7,7 +7,6 @@ use openapiv3::{
|
|||
ReferenceOr::{Item, Reference},
|
||||
Schema, SchemaData, SchemaKind, StringType, Type, VariantOrUnknownOrEmpty
|
||||
};
|
||||
|
||||
use std::{
|
||||
collections::{BTreeSet, HashMap, HashSet},
|
||||
hash::BuildHasher,
|
||||
|
|
Loading…
Add table
Reference in a new issue