use openapiv3::{ReferenceOr, SchemaKind, Type};
use proc_macro2::{Ident, TokenStream as TokenStream2};
use quote::quote;
use heck::ToSnakeCase;
use crate::utils::create_rust_safe_ident;
use crate::codegen::reference_or_schema_to_rust_type;
pub struct ParameterInfo {
pub name: String,
pub ident: Ident,
pub param_type: TokenStream2,
pub location: ParameterLocation,
pub is_array: bool,
}
#[derive(Debug, PartialEq)]
pub enum ParameterLocation {
Path,
Query,
Header,
Cookie,
}
pub fn process_parameter(
param_name: &str,
param_schema: &openapiv3::ParameterSchemaOrContent,
location: ParameterLocation,
) -> Result<ParameterInfo, String> {
let snake_case_param = param_name.to_snake_case();
let param_ident = create_rust_safe_ident(&snake_case_param);
let param_type = match param_schema {
openapiv3::ParameterSchemaOrContent::Schema(schema_ref) => {
reference_or_schema_to_rust_type(schema_ref)?
}
_ => quote! { String },
};
let is_array = match param_schema {
openapiv3::ParameterSchemaOrContent::Schema(schema_ref) => {
match schema_ref {
ReferenceOr::Item(schema) => {
matches!(schema.schema_kind, SchemaKind::Type(Type::Array(_)))
}
_ => false,
}
}
_ => false,
};
Ok(ParameterInfo {
name: param_name.to_string(),
ident: param_ident,
param_type,
location,
is_array,
})
}
pub fn generate_url_building(
path: &str,
path_params: &[&ParameterInfo],
query_params: &[&ParameterInfo],
) -> TokenStream2 {
let mut url_building = if path_params.is_empty() {
quote! {
let mut url = format!("{}{}", self.base_url, #path);
}
} else {
let path_replacements = path_params.iter().map(|param| {
let placeholder = format!("{{{}}}", param.name);
let param_ident = ¶m.ident;
quote! {
.replace(#placeholder, &#param_ident.to_string())
}
});
quote! {
let mut url = format!("{}{}", self.base_url, #path) #(#path_replacements)*;
}
};
if !query_params.is_empty() {
let query_building = query_params.iter().map(|param| {
let param_name = ¶m.name;
let param_ident = ¶m.ident;
if param.is_array {
quote! {
let param_value = #param_ident.join(",");
parsed_url.query_pairs_mut().append_pair(#param_name, ¶m_value);
}
} else {
quote! {
parsed_url.query_pairs_mut().append_pair(#param_name, &#param_ident.to_string());
}
}
});
url_building.extend(quote! {
let mut parsed_url = reqwest::Url::parse(&url).map_err(|e| ApiError::Api {
status: 400,
message: format!("Invalid URL: {}", e)
})?;
#(#query_building)*
let url = parsed_url.to_string();
});
}
url_building
}