autapi 0.0.1

Automatic OpenAPI specification from function signatures
Documentation
macro_rules! define_openapi_spec_object {
    (
        $([$($feature:ident),*]:)?
        $(#[$attr:meta])*
        pub struct $name:ident {
            $(
            $(#[$field_attr:meta])*
            pub $field_name:ident: $field_ty:ident $(<$($field_gen:ty),*>)?,
            )*
        }
    ) => {
        #[serde_with::skip_serializing_none]
        #[derive(PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
        #[serde(rename_all = "camelCase")]
        #[non_exhaustive]
        $(#[$attr])*
        pub struct $name {
            $(
            $(#[$field_attr])*
            pub $field_name: $field_ty $(<$($field_gen,)*>)?,
            )*
        }
        impl $name {
            $(
                $crate::openapi::macros::define_openapi_spec_object!(@with_fn $field_name $field_ty $(<$($field_gen),*>)?);
                $crate::openapi::macros::define_openapi_spec_object!(@with_entry $field_name $field_ty $(<$($field_gen),*>)?);
            )*
            $crate::openapi::macros::define_openapi_spec_object!(@impl_features [$($($feature),*)?] {
                $(#[$attr])*
                pub struct $name {
                    $(
                    $(#[$field_attr])*
                    pub $field_name: $field_ty $(<$($field_gen,)*>)?,
                    )*
                }
            });
        }
    };
    (@with_entry $field_name:ident Map<$key:ty, $value:ty>) => {
        pastey::paste! {
            pub fn [< with_ $field_name _entry>](mut self, key: impl Into<$key>, value: impl Into<$value>) -> Self {
                self.$field_name.insert(key.into(), value.into());
                self
            }
        }
    };
    (@with_entry $field_name:ident Vec<$value:ty>) => {
        pastey::paste! {
            pub fn [< with_ $field_name _entry>](mut self, value: impl Into<$value>) -> Self {
                self.$field_name.push(value.into());
                self
            }
        }
    };
    (@with_entry $field_name:ident Extensions) => {
        pastey::paste! {
            pub fn with_extension(mut self, key: impl Into<String>, value: impl Into<Value>) -> Self {
                self.insert_extension(key, value);
                self
            }
            pub fn insert_extension(&mut self, key:  impl Into<String>, value: impl Into<Value>) -> Option<serde_json::Value> {
                self.$field_name.insert(key.into(), value.into())
            }
        }
    };
    (@with_entry $field_name:ident $field_ty:ty) => {};
    (@with_fn $field_name:ident Option<$field_ty:ty>) => {
        pastey::paste! {
            pub fn [< with_ $field_name>](mut self, value: impl Into<$field_ty>) -> Self {
                self.$field_name = Some(value.into());
                self
            }
            pub fn [< with_maybe_ $field_name>](mut self, value: impl Into<Option<$field_ty>>) -> Self {
                self.$field_name = value.into();
                self
            }
        }
    };
    (@with_fn $field_name:ident $field_ty:ty) => {
        pastey::paste! {
            pub fn [< with_ $field_name>](mut self, value: impl Into<$field_ty>) -> Self {
                self.$field_name = value.into();
                self
            }
        }
    };
    (@impl_features [$($feature:ident),*] $def:tt) => {
        $($crate::openapi::macros::define_openapi_spec_object!(@impl_feature $feature $def);)*
    };
    (@impl_feature override_with {
        $(#[$attr:meta])*
        pub struct $name:ident {
            $(
            $(#[$field_attr:meta])*
            pub $field_name:ident: $field_ty:ident $(<$($field_gen:ty,)*>)?,
            )*
        }
    }
    ) => {
        pub fn override_with(&mut self, other: Self) {
            $(
                if !$crate::private::is_default(&other.$field_name) {
                    self.$field_name = other.$field_name;
                }
            )*
        }
    }
}

pub(crate) use define_openapi_spec_object;