qcs_api_client_openapi/apis/
mod.rs1use std::error;
16use std::fmt;
17
18use qcs_dependencies_client::reqwest;
19#[cfg(feature = "tracing-opentelemetry")]
20use qcs_dependencies_client::reqwest_middleware;
21
22#[derive(Debug, Clone)]
23pub struct ResponseContent<T> {
24 pub status: reqwest::StatusCode,
25 pub content: String,
26 pub entity: Option<T>,
27 pub retry_delay: Option<std::time::Duration>,
28}
29
30#[derive(Debug)]
31pub enum Error<T> {
32 Reqwest(reqwest::Error),
33 Serde(serde_path_to_error::Error<serde_json::Error>),
34 Io(std::io::Error),
35 QcsToken(crate::common::configuration::TokenError),
36 ResponseError(ResponseContent<T>),
37 InvalidContentType {
38 content_type: String,
39 return_type: &'static str,
40 },
41 #[cfg(feature = "tracing-opentelemetry")]
42 ReqwestMiddleware(anyhow::Error),
43}
44
45impl<T> Error<T> {
46 pub fn status_code(&self) -> Option<reqwest::StatusCode> {
47 match self {
48 Self::ResponseError(err) => Some(err.status),
49 _ => None,
50 }
51 }
52}
53
54impl<T> fmt::Display for Error<T> {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 let (module, e) = match self {
57 Error::Reqwest(e) => ("reqwest", e.to_string()),
58 Error::Serde(e) => ("serde", e.to_string()),
59 Error::Io(e) => ("IO", e.to_string()),
60 Error::QcsToken(e) => ("refresh_qcs_token", e.to_string()),
61 Error::ResponseError(e) => (
62 "response",
63 format!("status code {}: {}", e.status, e.content),
64 ),
65 Error::InvalidContentType {
66 content_type,
67 return_type,
68 } => (
69 "api",
70 format!(
71 "received {content_type} content type response that cannot be converted to `{return_type}`"
72 ),
73 ),
74 #[cfg(feature = "tracing-opentelemetry")]
75 Error::ReqwestMiddleware(e) => ("reqwest-middleware", e.to_string()),
76 };
77 write!(f, "error in {}: {}", module, e)
78 }
79}
80
81impl<T: fmt::Debug> error::Error for Error<T> {
82 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
83 Some(match self {
84 Error::Reqwest(e) => e,
85 Error::Serde(e) => e,
86 Error::Io(e) => e,
87 Error::QcsToken(e) => e,
88 #[cfg(feature = "tracing-opentelemetry")]
89 Error::ReqwestMiddleware(e) => e.source()?,
90 Error::InvalidContentType { .. } => return None,
91 Error::ResponseError(_) => return None,
92 })
93 }
94}
95
96impl<T> From<reqwest::Error> for Error<T> {
97 fn from(e: reqwest::Error) -> Self {
98 Error::Reqwest(e)
99 }
100}
101
102#[cfg(feature = "tracing-opentelemetry")]
103impl<T> From<reqwest_middleware::Error> for Error<T> {
104 fn from(e: reqwest_middleware::Error) -> Self {
105 match e {
106 reqwest_middleware::Error::Reqwest(e) => Error::Reqwest(e),
107 reqwest_middleware::Error::Middleware(e) => Error::ReqwestMiddleware(e),
108 }
109 }
110}
111
112impl<T> From<serde_path_to_error::Error<serde_json::Error>> for Error<T> {
113 fn from(e: serde_path_to_error::Error<serde_json::Error>) -> Self {
114 Error::Serde(e)
115 }
116}
117
118impl<T> From<std::io::Error> for Error<T> {
119 fn from(e: std::io::Error) -> Self {
120 Error::Io(e)
121 }
122}
123
124impl<T> From<crate::common::configuration::TokenError> for Error<T> {
125 fn from(e: crate::common::configuration::TokenError) -> Self {
126 Error::QcsToken(e)
127 }
128}
129
130pub fn urlencode<T: AsRef<str>>(s: T) -> String {
131 ::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect()
132}
133
134pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> {
135 if let serde_json::Value::Object(object) = value {
136 let mut params = vec![];
137
138 for (key, value) in object {
139 match value {
140 serde_json::Value::Object(_) => params.append(&mut parse_deep_object(
141 &format!("{}[{}]", prefix, key),
142 value,
143 )),
144 serde_json::Value::Array(array) => {
145 for (i, value) in array.iter().enumerate() {
146 params.append(&mut parse_deep_object(
147 &format!("{}[{}][{}]", prefix, key, i),
148 value,
149 ));
150 }
151 }
152 serde_json::Value::String(s) => {
153 params.push((format!("{}[{}]", prefix, key), s.clone()))
154 }
155 _ => params.push((format!("{}[{}]", prefix, key), value.to_string())),
156 }
157 }
158
159 return params;
160 }
161
162 unimplemented!("Only objects are supported with style=deepObject, got: {value:#}")
163}
164
165#[allow(dead_code)]
168enum ContentType {
169 Json,
170 Text,
171 Unsupported(String),
172}
173
174impl From<&str> for ContentType {
175 fn from(content_type: &str) -> Self {
176 if content_type.starts_with("application") && content_type.contains("json") {
177 Self::Json
178 } else if content_type.starts_with("text/plain") {
179 Self::Text
180 } else {
181 Self::Unsupported(content_type.to_string())
182 }
183 }
184}
185
186pub mod account_api;
187pub mod authentication_api;
188pub mod client_applications_api;
189pub mod default_api;
190pub mod endpoints_api;
191pub mod engagements_api;
192pub mod quantum_processors_api;
193pub mod reservations_api;
194
195pub mod configuration;