Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions codegen/src/enu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ pub enum Method {
POST,
PUT,
DELETE,
PATCH,
HEAD,
OPTIONS,
}

impl Method {
Expand All @@ -15,6 +18,9 @@ impl Method {
Method::POST => "POST",
Method::PUT => "PUT",
Method::DELETE => "DELETE",
Method::PATCH => "PATCH",
Method::HEAD => "HEAD",
Method::OPTIONS => "OPTIONS",
}
}
pub fn from_str(str: &str) -> Result<Method, String> {
Expand All @@ -23,6 +29,9 @@ impl Method {
"post" | "POST" => Ok(Method::POST),
"put" | "PUT" => Ok(Method::PUT),
"delete" | "DELETE" => Ok(Method::DELETE),
"patch" | "PATCH" => Ok(Method::PATCH),
"head" | "HEAD" => Ok(Method::HEAD),
"options" | "OPTIONS" => Ok(Method::OPTIONS),
_ => Err("unknown request method marker: ".to_string() + str),
}
}
Expand Down
24 changes: 16 additions & 8 deletions codegen/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn client_fn_impl(mut item_struct: DataStruct) -> syn::Result<proc_macro2::T
let (query_array_names, query_array_vars) =
find_type_name_vars(&args, ArgType::QUERY, |fn_arg| filter_query_array(fn_arg));

let (_query_struct_names, query_struct_vars) =
let (query_struct_names, query_struct_vars) =
find_type_name_vars(&args, ArgType::QUERY, |fn_arg| filter_struct(fn_arg));

let tokens = quote!(
Expand Down Expand Up @@ -123,9 +123,13 @@ pub fn client_fn_impl(mut item_struct: DataStruct) -> syn::Result<proc_macro2::T
)*

#(
let map = ser::to_map(& self.#query_struct_vars)?;
for (key, value) in map {
query_vec.push((key, value));
let mut pairs = ser::to_pairs(& self.#query_struct_vars)?;
for (key, value) in pairs.drain(..) {
if key.is_empty() {
query_vec.push((#query_struct_names.to_string(), value));
} else {
query_vec.push((key, value));
}
}
)*
Ok(query_vec)
Expand Down Expand Up @@ -198,7 +202,7 @@ pub fn fn_impl(
let (query_array_names, query_array_vars) =
find_type_name_vars(&args, ArgType::QUERY, |fn_arg| filter_query_array(fn_arg));

let (_query_struct_names, query_struct_vars) =
let (query_struct_names, query_struct_vars) =
find_type_name_vars(&args, ArgType::QUERY, |fn_arg| filter_struct(fn_arg));

let (form_names, form_vars) = find_type_name_vars(&args, ArgType::FORM, |_fn_arg| true);
Expand Down Expand Up @@ -373,9 +377,13 @@ pub fn fn_impl(
)*

#(
let map = ser::to_map(& #query_struct_vars)?;
for (key, value) in map.iter() {
query_vec.push((key.clone(), value.to_string()));
let mut pairs = ser::to_pairs(& #query_struct_vars)?;
for (key, value) in pairs.drain(..) {
if key.is_empty() {
query_vec.push((#query_struct_names.to_string(), value));
} else {
query_vec.push((key, value));
}
}
)*

Expand Down
15 changes: 15 additions & 0 deletions codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ pub fn delete(attr: TokenStream, item: TokenStream) -> TokenStream {
http_impl(Method::DELETE, attr, item)
}

#[proc_macro_attribute]
pub fn patch(attr: TokenStream, item: TokenStream) -> TokenStream {
http_impl(Method::PATCH, attr, item)
}

#[proc_macro_attribute]
pub fn head(attr: TokenStream, item: TokenStream) -> TokenStream {
http_impl(Method::HEAD, attr, item)
}

#[proc_macro_attribute]
pub fn options(attr: TokenStream, item: TokenStream) -> TokenStream {
http_impl(Method::OPTIONS, attr, item)
}

#[proc_macro_derive(Context, attributes(url_path, query, header, param))]
pub fn feign_context(item: TokenStream) -> TokenStream {
feign_context_impl(item)
Expand Down
17 changes: 13 additions & 4 deletions codegen/src/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ pub fn feign_impl(attr: TokenStream, item: TokenStream) -> TokenStream {
let builder_ident = format_ident!("{}Builder", trait_ident);

let trait_fn_streams =
match fn_to_streams_for_trait(url.clone(), &item_trait.items, meta_map.clone()) {
match fn_to_streams_for_trait(
url.clone(),
&item_trait.items,
meta_map.clone(),
&item_trait.vis,
) {
Ok(streams) => streams,
Err(err) => return err.into_compile_error().into(),
};
Expand Down Expand Up @@ -286,6 +291,7 @@ fn fn_to_streams_for_trait(
url: proc_macro2::TokenStream,
items: &[syn::TraitItem],
meta_map: HashMap<String, String>,
trait_vis: &syn::Visibility,
) -> syn::Result<Vec<proc_macro2::TokenStream>> {
let base_url = url;
let base_meta = meta_map;
Expand Down Expand Up @@ -314,7 +320,7 @@ fn fn_to_streams_for_trait(
meta_map.insert(k, v);
}

let item_fn = trait_method_to_item_fn(trait_method);
let item_fn = trait_method_to_item_fn(trait_method, trait_vis);
let fn_stream = fn_impl(
FnMetadata {
url,
Expand All @@ -332,12 +338,15 @@ fn fn_to_streams_for_trait(
Ok(trait_fn_streams)
}

fn trait_method_to_item_fn(trait_method: &syn::TraitItemFn) -> syn::ItemFn {
fn trait_method_to_item_fn(
trait_method: &syn::TraitItemFn,
trait_vis: &syn::Visibility,
) -> syn::ItemFn {
let sig = &trait_method.sig;

syn::ItemFn {
attrs: trait_method.attrs.clone(),
vis: syn::Visibility::Inherited,
vis: trait_vis.clone(),
sig: syn::Signature {
constness: None,
asyncness: sig.asyncness,
Expand Down
24 changes: 24 additions & 0 deletions examples/method.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use feignhttp::{head, options, patch};

#[patch("https://httpbin.org/patch")]
async fn patch() -> feignhttp::Result<String> {}

#[head("https://httpbin.org/get")]
async fn head() -> feignhttp::Result<()> {}

#[options("https://httpbin.org")]
async fn options() -> feignhttp::Result<String> {}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let r = patch().await?;
println!("patch result: {}", r);

head().await?;
println!("head ok");

let r = options().await?;
println!("options result: {}", r);

Ok(())
}
Loading