Skip to main content

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}