ploidy_codegen_rust/
client.rs1use itertools::Itertools;
2use ploidy_core::codegen::IntoCode;
3use proc_macro2::TokenStream;
4use quote::{ToTokens, TokenStreamExt, quote};
5
6use super::{graph::CodegenGraph, naming::CodegenIdent};
7
8#[derive(Clone, Copy, Debug)]
10pub struct CodegenClientModule<'a> {
11 graph: &'a CodegenGraph<'a>,
12 resources: &'a [&'a str],
13}
14
15impl<'a> CodegenClientModule<'a> {
16 pub fn new(graph: &'a CodegenGraph<'a>, resources: &'a [&'a str]) -> Self {
17 Self { graph, resources }
18 }
19}
20
21impl ToTokens for CodegenClientModule<'_> {
22 fn to_tokens(&self, tokens: &mut TokenStream) {
23 let mods = self
24 .resources
25 .iter()
26 .map(|resource| {
27 let mod_name = CodegenIdent::Module(resource);
28 quote! {
29 #[cfg(feature = #resource)]
30 pub mod #mod_name;
31 }
32 })
33 .collect_vec();
34
35 let client_doc = {
36 let info = self.graph.spec().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: ::reqwest::Client,
45 headers: ::http::HeaderMap,
46 base_url: ::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 ::reqwest::Client::new(),
54 base_url.as_ref().parse()?,
55 ))
56 }
57
58 pub fn with_reqwest_client(client: ::reqwest::Client, base_url: ::url::Url) -> Self {
59 Self {
60 client,
61 headers: ::http::HeaderMap::new(),
62 base_url,
63 }
64 }
65
66 pub fn with_header<K, V>(mut self, name: K, value: V) -> Result<Self, crate::error::Error>
68 where
69 K: TryInto<::http::HeaderName>,
70 V: TryInto<::http::HeaderValue>,
71 K::Error: Into<::http::Error>,
72 V::Error: Into<::http::Error>,
73 {
74 let name = name
75 .try_into()
76 .map_err(|err| crate::error::Error::BadHeaderName(err.into()))?;
77 let value = value
78 .try_into()
79 .map_err(|err| crate::error::Error::BadHeaderValue(name.clone(), err.into()))?;
80 self.headers.insert(name, value);
81 Ok(Self {
82 client: self.client,
83 headers: self.headers,
84 base_url: self.base_url,
85 })
86 }
87
88 pub fn with_sensitive_header<K, V>(self, name: K, value: V) -> Result<Self, crate::error::Error>
101 where
102 K: TryInto<::http::HeaderName>,
103 V: TryInto<::http::HeaderValue>,
104 K::Error: Into<::http::Error>,
105 V::Error: Into<::http::Error>,
106 {
107 let name = name
108 .try_into()
109 .map_err(|err| crate::error::Error::BadHeaderName(err.into()))?;
110 let mut value: ::http::HeaderValue = value
111 .try_into()
112 .map_err(|err| crate::error::Error::BadHeaderValue(name.clone(), err.into()))?;
113 value.set_sensitive(true);
114 self.with_header(name, value)
115 }
116
117 pub fn with_user_agent<V>(self, value: V) -> Result<Self, crate::error::Error>
118 where
119 V: TryInto<::http::HeaderValue>,
120 V::Error: Into<::http::Error>,
121 {
122 self.with_header(::http::header::USER_AGENT, value)
123 }
124 }
125
126 #(#mods)*
127 });
128 }
129}
130
131impl IntoCode for CodegenClientModule<'_> {
132 type Code = (&'static str, TokenStream);
133
134 fn into_code(self) -> Self::Code {
135 ("src/client/mod.rs", self.into_token_stream())
136 }
137}