use crate::{ObjectVisitor, OpenapiType, Visitor};
use indexmap::{IndexMap, IndexSet};
use serde_json::Value;
use std::{
collections::{BTreeMap, BTreeSet, HashMap, HashSet, LinkedList, VecDeque},
ffi::{CStr, CString},
num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize}
};
impl OpenapiType for () {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_unit();
}
}
impl OpenapiType for Value {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_any();
}
}
impl OpenapiType for bool {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_bool();
}
}
macro_rules! tuples {
($(#[$($attr:tt)*])* ($($fixed:ident),*),) => {};
($(#[$($attr:tt)*])* ($($fixed:ident),*), $first:ident $(, $other:ident)*) => {
tuples!($(#[$($attr)*])* ($($fixed),*), $($other),*);
$(#[$($attr)*])*
impl<$first, $($other,)* $($fixed,)*> OpenapiType for ($first, $($other,)* $($fixed,)*)
where
$first: OpenapiType,
$($other: OpenapiType,)*
$($fixed: OpenapiType,)*
{
fn visit_type<V: Visitor>(visitor: &mut V) {
let visitor = visitor.visit_tuple();
use $crate::TupleVisitor as _;
$first::visit_type(visitor.visit_field(None));
$($other::visit_type(visitor.visit_field(None));)*
$($fixed::visit_type(visitor.visit_field(None));)*
}
}
};
}
#[cfg(feature = "tuples16")]
tuples! {
#[cfg(feature = "tuples16")]
(),
T15, T14, T13, T12, T11, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1, T0
}
#[cfg(feature = "tuples32")]
tuples! {
#[cfg(feature = "tuples32")]
(T15, T14, T13, T12, T11, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1, T0),
T31, T30, T29, T28, T27, T26, T25, T24, T23, T22, T21, T20, T19, T18, T17, T16
}
#[cfg(feature = "tuples48")]
tuples! {
#[cfg(feature = "tuples48")]
(
T31, T30, T29, T28, T27, T26, T25, T24, T23, T22, T21, T20, T19, T18, T17, T16,
T15, T14, T13, T12, T11, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1, T0
),
T47, T46, T45, T44, T43, T42, T41, T40, T39, T38, T37, T36, T35, T34, T33, T32
}
#[cfg(feature = "tuples64")]
tuples! {
#[cfg(feature = "tuples64")]
(
T47, T46, T45, T44, T43, T42, T41, T40, T39, T38, T37, T36, T35, T34, T33, T32,
T31, T30, T29, T28, T27, T26, T25, T24, T23, T22, T21, T20, T19, T18, T17, T16,
T15, T14, T13, T12, T11, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1, T0
),
T63, T62, T61, T60, T59, T58, T57, T56, T55, T54, T53, T52, T51, T50, T49, T48
}
macro_rules! int {
($($ty:ident($minimum:expr, $bits:expr);)+) => {
$(
impl OpenapiType for $ty {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_int($bits, $minimum);
}
}
)+
}
}
int! {
isize(None, None);
i8(None, Some(8));
i16(None, Some(16));
i32(None, Some(32));
i64(None, Some(64));
i128(None, Some(128));
usize(Some(0), None);
u8(Some(0), Some(8));
u16(Some(0), Some(16));
u32(Some(0), Some(32));
u64(Some(0), Some(64));
u128(Some(0), Some(128));
NonZeroUsize(Some(1), None);
NonZeroU8(Some(1), Some(8));
NonZeroU16(Some(1), Some(16));
NonZeroU32(Some(1), Some(32));
NonZeroU64(Some(1), Some(64));
NonZeroU128(Some(1), Some(128));
}
macro_rules! number {
($($ty:ident($bits:expr);)+) => {
$(
impl OpenapiType for $ty {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_number($bits);
}
}
)+
}
}
number! {
f32(Some(32));
f64(Some(64));
}
impl OpenapiType for char {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_char();
}
}
macro_rules! string {
($($ty:ident;)+) => {
$(
impl OpenapiType for $ty {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_string();
}
}
)+
}
}
string! {
String;
str;
CString;
CStr;
}
#[cfg(feature = "url2")]
impl OpenapiType for url2::Url {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_url();
}
}
#[cfg(feature = "uuid1")]
impl OpenapiType for uuid1::Uuid {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_uuid();
}
}
#[cfg(feature = "_datetime")]
macro_rules! date {
($($(#[$($attr:tt)*])* $($ty:ident)::+ $(<$arg:ident: $bound:path>)?;)+) => {
$(
$(#[$($attr)*])*
impl$(<$arg: $bound>)? OpenapiType for $($ty)::+$(<$arg>)? {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_date();
}
}
)+
}
}
#[cfg(feature = "_datetime")]
date! {
#[cfg(feature = "chrono04")]
#[allow(deprecated)]
chrono04::Date<T: chrono04::TimeZone>;
#[cfg(feature = "chrono04")]
chrono04::NaiveDate;
#[cfg(feature = "jiff02")]
jiff02::civil::Date;
#[cfg(feature = "time03")]
time03::Date;
}
#[cfg(feature = "_datetime")]
macro_rules! datetime {
($($(#[$($attr:tt)*])* $($ty:ident)::+ $(<$arg:ident: $bound:path>)?;)+) => {
$(
$(#[$($attr)*])*
impl$(<$arg: $bound>)? OpenapiType for $($ty)::+$(<$arg>)? {
fn visit_type<V: Visitor>(visitor: &mut V) {
visitor.visit_datetime();
}
}
)+
}
}
#[cfg(feature = "_datetime")]
datetime! {
#[cfg(feature = "chrono04")]
chrono04::DateTime<T: chrono04::TimeZone>;
#[cfg(feature = "chrono04")]
chrono04::NaiveDateTime;
#[cfg(feature = "jiff02")]
jiff02::civil::DateTime;
#[cfg(feature = "jiff02")]
jiff02::Timestamp;
#[cfg(feature = "jiff02")]
jiff02::Zoned;
#[cfg(feature = "time03")]
time03::PrimitiveDateTime;
#[cfg(feature = "time03")]
time03::OffsetDateTime;
#[cfg(feature = "time03")]
time03::UtcDateTime;
}
impl<T: OpenapiType> OpenapiType for Option<T> {
fn visit_type<V: Visitor>(visitor: &mut V) {
let v = visitor.visit_option();
T::visit_type(v);
}
}
macro_rules! array {
($($(#[$($attr:tt)*])* $($ty:ident)::+ $(<$($arg:ident),+>)? ($unique_items:literal, $inner:ident);)+) => {
$(
$(#[$($attr)*])*
impl$(<$($arg),+>)? OpenapiType for $($ty)::+$(<$($arg),+>)?
where
$inner: OpenapiType
{
fn visit_type<V: Visitor>(visitor: &mut V) {
let v = visitor.visit_array(None, $unique_items);
<$inner as OpenapiType>::visit_type(v);
}
}
)+
}
}
type Array<T> = [T];
array! {
Array<T>(false, T);
LinkedList<T>(false, T);
Vec<T>(false, T);
VecDeque<T>(false, T);
BTreeSet<T>(true, T);
HashSet<T, S>(true, T);
IndexSet<T, S>(true, T);
#[cfg(feature = "hashbrown016")]
hashbrown016::HashSet<T, S>(true, T);
#[cfg(feature = "hashbrown017")]
hashbrown017::HashSet<T, S>(true, T);
}
impl<T: OpenapiType, const N: usize> OpenapiType for [T; N] {
fn visit_type<V: Visitor>(visitor: &mut V) {
let v = visitor.visit_array(Some(N as u64), false);
T::visit_type(v);
}
}
macro_rules! map {
($($(#[$($attr:tt)*])* $($ty:ident)::+ $(<$($arg:ident$(: $bound:path)?),+>)? ($inner:ident);)+) => {
$(
$(#[$($attr)*])*
impl$(<$($arg$(: $bound)?),+>)? OpenapiType for $($ty)::+$(<$($arg),+>)?
where
$inner: OpenapiType
{
fn visit_type<Vi: Visitor>(visitor: &mut Vi) {
let obj = visitor.visit_object();
let v = obj.visit_additional();
<$inner as OpenapiType>::visit_type(v);
}
}
)+
}
}
map! {
BTreeMap<K, V>(V);
HashMap<K, V, S>(V);
IndexMap<K, V, S>(V);
#[cfg(feature = "hashbrown016")]
hashbrown016::HashMap<K, V, S>(V);
#[cfg(feature = "hashbrown017")]
hashbrown017::HashMap<K, V, S>(V);
#[cfg(feature = "linked-hash-map05")]
linked_hash_map05::LinkedHashMap<K, V, S>(V);
}