#![doc = include_str!("../docs/lib.md")]
#![doc(html_favicon_url = "https://salvo.rs/favicon-32x32.png")]
#![doc(html_logo_url = "https://salvo.rs/images/logo.svg")]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(test, allow(clippy::unwrap_used))]
#[macro_use]
mod cfg;
mod openapi;
pub use openapi::*;
#[doc = include_str!("../docs/endpoint.md")]
pub mod endpoint;
pub use endpoint::{Endpoint, EndpointArgRegister, EndpointOutRegister, EndpointRegistry};
pub mod extract;
mod routing;
pub use routing::RouterExt;
pub mod naming;
cfg_feature! {
#![feature ="swagger-ui"]
pub mod swagger_ui;
}
cfg_feature! {
#![feature ="scalar"]
pub mod scalar;
}
cfg_feature! {
#![feature ="rapidoc"]
pub mod rapidoc;
}
cfg_feature! {
#![feature ="redoc"]
pub mod redoc;
}
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, LinkedList};
use std::marker::PhantomData;
use salvo_core::extract::Extractible;
use salvo_core::http::StatusError;
use salvo_core::writing;
#[doc = include_str!("../docs/derive_to_parameters.md")]
pub use salvo_oapi_macros::ToParameters;
#[doc = include_str!("../docs/derive_to_response.md")]
pub use salvo_oapi_macros::ToResponse;
#[doc = include_str!("../docs/derive_to_responses.md")]
pub use salvo_oapi_macros::ToResponses;
#[doc = include_str!("../docs/derive_to_schema.md")]
pub use salvo_oapi_macros::ToSchema;
#[doc = include_str!("../docs/endpoint.md")]
pub use salvo_oapi_macros::endpoint;
pub(crate) use salvo_oapi_macros::schema;
use crate::oapi::openapi::schema::OneOf;
extern crate self as salvo_oapi;
pub trait ToSchema {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema>;
}
pub trait ComposeSchema {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema>;
}
#[derive(Debug, Clone, Default)]
pub struct SchemaReference {
pub name: std::borrow::Cow<'static, str>,
pub inline: bool,
pub references: Vec<Self>,
}
impl SchemaReference {
pub fn new(name: impl Into<std::borrow::Cow<'static, str>>) -> Self {
Self {
name: name.into(),
inline: false,
references: Vec::new(),
}
}
#[must_use]
pub fn inline(mut self, inline: bool) -> Self {
self.inline = inline;
self
}
#[must_use]
pub fn reference(mut self, reference: Self) -> Self {
self.references.push(reference);
self
}
#[must_use]
pub fn compose_name(&self) -> String {
if self.references.is_empty() {
self.name.to_string()
} else {
let generic_names: Vec<String> =
self.references.iter().map(|r| r.compose_name()).collect();
format!("{}<{}>", self.name, generic_names.join(", "))
}
}
#[must_use]
pub fn compose_generics(&self) -> &[Self] {
&self.references
}
#[must_use]
pub fn compose_child_references(&self) -> Vec<&Self> {
let mut result = Vec::new();
for reference in &self.references {
result.push(reference);
result.extend(reference.compose_child_references());
}
result
}
}
pub type TupleUnit = ();
impl ToSchema for TupleUnit {
fn to_schema(_components: &mut Components) -> RefOr<schema::Schema> {
schema::empty().into()
}
}
impl ComposeSchema for TupleUnit {
fn compose(
_components: &mut Components,
_generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
schema::empty().into()
}
}
macro_rules! impl_to_schema {
($ty:path) => {
impl_to_schema!( @impl_schema $ty );
};
(&$ty:path) => {
impl_to_schema!( @impl_schema &$ty );
};
(@impl_schema $($tt:tt)*) => {
impl ToSchema for $($tt)* {
fn to_schema(_components: &mut Components) -> crate::RefOr<crate::schema::Schema> {
schema!( $($tt)* ).into()
}
}
impl ComposeSchema for $($tt)* {
fn compose(_components: &mut Components, _generics: Vec<crate::RefOr<crate::schema::Schema>>) -> crate::RefOr<crate::schema::Schema> {
schema!( $($tt)* ).into()
}
}
};
}
macro_rules! impl_to_schema_primitive {
($($tt:path),*) => {
$( impl_to_schema!( $tt ); )*
};
}
#[doc(hidden)]
pub mod oapi {
pub use super::*;
}
#[doc(hidden)]
pub mod __private {
pub use inventory;
pub use serde_json;
}
#[rustfmt::skip]
impl_to_schema_primitive!(
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, bool, f32, f64, String, str, char
);
impl_to_schema!(&str);
impl_to_schema!(std::net::Ipv4Addr);
impl_to_schema!(std::net::Ipv6Addr);
impl ToSchema for std::net::IpAddr {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
crate::RefOr::Type(Schema::OneOf(
OneOf::default()
.item(std::net::Ipv4Addr::to_schema(components))
.item(std::net::Ipv6Addr::to_schema(components)),
))
}
}
impl ComposeSchema for std::net::IpAddr {
fn compose(
components: &mut Components,
_generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
Self::to_schema(components)
}
}
#[cfg(feature = "chrono")]
impl_to_schema_primitive!(chrono::NaiveDate, chrono::Duration, chrono::NaiveDateTime);
#[cfg(feature = "chrono")]
impl<T: chrono::TimeZone> ToSchema for chrono::DateTime<T> {
fn to_schema(_components: &mut Components) -> RefOr<schema::Schema> {
schema!(#[inline] DateTime<T>).into()
}
}
#[cfg(feature = "chrono")]
impl<T: chrono::TimeZone> ComposeSchema for chrono::DateTime<T> {
fn compose(
_components: &mut Components,
_generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
schema!(#[inline] DateTime<T>).into()
}
}
#[cfg(feature = "compact_str")]
impl_to_schema_primitive!(compact_str::CompactString);
#[cfg(any(feature = "decimal", feature = "decimal-float"))]
impl_to_schema!(rust_decimal::Decimal);
#[cfg(feature = "url")]
impl_to_schema!(url::Url);
#[cfg(feature = "uuid")]
impl_to_schema!(uuid::Uuid);
#[cfg(feature = "ulid")]
impl_to_schema!(ulid::Ulid);
#[cfg(feature = "time")]
impl_to_schema_primitive!(
time::Date,
time::PrimitiveDateTime,
time::OffsetDateTime,
time::Duration
);
#[cfg(feature = "smallvec")]
impl<T: ToSchema + smallvec::Array> ToSchema for smallvec::SmallVec<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(#[inline] smallvec::SmallVec<T>).into()
}
}
#[cfg(feature = "smallvec")]
impl<T: ComposeSchema + smallvec::Array> ComposeSchema for smallvec::SmallVec<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::Array::new().items(t_schema).into()
}
}
#[cfg(feature = "indexmap")]
impl<K: ToSchema, V: ToSchema> ToSchema for indexmap::IndexMap<K, V> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(#[inline] indexmap::IndexMap<K, V>).into()
}
}
#[cfg(feature = "indexmap")]
impl<K: ComposeSchema, V: ComposeSchema> ComposeSchema for indexmap::IndexMap<K, V> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let v_schema = generics
.get(1)
.cloned()
.unwrap_or_else(|| V::compose(components, vec![]));
schema::Object::new().additional_properties(v_schema).into()
}
}
impl<T: ToSchema> ToSchema for Vec<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(#[inline] Vec<T>).into()
}
}
impl<T: ComposeSchema> ComposeSchema for Vec<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::Array::new().items(t_schema).into()
}
}
impl<T: ToSchema> ToSchema for LinkedList<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(#[inline] LinkedList<T>).into()
}
}
impl<T: ComposeSchema> ComposeSchema for LinkedList<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::Array::new().items(t_schema).into()
}
}
impl<T: ToSchema> ToSchema for HashSet<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema::Array::new()
.items(T::to_schema(components))
.unique_items(true)
.into()
}
}
impl<T: ComposeSchema> ComposeSchema for HashSet<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::Array::new()
.items(t_schema)
.unique_items(true)
.into()
}
}
impl<T: ToSchema> ToSchema for BTreeSet<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema::Array::new()
.items(T::to_schema(components))
.unique_items(true)
.into()
}
}
impl<T: ComposeSchema> ComposeSchema for BTreeSet<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::Array::new()
.items(t_schema)
.unique_items(true)
.into()
}
}
#[cfg(feature = "indexmap")]
impl<T: ToSchema> ToSchema for indexmap::IndexSet<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema::Array::new()
.items(T::to_schema(components))
.unique_items(true)
.into()
}
}
#[cfg(feature = "indexmap")]
impl<T: ComposeSchema> ComposeSchema for indexmap::IndexSet<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::Array::new()
.items(t_schema)
.unique_items(true)
.into()
}
}
impl<T: ToSchema> ToSchema for Box<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
T::to_schema(components)
}
}
impl<T: ComposeSchema> ComposeSchema for Box<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
T::compose(components, generics)
}
}
impl<T: ToSchema + ToOwned> ToSchema for std::borrow::Cow<'_, T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
T::to_schema(components)
}
}
impl<T: ComposeSchema + ToOwned> ComposeSchema for std::borrow::Cow<'_, T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
T::compose(components, generics)
}
}
impl<T: ToSchema> ToSchema for std::cell::RefCell<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
T::to_schema(components)
}
}
impl<T: ComposeSchema> ComposeSchema for std::cell::RefCell<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
T::compose(components, generics)
}
}
impl<T: ToSchema> ToSchema for std::rc::Rc<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
T::to_schema(components)
}
}
impl<T: ComposeSchema> ComposeSchema for std::rc::Rc<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
T::compose(components, generics)
}
}
impl<T: ToSchema> ToSchema for std::sync::Arc<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
T::to_schema(components)
}
}
impl<T: ComposeSchema> ComposeSchema for std::sync::Arc<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
T::compose(components, generics)
}
}
impl<T: ToSchema> ToSchema for [T] {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(
#[inline]
[T]
)
.into()
}
}
impl<T: ComposeSchema> ComposeSchema for [T] {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::Array::new().items(t_schema).into()
}
}
impl<T: ToSchema, const N: usize> ToSchema for [T; N] {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(
#[inline]
[T; N]
)
.into()
}
}
impl<T: ComposeSchema, const N: usize> ComposeSchema for [T; N] {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::Array::new().items(t_schema).into()
}
}
impl<T: ToSchema> ToSchema for &[T] {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(
#[inline]
&[T]
)
.into()
}
}
impl<T: ComposeSchema> ComposeSchema for &[T] {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::Array::new().items(t_schema).into()
}
}
impl<T: ToSchema> ToSchema for Option<T> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(#[inline] Option<T>).into()
}
}
impl<T: ComposeSchema> ComposeSchema for Option<T> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
schema::OneOf::new()
.item(t_schema)
.item(schema::Object::new().schema_type(schema::BasicType::Null))
.into()
}
}
impl<T> ToSchema for PhantomData<T> {
fn to_schema(_components: &mut Components) -> RefOr<schema::Schema> {
Schema::Object(Box::default()).into()
}
}
impl<T> ComposeSchema for PhantomData<T> {
fn compose(
_components: &mut Components,
_generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
Schema::Object(Box::default()).into()
}
}
impl<K: ToSchema, V: ToSchema> ToSchema for BTreeMap<K, V> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(#[inline]BTreeMap<K, V>).into()
}
}
impl<K: ComposeSchema, V: ComposeSchema> ComposeSchema for BTreeMap<K, V> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let v_schema = generics
.get(1)
.cloned()
.unwrap_or_else(|| V::compose(components, vec![]));
schema::Object::new().additional_properties(v_schema).into()
}
}
impl<K: ToSchema, V: ToSchema> ToSchema for HashMap<K, V> {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
schema!(#[inline]HashMap<K, V>).into()
}
}
impl<K: ComposeSchema, V: ComposeSchema> ComposeSchema for HashMap<K, V> {
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let v_schema = generics
.get(1)
.cloned()
.unwrap_or_else(|| V::compose(components, vec![]));
schema::Object::new().additional_properties(v_schema).into()
}
}
impl ToSchema for StatusError {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
let name = crate::naming::assign_name::<Self>(Default::default());
let ref_or = crate::RefOr::Ref(crate::Ref::new(format!("#/components/schemas/{name}")));
if !components.schemas.contains_key(&name) {
components.schemas.insert(name.clone(), ref_or.clone());
let schema = Schema::from(
Object::new()
.property("code", u16::to_schema(components))
.required("code")
.required("name")
.property("name", String::to_schema(components))
.required("brief")
.property("brief", String::to_schema(components))
.required("detail")
.property("detail", String::to_schema(components))
.property("cause", String::to_schema(components)),
);
components.schemas.insert(name, schema);
}
ref_or
}
}
impl ComposeSchema for StatusError {
fn compose(
components: &mut Components,
_generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
Self::to_schema(components)
}
}
impl ToSchema for salvo_core::Error {
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
StatusError::to_schema(components)
}
}
impl ComposeSchema for salvo_core::Error {
fn compose(
components: &mut Components,
_generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
Self::to_schema(components)
}
}
impl<T, E> ToSchema for Result<T, E>
where
T: ToSchema,
E: ToSchema,
{
fn to_schema(components: &mut Components) -> RefOr<schema::Schema> {
let name = crate::naming::assign_name::<StatusError>(Default::default());
let ref_or = crate::RefOr::Ref(crate::Ref::new(format!("#/components/schemas/{name}")));
if !components.schemas.contains_key(&name) {
components.schemas.insert(name.clone(), ref_or.clone());
let schema = OneOf::new()
.item(T::to_schema(components))
.item(E::to_schema(components));
components.schemas.insert(name, schema);
}
ref_or
}
}
impl<T, E> ComposeSchema for Result<T, E>
where
T: ComposeSchema,
E: ComposeSchema,
{
fn compose(
components: &mut Components,
generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
let t_schema = generics
.first()
.cloned()
.unwrap_or_else(|| T::compose(components, vec![]));
let e_schema = generics
.get(1)
.cloned()
.unwrap_or_else(|| E::compose(components, vec![]));
OneOf::new().item(t_schema).item(e_schema).into()
}
}
impl ToSchema for serde_json::Value {
fn to_schema(_components: &mut Components) -> RefOr<schema::Schema> {
Schema::Object(Box::default()).into()
}
}
impl ComposeSchema for serde_json::Value {
fn compose(
_components: &mut Components,
_generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
Schema::Object(Box::default()).into()
}
}
impl ToSchema for serde_json::Map<String, serde_json::Value> {
fn to_schema(_components: &mut Components) -> RefOr<schema::Schema> {
Schema::Object(Box::new(schema::Object::new())).into()
}
}
impl ComposeSchema for serde_json::Map<String, serde_json::Value> {
fn compose(
_components: &mut Components,
_generics: Vec<RefOr<schema::Schema>>,
) -> RefOr<schema::Schema> {
Schema::Object(Box::new(schema::Object::new())).into()
}
}
pub trait ToParameters<'de>: Extractible<'de> {
fn to_parameters(components: &mut Components) -> Parameters;
}
pub trait ToParameter {
fn to_parameter(components: &mut Components) -> Parameter;
}
pub trait ToRequestBody {
fn to_request_body(components: &mut Components) -> RequestBody;
}
pub trait ToResponses {
fn to_responses(components: &mut Components) -> Responses;
}
impl<C> ToResponses for writing::Json<C>
where
C: ToSchema,
{
fn to_responses(components: &mut Components) -> Responses {
Responses::new().response(
"200",
Response::new("Response json format data")
.add_content("application/json", Content::new(C::to_schema(components))),
)
}
}
impl ToResponses for StatusError {
fn to_responses(components: &mut Components) -> Responses {
let mut responses = Responses::new();
let errors = vec![
Self::bad_request(),
Self::unauthorized(),
Self::payment_required(),
Self::forbidden(),
Self::not_found(),
Self::method_not_allowed(),
Self::not_acceptable(),
Self::proxy_authentication_required(),
Self::request_timeout(),
Self::conflict(),
Self::gone(),
Self::length_required(),
Self::precondition_failed(),
Self::payload_too_large(),
Self::uri_too_long(),
Self::unsupported_media_type(),
Self::range_not_satisfiable(),
Self::expectation_failed(),
Self::im_a_teapot(),
Self::misdirected_request(),
Self::unprocessable_entity(),
Self::locked(),
Self::failed_dependency(),
Self::upgrade_required(),
Self::precondition_required(),
Self::too_many_requests(),
Self::request_header_fields_toolarge(),
Self::unavailable_for_legalreasons(),
Self::internal_server_error(),
Self::not_implemented(),
Self::bad_gateway(),
Self::service_unavailable(),
Self::gateway_timeout(),
Self::http_version_not_supported(),
Self::variant_also_negotiates(),
Self::insufficient_storage(),
Self::loop_detected(),
Self::not_extended(),
Self::network_authentication_required(),
];
for Self { code, brief, .. } in errors {
responses.insert(
code.as_str(),
Response::new(brief).add_content(
"application/json",
Content::new(Self::to_schema(components)),
),
)
}
responses
}
}
impl ToResponses for salvo_core::Error {
fn to_responses(components: &mut Components) -> Responses {
StatusError::to_responses(components)
}
}
pub trait ToResponse {
fn to_response(components: &mut Components) -> RefOr<crate::Response>;
}
impl<C> ToResponse for writing::Json<C>
where
C: ToSchema,
{
fn to_response(components: &mut Components) -> RefOr<Response> {
let schema = <C as ToSchema>::to_schema(components);
Response::new("Response with json format data")
.add_content("application/json", Content::new(schema))
.into()
}
}
#[cfg(test)]
mod tests {
use assert_json_diff::assert_json_eq;
use serde_json::json;
use super::*;
#[test]
fn test_primitive_schema() {
let mut components = Components::new();
let non_strict = cfg!(feature = "non-strict-integers");
for (name, schema, value) in [
(
"i8",
i8::to_schema(&mut components),
if non_strict {
json!({"type": "integer", "format": "int8"})
} else {
json!({"type": "integer", "format": "int32"})
},
),
(
"i16",
i16::to_schema(&mut components),
if non_strict {
json!({"type": "integer", "format": "int16"})
} else {
json!({"type": "integer", "format": "int32"})
},
),
(
"i32",
i32::to_schema(&mut components),
json!({"type": "integer", "format": "int32"}),
),
(
"i64",
i64::to_schema(&mut components),
json!({"type": "integer", "format": "int64"}),
),
(
"i128",
i128::to_schema(&mut components),
json!({"type": "integer"}),
),
(
"isize",
isize::to_schema(&mut components),
json!({"type": "integer"}),
),
(
"u8",
u8::to_schema(&mut components),
if non_strict {
json!({"type": "integer", "format": "uint8", "minimum": 0})
} else {
json!({"type": "integer", "format": "int32", "minimum": 0})
},
),
(
"u16",
u16::to_schema(&mut components),
if non_strict {
json!({"type": "integer", "format": "uint16", "minimum": 0})
} else {
json!({"type": "integer", "format": "int32", "minimum": 0})
},
),
(
"u32",
u32::to_schema(&mut components),
if non_strict {
json!({"type": "integer", "format": "uint32", "minimum": 0})
} else {
json!({"type": "integer", "format": "int32", "minimum": 0})
},
),
(
"u64",
u64::to_schema(&mut components),
if non_strict {
json!({"type": "integer", "format": "uint64", "minimum": 0})
} else {
json!({"type": "integer", "format": "int64", "minimum": 0})
},
),
(
"u128",
u128::to_schema(&mut components),
json!({"type": "integer", "minimum": 0}),
),
(
"usize",
usize::to_schema(&mut components),
json!({"type": "integer", "minimum": 0}),
),
(
"bool",
bool::to_schema(&mut components),
json!({"type": "boolean"}),
),
(
"str",
str::to_schema(&mut components),
json!({"type": "string"}),
),
(
"String",
String::to_schema(&mut components),
json!({"type": "string"}),
),
(
"char",
char::to_schema(&mut components),
json!({"type": "string"}),
),
(
"f32",
f32::to_schema(&mut components),
json!({"type": "number", "format": "float"}),
),
(
"f64",
f64::to_schema(&mut components),
json!({"type": "number", "format": "double"}),
),
] {
println!(
"{name}: {json}",
json = serde_json::to_string(&schema).unwrap()
);
let schema = serde_json::to_value(schema).unwrap();
assert_json_eq!(schema, value);
}
}
}