ud
This commit is contained in:
105
Cargo.lock
generated
105
Cargo.lock
generated
@ -156,9 +156,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "awc"
|
||||
version = "3.7.0"
|
||||
version = "3.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e76d68b4f02400c2f9110437f254873e8f265b35ea87352f142bc7c8e878115a"
|
||||
checksum = "117ec0a30fe956b77d69efff54bce923854df0437874fe4bfa701dfdddca8d5d"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-http",
|
||||
@ -252,18 +252,18 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
|
||||
[[package]]
|
||||
name = "bytestring"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f"
|
||||
checksum = "113b4343b5f6617e7ad401ced8de3cc8b012e73a594347c307b90db3e9271289"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.36"
|
||||
version = "1.2.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54"
|
||||
checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
@ -373,9 +373,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d"
|
||||
checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
@ -458,7 +458,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasi 0.14.4+wasi-0.2.4",
|
||||
"wasi 0.14.7+wasi-0.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -488,9 +488,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
@ -556,9 +556,9 @@ checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.11.0"
|
||||
version = "2.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9"
|
||||
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
@ -599,9 +599,9 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.175"
|
||||
version = "0.2.176"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
|
||||
|
||||
[[package]]
|
||||
name = "local-channel"
|
||||
@ -833,18 +833,28 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
version = "1.0.226"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.226"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
version = "1.0.226"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -853,23 +863,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.143"
|
||||
version = "1.0.145"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
|
||||
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.0.0"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
|
||||
checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -945,11 +956,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.43"
|
||||
version = "0.3.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031"
|
||||
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
@ -1007,12 +1019,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.5"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8"
|
||||
checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
@ -1022,27 +1034,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.0"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
|
||||
checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
|
||||
checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64"
|
||||
checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
@ -1072,9 +1084,9 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
@ -1102,9 +1114,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.14.4+wasi-0.2.4"
|
||||
version = "0.14.7+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a"
|
||||
checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
|
||||
dependencies = [
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.1+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
@ -1190,9 +1211,9 @@ checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.45.1"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36"
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
|
||||
188
src/lib.rs
188
src/lib.rs
@ -1,118 +1,83 @@
|
||||
// src/lib.rs -- proc-macro crate
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Span;
|
||||
use quote::{quote};
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
parse_macro_input, ItemStruct, ItemEnum, Fields, Type, Meta, Lit, Expr,
|
||||
punctuated::Punctuated, token::Comma, MetaNameValue, parse::Parser
|
||||
punctuated::Punctuated, token::Comma, MetaNameValue,
|
||||
// Important: Parser trait brings `parse2` into scope for parser functions
|
||||
parse::Parser,
|
||||
};
|
||||
|
||||
/// #[http(...)] attribute macro
|
||||
/// Accepts (with defaults):
|
||||
/// - method = "GET"
|
||||
/// - live_url = ""
|
||||
/// - sandbox_url = ""
|
||||
/// - response = "<StructName>Resp"
|
||||
/// - error = "Box<dyn std::error::Error>"
|
||||
#[proc_macro_attribute]
|
||||
pub fn http(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
// parse the struct we're attached to
|
||||
let mut input = parse_macro_input!(item as ItemStruct);
|
||||
let input = parse_macro_input!(item as ItemStruct);
|
||||
let struct_ident = &input.ident;
|
||||
|
||||
// defaults
|
||||
let mut method_s = "GET".to_string();
|
||||
let mut url_s = "".to_string();
|
||||
let mut live_url_s = "".to_string();
|
||||
let mut sandbox_url_s = "".to_string();
|
||||
let mut response_s = format!("{}Resp", struct_ident);
|
||||
let mut error_s = "Box<dyn std::error::Error>".to_string();
|
||||
let mut error_s = "Box<dyn std::error::Error + Send + Sync>".to_string();
|
||||
|
||||
// Convert attr TokenStream -> proc_macro2 TokenStream so we can inspect/try parses safely
|
||||
let attr_ts: proc_macro2::TokenStream = proc_macro2::TokenStream::from(attr);
|
||||
// turn attr into TokenStream2
|
||||
let attr_ts: proc_macro2::TokenStream = attr.into();
|
||||
|
||||
if !attr_ts.is_empty() {
|
||||
// First try: parse as syn::Meta (preferred)
|
||||
match syn::parse2::<Meta>(attr_ts.clone()) {
|
||||
Ok(meta) => match meta {
|
||||
Meta::List(meta_list) => {
|
||||
// parse the inner tokens into name = value pairs
|
||||
if let Ok(meta) = syn::parse2::<Meta>(attr_ts.clone()) {
|
||||
if let Meta::List(list) = meta {
|
||||
let nested: Punctuated<MetaNameValue, Comma> =
|
||||
Punctuated::parse_terminated.parse2(meta_list.tokens)
|
||||
Punctuated::parse_terminated.parse2(list.tokens)
|
||||
.expect("failed to parse http attribute list");
|
||||
for nv in nested {
|
||||
if let Some(ident) = nv.path.get_ident() {
|
||||
let key = ident.to_string();
|
||||
// nv.value is an Expr in syn 2.x; expect Expr::Lit(Lit::Str)
|
||||
if let Expr::Lit(expr_lit) = nv.value {
|
||||
if let Lit::Str(litstr) = expr_lit.lit {
|
||||
let val = litstr.value();
|
||||
match key.as_str() {
|
||||
"method" => method_s = val,
|
||||
"url" => url_s = val,
|
||||
"response" => response_s = val,
|
||||
"error" => if !val.is_empty() { error_s = val },
|
||||
_ => {}
|
||||
for nv in nested {
|
||||
if let Some(ident) = nv.path.get_ident() {
|
||||
let key = ident.to_string();
|
||||
if key == "error" {
|
||||
match &nv.value {
|
||||
Expr::Lit(expr_lit) => {
|
||||
if let Lit::Str(ls) = &expr_lit.lit {
|
||||
error_s = ls.value();
|
||||
}
|
||||
}
|
||||
Expr::Path(p) => {
|
||||
error_s = quote!(#p).to_string();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Meta::NameValue(nv) => {
|
||||
// handle weird case like `#[http = "foo"]` (unlikely) — accept name-value if it has ident
|
||||
if let Some(ident) = nv.path.get_ident() {
|
||||
if let Expr::Lit(expr_lit) = nv.value {
|
||||
if let Lit::Str(litstr) = expr_lit.lit {
|
||||
let key = ident.to_string();
|
||||
let val = litstr.value();
|
||||
} else if let Expr::Lit(expr_lit) = &nv.value {
|
||||
if let Lit::Str(ls) = &expr_lit.lit {
|
||||
let val = ls.value();
|
||||
match key.as_str() {
|
||||
"method" => method_s = val,
|
||||
"url" => url_s = val,
|
||||
"live_url" => live_url_s = val,
|
||||
"sandbox_url" => sandbox_url_s = val,
|
||||
"response" => response_s = val,
|
||||
"error" => if !val.is_empty() { error_s = val },
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Meta::Path(_) => {
|
||||
// attribute present but without key/value — keep defaults
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
// Fallback: maybe the tokens are just a comma-separated `k = "v", ...` list without meta wrapper.
|
||||
if let Ok(nested) = Punctuated::<MetaNameValue, Comma>::parse_terminated.parse2(attr_ts.clone()) {
|
||||
for nv in nested {
|
||||
if let Some(ident) = nv.path.get_ident() {
|
||||
let key = ident.to_string();
|
||||
if let Expr::Lit(expr_lit) = nv.value {
|
||||
if let Lit::Str(litstr) = expr_lit.lit {
|
||||
let val = litstr.value();
|
||||
match key.as_str() {
|
||||
"method" => method_s = val,
|
||||
"url" => url_s = val,
|
||||
"response" => response_s = val,
|
||||
"error" => if !val.is_empty() { error_s = val },
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attach #[http_error_type = "..."] for build.rs introspection
|
||||
let error_lit = syn::LitStr::new(&error_s, Span::call_site());
|
||||
input.attrs.push(syn::parse_quote!(#[http_error_type = #error_lit]));
|
||||
|
||||
// Re-attach compact http attr (so your build.rs logic still sees it)
|
||||
let method_lit = syn::LitStr::new(&method_s, Span::call_site());
|
||||
let url_lit = syn::LitStr::new(&url_s, Span::call_site());
|
||||
let resp_lit = syn::LitStr::new(&response_s, Span::call_site());
|
||||
input.attrs.push(syn::parse_quote!(#[http(method = #method_lit, url = #url_lit, response = #resp_lit)]));
|
||||
|
||||
// Build query param snippets for lnk_p_* fields
|
||||
let mut qparam_snippets: Vec<proc_macro2::TokenStream> = Vec::new();
|
||||
// collect lnk_p_* -> query
|
||||
let mut qparam_snippets = Vec::new();
|
||||
if let Fields::Named(fields_named) = &input.fields {
|
||||
for field in &fields_named.named {
|
||||
if let Some(ident) = &field.ident {
|
||||
if let Some(key) = ident.to_string().strip_prefix("lnk_p_") {
|
||||
let key_lit = syn::LitStr::new(key, Span::call_site());
|
||||
if let Some(k) = ident.to_string().strip_prefix("lnk_p_") {
|
||||
let key_lit = syn::LitStr::new(k, Span::call_site());
|
||||
qparam_snippets.push(quote! {
|
||||
if let Some(val) = &self.#ident {
|
||||
query_params.push((#key_lit.to_string(), val.to_string()));
|
||||
@ -123,18 +88,25 @@ pub fn http(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
// Parse response & error into syn::Type so complex paths (crate::X) are allowed
|
||||
let response_ty: Type = syn::parse_str(&response_s).unwrap_or_else(|_| {
|
||||
syn::parse_str::<Type>("serde_json::Value").expect("fallback parse")
|
||||
});
|
||||
let error_ty: Type = syn::parse_str(&error_s).unwrap_or_else(|_| {
|
||||
syn::parse_str::<Type>("Box<dyn std::error::Error>").expect("fallback parse")
|
||||
});
|
||||
// parse response & error types
|
||||
let response_ty: Type = syn::parse_str(&response_s)
|
||||
.unwrap_or_else(|_| syn::parse_str("serde_json::Value").unwrap());
|
||||
let error_ty: Type = syn::parse_str(&error_s)
|
||||
.unwrap_or_else(|_| syn::parse_str("Box<dyn std::error::Error + Send + Sync>").unwrap());
|
||||
|
||||
let method_lit = syn::LitStr::new(&method_s, Span::call_site());
|
||||
let live_lit = syn::LitStr::new(&live_url_s, Span::call_site());
|
||||
let sandbox_lit = syn::LitStr::new(&sandbox_url_s, Span::call_site());
|
||||
|
||||
// Build the impl
|
||||
let expanded = quote! {
|
||||
#input
|
||||
|
||||
impl http_core::HasHttp for #struct_ident {
|
||||
fn http_methods() -> &'static [&'static str] { &[#method_lit] }
|
||||
fn live_url() -> &'static str { #live_lit }
|
||||
fn sandbox_url() -> &'static str { #sandbox_lit }
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl http_core::Queryable for #struct_ident {
|
||||
type R = #response_ty;
|
||||
@ -148,12 +120,10 @@ pub fn http(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
headers: Option<Vec<(&str, &str)>>,
|
||||
) -> Result<Self::R, Self::E> {
|
||||
use awc::Client;
|
||||
use urlencoding::encode;
|
||||
use http_core::HasHttp;
|
||||
use urlencoding::encode;
|
||||
|
||||
let mut query_params: Vec<(String,String)> = Vec::new();
|
||||
|
||||
// expand lnk_p_* fields
|
||||
let mut query_params: Vec<(String, String)> = Vec::new();
|
||||
#(#qparam_snippets)*
|
||||
|
||||
let mut url = if let Some(u) = override_url {
|
||||
@ -175,24 +145,22 @@ pub fn http(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
|
||||
let method = method_override.unwrap_or(#method_lit);
|
||||
let client = Client::default();
|
||||
let mut request = match method {
|
||||
"GET" => client.get(url.clone()),
|
||||
"POST" => client.post(url.clone()),
|
||||
"PUT" => client.put(url.clone()),
|
||||
let mut req = match method {
|
||||
"GET" => client.get(url.clone()),
|
||||
"POST" => client.post(url.clone()),
|
||||
"PUT" => client.put(url.clone()),
|
||||
"DELETE" => client.delete(url.clone()),
|
||||
"PATCH" => client.patch(url.clone()),
|
||||
_ => client.get(url.clone()),
|
||||
"PATCH" => client.patch(url.clone()),
|
||||
_ => client.get(url.clone()),
|
||||
};
|
||||
|
||||
if let Some(hdrs) = headers {
|
||||
for (k,v) in hdrs {
|
||||
request = request.append_header((k, v));
|
||||
}
|
||||
if let Some(hs) = headers {
|
||||
for (k, v) in hs { req = req.append_header((k, v)); }
|
||||
}
|
||||
|
||||
let response = request.send().await.map_err(Into::into)?;
|
||||
let bytes = response.body().await.map_err(Into::into)?;
|
||||
let parsed: Self::R = serde_json::from_slice(&bytes).map_err(Into::into)?;
|
||||
let resp = req.send().await.map_err(Into::into)?;
|
||||
let body = resp.body().await.map_err(Into::into)?;
|
||||
let parsed: Self::R = serde_json::from_slice(&body).map_err(Into::into)?;
|
||||
Ok(parsed)
|
||||
}
|
||||
}
|
||||
@ -201,17 +169,18 @@ pub fn http(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
/// CLI generator macro (keeps your existing CLI structure)
|
||||
#[proc_macro_attribute]
|
||||
pub fn alpaca_cli(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let input_enum = parse_macro_input!(item as ItemEnum);
|
||||
let top_enum_ident = &input_enum.ident;
|
||||
let top_variants = &input_enum.variants;
|
||||
|
||||
// Build outer match arms
|
||||
// Build outer match arms same as your previous implementation
|
||||
let match_arms: Vec<_> = top_variants.iter().map(|variant| {
|
||||
let variant_ident = &variant.ident;
|
||||
|
||||
// Expecting tuple variants like Alpaca(AlpacaCmd)
|
||||
// Expect tuple variant like Alpaca(AlpacaCmd)
|
||||
let inner_type = match &variant.fields {
|
||||
Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
|
||||
match &fields.unnamed.first().unwrap().ty {
|
||||
@ -239,17 +208,16 @@ pub fn alpaca_cli(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let client = Arc::new(awc::Client::default());
|
||||
let keys = Arc::new(crate::load_api_keys()?);
|
||||
|
||||
// Spawn all queries as async tasks
|
||||
// Spawn tasks for each query and await
|
||||
let mut handles = Vec::new();
|
||||
for q in queries {
|
||||
let client = Arc::clone(&client);
|
||||
let keys = Arc::clone(&keys);
|
||||
handles.push(tokio::spawn(async move {
|
||||
q.send_all(&client, &keys).await
|
||||
q.send_all(&client, &keys, None, false, None).await
|
||||
}));
|
||||
}
|
||||
|
||||
// Await all results and propagate first error (if any)
|
||||
for h in handles {
|
||||
h.await??;
|
||||
}
|
||||
@ -257,14 +225,13 @@ pub fn alpaca_cli(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
other => {
|
||||
let client = awc::Client::default();
|
||||
let keys = crate::load_api_keys()?;
|
||||
other.send_all(&client, &keys).await?;
|
||||
other.send_all(&client, &keys, None, false, None).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
|
||||
// Generate the final code
|
||||
let expanded = quote! {
|
||||
use clap::Parser;
|
||||
use std::io::Read;
|
||||
@ -284,3 +251,4 @@ pub fn alpaca_cli(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user