ploidy_codegen_rust/
client.rs1use ploidy_core::codegen::IntoCode;
2use proc_macro2::TokenStream;
3use quote::{ToTokens, TokenStreamExt, quote};
4
5use super::{
6 cfg::CfgFeature,
7 graph::CodegenGraph,
8 naming::{CargoFeature, CodegenIdentUsage},
9};
10
11#[derive(Clone, Copy, Debug)]
13pub struct CodegenClientModule<'a> {
14 graph: &'a CodegenGraph<'a>,
15 features: &'a [&'a CargoFeature],
16}
17
18impl<'a> CodegenClientModule<'a> {
19 pub fn new(graph: &'a CodegenGraph<'a>, features: &'a [&'a CargoFeature]) -> Self {
20 Self { graph, features }
21 }
22}
23
24impl ToTokens for CodegenClientModule<'_> {
25 fn to_tokens(&self, tokens: &mut TokenStream) {
26 let mods = self.features.iter().map(|feature| {
27 let cfg = CfgFeature::for_resource_module(feature);
28 let mod_name = CodegenIdentUsage::Module(feature.as_ident());
29 quote! {
30 #cfg
31 pub mod #mod_name;
32 }
33 });
34
35 let client_doc = {
36 let info = self.graph.info();
37 format!("API client for {} (version {})", info.title, info.version)
38 };
39
40 tokens.append_all(quote! {
41 #[doc = #client_doc]
42 #[derive(Clone, Debug)]
43 pub struct Client {
44 client: ::ploidy_util::reqwest::Client,
45 headers: ::ploidy_util::http::HeaderMap,
46 base_url: ::ploidy_util::url::Url,
47 }
48
49 impl Client {
50 pub fn new(base_url: impl AsRef<str>) -> Result<Self, crate::error::Error> {
52 Ok(Self::with_reqwest_client(
53 ::ploidy_util::reqwest::Client::new(),
54 base_url.as_ref().parse()?,
55 ))
56 }
57
58 pub fn with_reqwest_client(
59 client: crate::util::reqwest::Client,
60 base_url: crate::util::url::Url,
61 ) -> Self {
62 Self {
63 client,
64 headers: ::ploidy_util::http::HeaderMap::new(),
65 base_url,
66 }
67 }
68
69 pub fn with_header<K, V>(mut self, name: K, value: V) -> Result<Self, crate::error::Error>
71 where
72 K: TryInto<crate::util::http::HeaderName>,
73 V: TryInto<crate::util::http::HeaderValue>,
74 K::Error: Into<crate::util::http::Error>,
75 V::Error: Into<crate::util::http::Error>,
76 {
77 let name = name
78 .try_into()
79 .map_err(|err| crate::error::Error::BadHeaderName(err.into()))?;
80 let value = value
81 .try_into()
82 .map_err(|err| crate::error::Error::BadHeaderValue(name.clone(), err.into()))?;
83 self.headers.insert(name, value);
84 Ok(Self {
85 client: self.client,
86 headers: self.headers,
87 base_url: self.base_url,
88 })
89 }
90
91 pub fn with_sensitive_header<K, V>(self, name: K, value: V) -> Result<Self, crate::error::Error>
104 where
105 K: TryInto<crate::util::http::HeaderName>,
106 V: TryInto<crate::util::http::HeaderValue>,
107 K::Error: Into<crate::util::http::Error>,
108 V::Error: Into<crate::util::http::Error>,
109 {
110 let name = name
111 .try_into()
112 .map_err(|err| crate::error::Error::BadHeaderName(err.into()))?;
113 let mut value: ::ploidy_util::http::HeaderValue = value
114 .try_into()
115 .map_err(|err| crate::error::Error::BadHeaderValue(name.clone(), err.into()))?;
116 value.set_sensitive(true);
117 self.with_header(name, value)
118 }
119
120 pub fn with_user_agent<V>(self, value: V) -> Result<Self, crate::error::Error>
121 where
122 V: TryInto<crate::util::http::HeaderValue>,
123 V::Error: Into<crate::util::http::Error>,
124 {
125 self.with_header(::ploidy_util::http::header::USER_AGENT, value)
126 }
127
128 pub fn request(
135 &self,
136 method: crate::util::reqwest::Method,
137 path: &str,
138 ) -> crate::util::reqwest::RequestBuilder {
139 let mut url = self.base_url.clone();
140 let _ = url
141 .path_segments_mut()
142 .map(|mut segments| {
143 segments.pop_if_empty().extend(path.split('/'));
144 });
145 self.client
146 .request(method, url)
147 .headers(self.headers.clone())
148 }
149 }
150
151 #(#mods)*
152 });
153 }
154}
155
156impl IntoCode for CodegenClientModule<'_> {
157 type Code = (&'static str, TokenStream);
158
159 fn into_code(self) -> Self::Code {
160 ("src/client/mod.rs", self.into_token_stream())
161 }
162}