ud
This commit is contained in:
97
Cargo.lock
generated
97
Cargo.lock
generated
@ -21,9 +21,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "3.11.0"
|
version = "3.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44dfe5c9e0004c623edc65391dfd51daa201e7e30ebd9c9bedf873048ec32bc2"
|
checksum = "44cceded2fb55f3c4b67068fa64962e2ca59614edc5b03167de9ff82ae803da0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-codec",
|
"actix-codec",
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
@ -60,9 +60,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-rt"
|
name = "actix-rt"
|
||||||
version = "2.10.0"
|
version = "2.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208"
|
checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -210,9 +210,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.9.2"
|
version = "2.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
|
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
@ -261,10 +261,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.33"
|
version = "1.2.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
|
checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"find-msvc-tools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
"shlex",
|
"shlex",
|
||||||
@ -317,9 +318,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.4.0"
|
version = "0.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
|
checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
@ -370,6 +371,12 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "find-msvc-tools"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
@ -394,9 +401,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.1"
|
version = "1.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
|
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
@ -451,7 +458,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi",
|
"r-efi",
|
||||||
"wasi 0.14.2+wasi-0.2.4",
|
"wasi 0.14.4+wasi-0.2.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -549,9 +556,9 @@ checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.10.0"
|
version = "2.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
|
checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@ -559,9 +566,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-uring"
|
name = "io-uring"
|
||||||
version = "0.7.9"
|
version = "0.7.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
|
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@ -576,9 +583,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.33"
|
version = "0.1.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
|
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"libc",
|
"libc",
|
||||||
@ -625,9 +632,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.27"
|
version = "0.4.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
@ -707,9 +714,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.1"
|
version = "2.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
@ -938,12 +945,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.41"
|
version = "0.3.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
|
checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deranged",
|
"deranged",
|
||||||
"itoa",
|
|
||||||
"num-conv",
|
"num-conv",
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
"serde",
|
"serde",
|
||||||
@ -953,15 +959,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-core"
|
name = "time-core"
|
||||||
version = "0.1.4"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
|
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-macros"
|
name = "time-macros"
|
||||||
version = "0.2.22"
|
version = "0.2.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
|
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-conv",
|
"num-conv",
|
||||||
"time-core",
|
"time-core",
|
||||||
@ -1096,11 +1102,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.14.2+wasi-0.2.4"
|
version = "0.14.4+wasi-0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen-rt",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1178,33 +1184,30 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.7.12"
|
version = "0.7.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
|
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen-rt"
|
name = "wit-bindgen"
|
||||||
version = "0.39.0"
|
version = "0.45.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36"
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.26"
|
version = "0.8.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
|
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.8.26"
|
version = "0.8.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1231,9 +1234,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zstd-sys"
|
name = "zstd-sys"
|
||||||
version = "2.0.15+zstd.1.5.7"
|
version = "2.0.16+zstd.1.5.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
|
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
|
|||||||
164
src/lib.rs
164
src/lib.rs
@ -5,12 +5,12 @@ use quote::format_ident;
|
|||||||
use http_core::{Queryable, ApiDispatch, HasHttp, Keys};
|
use http_core::{Queryable, ApiDispatch, HasHttp, Keys};
|
||||||
|
|
||||||
#[proc_macro_derive(HttpRequest, attributes(http_response, http_error_type))]
|
#[proc_macro_derive(HttpRequest, attributes(http_response, http_error_type))]
|
||||||
pub fn derive_http_get_request(input: TokenStream) -> TokenStream {
|
pub fn derive_http_request(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
let query_name = &input.ident;
|
let query_name = &input.ident;
|
||||||
let query_name_str = query_name.to_string();
|
let query_name_str = query_name.to_string();
|
||||||
|
|
||||||
// Parse optional #[http_response = "..."] attribute
|
// Parse optional #[http_response = "..."]
|
||||||
let mut response_name_opt: Option<String> = None;
|
let mut response_name_opt: Option<String> = None;
|
||||||
for attr in &input.attrs {
|
for attr in &input.attrs {
|
||||||
if attr.path().is_ident("http_response") {
|
if attr.path().is_ident("http_response") {
|
||||||
@ -22,15 +22,14 @@ pub fn derive_http_get_request(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}).unwrap_or_else(|e| panic!("Error parsing http_response attribute: {}", e));
|
}).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let response_name_str = response_name_opt.unwrap_or_else(|| format!("{}Resp", query_name_str));
|
let response_name_str = response_name_opt.unwrap_or_else(|| format!("{}Resp", query_name_str));
|
||||||
let response_name = format_ident!("{}", response_name_str);
|
let response_name = format_ident!("{}", response_name_str);
|
||||||
|
|
||||||
// Parse optional #[http_error_type = "..."] attribute (default to `E`)
|
// Parse optional #[http_error_type = "..."] (default to Box<dyn Error>)
|
||||||
let mut error_type = syn::Path::from(syn::Ident::new("E", proc_macro2::Span::call_site()));
|
let mut error_type = syn::parse_str::<syn::Path>("Box<dyn std::error::Error>").unwrap();
|
||||||
for attr in &input.attrs {
|
for attr in &input.attrs {
|
||||||
if attr.path().is_ident("http_error_type") {
|
if attr.path().is_ident("http_error_type") {
|
||||||
attr.parse_nested_meta(|meta| {
|
attr.parse_nested_meta(|meta| {
|
||||||
@ -41,11 +40,11 @@ pub fn derive_http_get_request(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}).unwrap_or_else(|e| panic!("Error parsing http_error_type attribute: {}", e));
|
}).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect query parameters from lnk_p_* fields
|
// Collect query parameters from fields prefixed with lnk_p_
|
||||||
let query_param_code = if let Data::Struct(data_struct) = &input.data {
|
let query_param_code = if let Data::Struct(data_struct) = &input.data {
|
||||||
if let Fields::Named(fields_named) = &data_struct.fields {
|
if let Fields::Named(fields_named) = &data_struct.fields {
|
||||||
fields_named.named.iter().filter_map(|field| {
|
fields_named.named.iter().filter_map(|field| {
|
||||||
@ -58,51 +57,62 @@ pub fn derive_http_get_request(input: TokenStream) -> TokenStream {
|
|||||||
query_params.push((#key.to_string(), val.to_string()));
|
query_params.push((#key.to_string(), val.to_string()));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else { None }
|
||||||
None
|
|
||||||
}
|
|
||||||
}).collect::<Vec<_>>()
|
}).collect::<Vec<_>>()
|
||||||
} else {
|
} else { Vec::new() }
|
||||||
Vec::new()
|
} else { Vec::new() };
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Vec::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Queryable for #query_name {
|
impl http_core::Queryable for #query_name {
|
||||||
type R = #response_name;
|
type R = #response_name;
|
||||||
|
type E = #error_type;
|
||||||
|
|
||||||
async fn send(
|
async fn send(
|
||||||
&self,
|
&self,
|
||||||
base_url: &str,
|
override_url: Option<&str>,
|
||||||
|
sandbox: bool,
|
||||||
|
method_override: Option<&str>,
|
||||||
headers: Option<Vec<(&str, &str)>>,
|
headers: Option<Vec<(&str, &str)>>,
|
||||||
) -> Result<Self::R, #error_type> {
|
) -> Result<Self::R, Self::E> {
|
||||||
use awc::Client;
|
use awc::Client;
|
||||||
use urlencoding::encode;
|
use urlencoding::encode;
|
||||||
|
use http_core::HasHttp;
|
||||||
|
|
||||||
|
// collect lnk_p_* query params
|
||||||
let mut query_params: Vec<(String, String)> = Vec::new();
|
let mut query_params: Vec<(String, String)> = Vec::new();
|
||||||
#(#query_param_code)*
|
#(#query_param_code)*
|
||||||
|
|
||||||
let mut url = base_url.to_string();
|
// pick URL
|
||||||
|
let mut url = if let Some(u) = override_url {
|
||||||
|
u.to_string()
|
||||||
|
} else if sandbox {
|
||||||
|
<Self as HasHttp>::sandbox_url().to_string()
|
||||||
|
} else {
|
||||||
|
<Self as HasHttp>::live_url().to_string()
|
||||||
|
};
|
||||||
|
|
||||||
if !query_params.is_empty() {
|
if !query_params.is_empty() {
|
||||||
let mut query_string = String::new();
|
let query_string = query_params.into_iter()
|
||||||
let mut first = true;
|
.map(|(k,v)| format!("{}={}", k, encode(&v)))
|
||||||
for (k, v) in &query_params {
|
.collect::<Vec<_>>()
|
||||||
if !first {
|
.join("&");
|
||||||
query_string.push('&');
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
query_string.push_str(&format!("{}={}", k, encode(v)));
|
|
||||||
}
|
|
||||||
url.push('?');
|
url.push('?');
|
||||||
url.push_str(&query_string);
|
url.push_str(&query_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// choose method
|
||||||
let client = Client::default();
|
let client = Client::default();
|
||||||
let mut request = client.get(url);
|
let mut request = match method_override.unwrap_or("GET") {
|
||||||
|
"GET" => client.get(url),
|
||||||
|
"POST" => client.post(url),
|
||||||
|
"PUT" => client.put(url),
|
||||||
|
"DELETE" => client.delete(url),
|
||||||
|
"PATCH" => client.patch(url),
|
||||||
|
m => panic!("Unsupported method override: {}", m),
|
||||||
|
};
|
||||||
|
|
||||||
|
// add headers
|
||||||
if let Some(hdrs) = headers {
|
if let Some(hdrs) = headers {
|
||||||
for (k, v) in hdrs {
|
for (k, v) in hdrs {
|
||||||
request = request.append_header((k, v));
|
request = request.append_header((k, v));
|
||||||
@ -120,7 +130,6 @@ pub fn derive_http_get_request(input: TokenStream) -> TokenStream {
|
|||||||
TokenStream::from(expanded)
|
TokenStream::from(expanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn alpaca_cli(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn alpaca_cli(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let input_enum = parse_macro_input!(item as ItemEnum);
|
let input_enum = parse_macro_input!(item as ItemEnum);
|
||||||
@ -159,31 +168,19 @@ pub fn alpaca_cli(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
let client = Arc::new(awc::Client::default());
|
let client = Arc::new(awc::Client::default());
|
||||||
let keys = Arc::new(crate::load_api_keys()?);
|
let keys = Arc::new(crate::load_api_keys()?);
|
||||||
|
|
||||||
const THREADS: usize = 4;
|
// Spawn all queries as async tasks
|
||||||
let total = queries.len();
|
|
||||||
let per_thread = std::cmp::max(1, total / THREADS);
|
|
||||||
let shared_queries = Arc::new(queries);
|
|
||||||
|
|
||||||
let mut handles = Vec::new();
|
let mut handles = Vec::new();
|
||||||
for i in 0..THREADS {
|
for q in queries {
|
||||||
let queries = Arc::clone(&shared_queries);
|
|
||||||
let client = Arc::clone(&client);
|
let client = Arc::clone(&client);
|
||||||
let keys = Arc::clone(&keys);
|
let keys = Arc::clone(&keys);
|
||||||
let start = i * per_thread;
|
handles.push(tokio::spawn(async move {
|
||||||
let end = if i == THREADS - 1 { total } else { start + per_thread };
|
q.send_all(&client, &keys).await
|
||||||
|
}));
|
||||||
let handle = std::thread::spawn(move || {
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
||||||
for q in &queries[start..end] {
|
|
||||||
rt.block_on(q.send_all(&client, &keys)).unwrap();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
handles.push(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Await all results and propagate first error (if any)
|
||||||
for h in handles {
|
for h in handles {
|
||||||
h.join().expect("Thread panicked");
|
h.await??;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
@ -212,71 +209,6 @@ pub fn alpaca_cli(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trait for dispatching API calls
|
|
||||||
pub trait ApiDispatch {
|
|
||||||
fn send_all(
|
|
||||||
&self,
|
|
||||||
client: &awc::Client,
|
|
||||||
keys: &std::collections::HashMap<String, crate::Keys>,
|
|
||||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), Box<dyn std::error::Error>>> + Send>>;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TokenStream::from(expanded)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn api_dispatch(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|
||||||
let input = parse_macro_input!(item as syn::ItemEnum);
|
|
||||||
let enum_ident = &input.ident;
|
|
||||||
|
|
||||||
// Parse attribute input: input = "MyQuery"
|
|
||||||
let meta_args = attr.to_string();
|
|
||||||
let input_type: syn::Ident = {
|
|
||||||
let cleaned = meta_args.trim().replace("input", "").replace('=', "").replace('"', "").trim().to_string();
|
|
||||||
syn::Ident::new(&cleaned, proc_macro2::Span::call_site())
|
|
||||||
};
|
|
||||||
|
|
||||||
let expanded = quote! {
|
|
||||||
#input
|
|
||||||
|
|
||||||
impl ApiDispatch for #enum_ident {
|
|
||||||
fn send_all(
|
|
||||||
&self,
|
|
||||||
client: &awc::Client,
|
|
||||||
keys: &std::collections::HashMap<String, crate::Keys>,
|
|
||||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), Box<dyn std::error::Error>>> + Send>> {
|
|
||||||
Box::pin(async move {
|
|
||||||
match self {
|
|
||||||
#enum_ident::Single { query } => {
|
|
||||||
let parsed: #input_type = serde_json::from_str(query)?;
|
|
||||||
parsed.send(client, keys).await?;
|
|
||||||
}
|
|
||||||
#enum_ident::Bulk { input } => {
|
|
||||||
let json = if let Some(raw) = input {
|
|
||||||
if std::path::Path::new(&raw).exists() {
|
|
||||||
std::fs::read_to_string(raw)?
|
|
||||||
} else {
|
|
||||||
raw.clone()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
use std::io::Read;
|
|
||||||
let mut buf = String::new();
|
|
||||||
std::io::stdin().read_to_string(&mut buf)?;
|
|
||||||
buf
|
|
||||||
};
|
|
||||||
|
|
||||||
let items: Vec<#input_type> = serde_json::from_str(&json)?;
|
|
||||||
for item in items {
|
|
||||||
item.send(client, keys).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TokenStream::from(expanded)
|
TokenStream::from(expanded)
|
||||||
|
|||||||
Reference in New Issue
Block a user