aster_forge_api/response/
schema.rs1use super::{ApiErrorInfo, ApiResponse};
3use std::borrow::Cow;
4use utoipa::{
5 PartialSchema, ToSchema,
6 openapi::{
7 Ref, RefOr,
8 schema::{ObjectBuilder, Schema, Type},
9 },
10};
11
12fn value_schema<T: ToSchema>() -> RefOr<Schema> {
15 if std::any::type_name::<T>() == "()" {
16 ObjectBuilder::new().schema_type(Type::Null).into()
17 } else {
18 T::schema()
19 }
20}
21
22fn collect<T: ToSchema>(schemas: &mut Vec<(String, RefOr<Schema>)>) {
23 schemas.push((T::name().into_owned(), value_schema::<T>()));
24 T::schemas(schemas);
25}
26
27fn collect_error_info<D: ToSchema>(schemas: &mut Vec<(String, RefOr<Schema>)>) {
28 schemas.push((
29 format!("ApiErrorInfo_{}", D::name()),
30 ApiErrorInfo::<D>::schema(),
31 ));
32 D::schemas(schemas);
33 if std::any::type_name::<D>() != "()" {
34 let diagnostic_name = D::name().into_owned();
35 if !schemas.iter().any(|(name, _)| name == &diagnostic_name) {
36 schemas.push((diagnostic_name, value_schema::<D>()));
37 }
38 }
39}
40
41fn diagnostic_schema<D: ToSchema>() -> RefOr<Schema> {
42 if std::any::type_name::<D>() == "()" {
43 value_schema::<D>()
44 } else {
45 RefOr::Ref(Ref::from_schema_name(D::name()))
46 }
47}
48
49impl<D: ToSchema> ToSchema for ApiErrorInfo<D> {
50 fn name() -> Cow<'static, str> {
51 Cow::Borrowed("ApiErrorInfo")
52 }
53 fn schemas(schemas: &mut Vec<(String, RefOr<Schema>)>) {
54 D::schemas(schemas);
55 }
56}
57
58impl<D: ToSchema> utoipa::__dev::ComposeSchema for ApiErrorInfo<D> {
61 fn compose(_generics: Vec<RefOr<Schema>>) -> RefOr<Schema> {
62 ObjectBuilder::new()
63 .property("retryable", bool::schema())
64 .required("retryable")
65 .property("diagnostic", diagnostic_schema::<D>())
66 .into()
67 }
68}
69
70impl<T: ToSchema, C: ToSchema, D: ToSchema> ToSchema for ApiResponse<T, C, D> {
71 fn name() -> Cow<'static, str> {
72 Cow::Borrowed("ApiResponse")
73 }
74 fn schemas(schemas: &mut Vec<(String, RefOr<Schema>)>) {
75 T::schemas(schemas);
76 collect::<C>(schemas);
77 collect_error_info::<D>(schemas);
78 }
79}
80
81impl<T: ToSchema, C: ToSchema, D: ToSchema> utoipa::__dev::ComposeSchema for ApiResponse<T, C, D> {
82 fn compose(_generics: Vec<RefOr<Schema>>) -> RefOr<Schema> {
83 ObjectBuilder::new()
84 .property("code", Ref::from_schema_name(C::name()))
85 .required("code")
86 .property("msg", String::schema())
87 .required("msg")
88 .property("data", value_schema::<T>())
89 .property(
90 "error",
91 Ref::from_schema_name(format!("ApiErrorInfo_{}", D::name())),
92 )
93 .into()
94 }
95}