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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use std::collections::BTreeMap;

use openapiv3::{
    ArrayType, BooleanType, IntegerType, NumberType, Schema, SchemaData, SchemaKind, StringType,
    Type, VariantOrUnknownOrEmpty,
};
use paste::paste;

use crate::ToSchema;

impl ToSchema for bool {
    fn schema(_: &mut BTreeMap<String, Schema>, _: &mut Vec<String>) -> Schema {
        Schema {
            schema_data: SchemaData {
                title: Some("bool".to_string()),
                ..Default::default()
            },
            schema_kind: SchemaKind::Type(Type::Boolean(BooleanType::default())),
        }
    }
}

impl ToSchema for char {
    fn schema(_: &mut BTreeMap<String, Schema>, _: &mut Vec<String>) -> Schema {
        Schema {
            schema_data: SchemaData {
                title: Some("char".to_string()),
                ..Default::default()
            },
            schema_kind: SchemaKind::Type(Type::String(StringType {
                min_length: Some(1),
                max_length: Some(1),
                ..Default::default()
            })),
        }
    }
}

macro_rules! simple_impl {
    ($ty:ty, $ty_variant:ident, $format:literal) => {
        impl ToSchema for $ty {
            fn schema(_: &mut BTreeMap<String, Schema>, _: &mut Vec<String>) -> Schema {
                Schema {
                    schema_data: SchemaData {
                        title: Some(stringify!($ty).to_string()),
                        ..Default::default()
                    },
                    schema_kind: paste! {
                        SchemaKind::Type(Type::$ty_variant([<$ty_variant Type>] {
                            format: VariantOrUnknownOrEmpty::Unknown($format.to_string()),
                            ..Default::default()
                        }))
                    },
                }
            }
        }
    };
}

simple_impl!(f32, Number, "float");
simple_impl!(f64, Number, "double");
simple_impl!(i8, Integer, "int8");
simple_impl!(i16, Integer, "int16");
simple_impl!(i32, Integer, "int32");
simple_impl!(i64, Integer, "int64");
simple_impl!(i128, Integer, "int128");
simple_impl!(isize, Integer, "int");

macro_rules! unsigned_impl {
    ($ty:ty, $format:literal) => {
        impl ToSchema for $ty {
            fn schema(_: &mut BTreeMap<String, Schema>, _: &mut Vec<String>) -> Schema {
                Schema {
                    schema_data: SchemaData {
                        title: Some(stringify!($ty).to_string()),
                        ..Default::default()
                    },
                    schema_kind: SchemaKind::Type(Type::Integer(IntegerType {
                        format: VariantOrUnknownOrEmpty::Unknown($format.to_string()),
                        minimum: Some(0),
                        ..Default::default()
                    })),
                }
            }
        }
    };
}

unsigned_impl!(u8, "uint8");
unsigned_impl!(u16, "uint16");
unsigned_impl!(u32, "uint32");
unsigned_impl!(u64, "uint64");
unsigned_impl!(u128, "uint128");
unsigned_impl!(usize, "uint");

impl<T: ToSchema, const N: usize> ToSchema for [T; N] {
    fn schema(
        schemas: &mut BTreeMap<String, Schema>,
        schemas_in_progress: &mut Vec<String>,
    ) -> Schema {
        let schema = T::schema(schemas, schemas_in_progress);
        let title = schema.schema_data.title.as_deref().unwrap_or("Unknown");
        let title = format!("Array{}<{}>", N, title);

        let ty = ArrayType {
            items: Some(T::schema_ref_box(schemas, schemas_in_progress)),
            min_items: Some(N),
            max_items: Some(N),
            unique_items: false,
        };

        Schema {
            schema_data: SchemaData {
                title: Some(title),
                ..Default::default()
            },
            schema_kind: SchemaKind::Type(Type::Array(ty)),
        }
    }
}