everymap_core/client/macros.rs
1//! Declarative macro for generating provider client wrapper boilerplate.
2
3/// Generates a provider client struct that wraps `everymap_core::client::ProviderClient`.
4///
5/// Expands to a public struct holding a private `inner: ProviderClient`, a private
6/// `PROVIDER_NAME` const, and the standard methods shared by every provider client
7/// wrapper: `new`, `with_client_builder`, `set_verbose`, `is_verbose`,
8/// `build_request`, `request`, and `request_json`.
9///
10/// Provider-specific methods (e.g. Radar's `post_json`) stay outside the macro as
11/// inherent methods on the generated struct in the same module, accessing `inner`
12/// directly.
13///
14/// Usage:
15/// ```ignore
16/// everymap_core::provider_client! {
17/// /// The shared HTTP client for Google Maps APIs.
18/// GoogleClient, "google"
19/// }
20/// ```
21#[macro_export]
22macro_rules! provider_client {
23 (
24 $(#[$struct_documentation:meta])*
25 $struct_name:ident, $provider_name:literal
26 ) => {
27 $(#[$struct_documentation])*
28 pub struct $struct_name {
29 inner: $crate::client::ProviderClient,
30 }
31
32 const PROVIDER_NAME: &str = $provider_name;
33
34 impl $struct_name {
35 #[doc = concat!("Creates a new `", stringify!($struct_name), "` with the given authentication provider.")]
36 pub fn new(
37 auth_provider: ::std::sync::Arc<dyn $crate::auth::AuthProvider>,
38 ) -> Self {
39 Self {
40 inner: $crate::client::ProviderClient::new(
41 auth_provider,
42 PROVIDER_NAME,
43 ),
44 }
45 }
46
47 #[doc = concat!("Creates a `", stringify!($struct_name), "` with a custom `reqwest::Client` configuration.")]
48 pub fn with_client_builder(
49 builder: ::reqwest::ClientBuilder,
50 auth_provider: ::std::sync::Arc<dyn $crate::auth::AuthProvider>,
51 ) -> $crate::error::EveryMapResult<Self> {
52 Ok(Self {
53 inner: $crate::client::ProviderClient::with_client_builder(
54 builder,
55 auth_provider,
56 PROVIDER_NAME,
57 )?,
58 })
59 }
60
61 /// Enable or disable verbose output (request/response logging to stderr).
62 pub fn set_verbose(&mut self, verbose: bool) {
63 self.inner.set_verbose(verbose);
64 }
65
66 /// Whether verbose mode is enabled.
67 pub fn is_verbose(&self) -> bool {
68 self.inner.is_verbose()
69 }
70
71 /// Builds a request to the given full URL with the specified HTTP method.
72 pub fn build_request(
73 &self,
74 method: ::reqwest::Method,
75 url: &str,
76 ) -> ::reqwest::RequestBuilder {
77 self.inner.build_request(method, url)
78 }
79
80 /// Sends a request, applying authentication first.
81 pub async fn request(
82 &self,
83 builder: ::reqwest::RequestBuilder,
84 ) -> $crate::error::EveryMapResult<::reqwest::Response> {
85 self.inner.request(builder).await
86 }
87
88 /// Sends a request and deserializes the JSON response into `T`.
89 pub async fn request_json<T: ::serde::de::DeserializeOwned>(
90 &self,
91 builder: ::reqwest::RequestBuilder,
92 ) -> $crate::error::EveryMapResult<T> {
93 self.inner.request_json(builder).await
94 }
95 }
96 };
97}