axum-openapi3-derive 0.2.3

Facilitate the generation of OpenAPI 3.0 documentation for axum applications - derive macro
Documentation
use syn::{spanned::Spanned, FnArg, Signature};

use crate::util::recursive_type;

#[derive(Debug)]
pub enum HandlerArgument {
    RequestBody(String),
    Query(String),
    State(String),
    Path(String),
}

pub fn parse_handler_arguments(sig: &Signature) -> Result<Vec<HandlerArgument>, syn::Error> {
    let mut ret = vec![];
    for input in &sig.inputs {
        match input {
            FnArg::Typed(pat_type) => {
                let ty = &pat_type.ty;

                match ty.as_ref() {
                    syn::Type::Path(path) => {
                        let mut v = vec![];
                        recursive_type(path, &mut v);

                        let extractor = v.remove(0);

                        match extractor.as_str() {
                            "Json" => {
                                let l = v.len();

                                ret.push(HandlerArgument::RequestBody(
                                    v.join("<") + ">".repeat(l - 1).as_str(),
                                ));
                            }
                            "Query" => {
                                let l = v.len();

                                ret.push(HandlerArgument::Query(
                                    v.join("<") + ">".repeat(l - 1).as_str(),
                                ));
                            }
                            "State" => {
                                let l = v.len();

                                ret.push(HandlerArgument::State(
                                    v.join("<") + ">".repeat(l - 1).as_str(),
                                ));
                            }
                            "Path" => {
                                let l = v.len();

                                ret.push(HandlerArgument::Path(
                                    v.join("<") + ">".repeat(l - 1).as_str(),
                                ));
                            }
                            _ => continue,
                        };
                    }
                    _ => {
                        return Err(syn::Error::new(ty.span(), "Expected Type::Path type"));
                    }
                }
            }
            _ => {
                return Err(syn::Error::new(
                    input.span(),
                    "Self argument is unsupported",
                ));
            }
        };
    }

    Ok(ret)
}

pub fn parse_handler_ret_type(sig: &Signature) -> Result<Option<String>, syn::Error> {
    match &sig.output {
        syn::ReturnType::Default => Err(syn::Error::new(sig.output.span(), "Expected return type")),
        syn::ReturnType::Type(_, ty) => match ty.as_ref() {
            syn::Type::Path(path) => {
                let mut v = vec![];
                recursive_type(path, &mut v);

                if v.remove(0) != "Json" {
                    Ok(None)
                } else {
                    let l = v.len();
                    Ok(Some(v.join("<") + ">".repeat(l - 1).as_str()))
                }
            }
            _ => Ok(None),
        },
    }
}