qcs_api_client_openapi/apis/
quantum_processors_api.rs

1// Copyright 2022 Rigetti Computing
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*
16 * Rigetti QCS API
17 *
18 * # Introduction  This is the documentation for the Rigetti QCS HTTP API.  You can find out more about Rigetti at [https://rigetti.com](https://rigetti.com), and also interact with QCS via the web at [https://qcs.rigetti.com](https://qcs.rigetti.com).  This API is documented in **OpenAPI format** and so is compatible with the dozens of language-specific client generators available [here](https://github.com/OpenAPITools/openapi-generator) and elsewhere on the web.  # Principles  This API follows REST design principles where appropriate, and otherwise an HTTP RPC paradigm. We adhere to the Google [API Improvement Proposals](https://google.aip.dev/general) where reasonable to provide a consistent, intuitive developer experience. HTTP response codes match their specifications, and error messages fit a common format.  # Authentication  All access to the QCS API requires OAuth2 authentication provided by Okta. You can request access [here](https://www.rigetti.com/get-quantum). Once you have a user account, you can download your access token from QCS [here](https://qcs.rigetti.com/auth/token).   That access token is valid for 24 hours after issuance. The value of `access_token` within the JSON file is the token used for authentication (don't use the entire JSON file).  Authenticate requests using the `Authorization` header and a `Bearer` prefix:  ``` curl --header \"Authorization: Bearer eyJraW...Iow\" ```  # Quantum Processor Access  Access to the quantum processors themselves is not yet provided directly by this HTTP API, but is instead performed over ZeroMQ/[rpcq](https://github.com/rigetti/rpcq). Until that changes, we suggest using [pyquil](https://github.com/rigetti/pyquil) to build and execute quantum programs via the Legacy API.  # Legacy API  Our legacy HTTP API remains accessible at https://forest-server.qcs.rigetti.com, and it shares a source of truth with this API's services. You can use either service with the same user account and means of authentication. We strongly recommend using the API documented here, as the legacy API is on the path to deprecation.
19 *
20 * The version of the OpenAPI document: 2020-07-31
21 * Contact: support@rigetti.com
22 * Generated by: https://openapi-generator.tech
23 */
24
25use super::{configuration, Error};
26use crate::apis::ResponseContent;
27use ::qcs_api_client_common::backoff::{
28    duration_from_io_error, duration_from_reqwest_error, duration_from_response, ExponentialBackoff,
29};
30#[cfg(feature = "tracing")]
31use qcs_api_client_common::configuration::tokens::TokenRefresher;
32use reqwest::StatusCode;
33use serde::{Deserialize, Serialize};
34
35/// struct for typed errors of method [`get_instruction_set_architecture`]
36#[derive(Debug, Clone, Serialize, Deserialize)]
37#[serde(untagged)]
38pub enum GetInstructionSetArchitectureError {
39    Status422(crate::models::ValidationError),
40    DefaultResponse(crate::models::Error),
41    UnknownValue(serde_json::Value),
42}
43
44/// struct for typed errors of method [`get_quantum_processor`]
45#[derive(Debug, Clone, Serialize, Deserialize)]
46#[serde(untagged)]
47pub enum GetQuantumProcessorError {
48    Status422(crate::models::ValidationError),
49    DefaultResponse(crate::models::Error),
50    UnknownValue(serde_json::Value),
51}
52
53/// struct for typed errors of method [`list_instruction_set_architectures`]
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(untagged)]
56pub enum ListInstructionSetArchitecturesError {
57    Status422(crate::models::ValidationError),
58    DefaultResponse(crate::models::Error),
59    UnknownValue(serde_json::Value),
60}
61
62/// struct for typed errors of method [`list_quantum_processor_accessors`]
63#[derive(Debug, Clone, Serialize, Deserialize)]
64#[serde(untagged)]
65pub enum ListQuantumProcessorAccessorsError {
66    Status422(crate::models::ValidationError),
67    UnknownValue(serde_json::Value),
68}
69
70/// struct for typed errors of method [`list_quantum_processors`]
71#[derive(Debug, Clone, Serialize, Deserialize)]
72#[serde(untagged)]
73pub enum ListQuantumProcessorsError {
74    Status422(crate::models::ValidationError),
75    DefaultResponse(crate::models::Error),
76    UnknownValue(serde_json::Value),
77}
78
79async fn get_instruction_set_architecture_inner(
80    configuration: &configuration::Configuration,
81    backoff: &mut ExponentialBackoff,
82    quantum_processor_id: &str,
83) -> Result<crate::models::InstructionSetArchitecture, Error<GetInstructionSetArchitectureError>> {
84    let local_var_configuration = configuration;
85
86    let local_var_client = &local_var_configuration.client;
87
88    let local_var_uri_str = format!(
89        "{}/v1/quantumProcessors/{quantum_processor_id}/instructionSetArchitecture",
90        local_var_configuration.qcs_config.api_url(),
91        quantum_processor_id = crate::apis::urlencode(quantum_processor_id)
92    );
93    let mut local_var_req_builder =
94        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
95
96    #[cfg(feature = "tracing")]
97    {
98        // Ignore parsing errors if the URL is invalid for some reason.
99        // If it is invalid, it will turn up as an error later when actually making the request.
100        let local_var_do_tracing = local_var_uri_str
101            .parse::<::url::Url>()
102            .ok()
103            .is_none_or(|url| {
104                configuration
105                    .qcs_config
106                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
107            });
108
109        if local_var_do_tracing {
110            ::tracing::debug!(
111                url=%local_var_uri_str,
112                method="GET",
113                "making get_instruction_set_architecture request",
114            );
115        }
116    }
117
118    // Use the QCS Bearer token if a client OAuthSession is present,
119    // but do not require one when the security schema says it is optional.
120    {
121        use qcs_api_client_common::configuration::TokenError;
122
123        #[allow(
124            clippy::nonminimal_bool,
125            clippy::eq_op,
126            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
127        )]
128        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
129
130        let token = local_var_configuration
131            .qcs_config
132            .get_bearer_access_token()
133            .await;
134
135        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
136            // the client is configured without any OAuthSession, but this call does not require one.
137            #[cfg(feature = "tracing")]
138            tracing::debug!(
139                "No client credentials found, but this call does not require authentication."
140            );
141        } else {
142            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
143        }
144    }
145
146    let local_var_req = local_var_req_builder.build()?;
147    let local_var_resp = local_var_client.execute(local_var_req).await?;
148
149    let local_var_status = local_var_resp.status();
150
151    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
152        let local_var_content = local_var_resp.text().await?;
153        serde_json::from_str(&local_var_content).map_err(Error::from)
154    } else {
155        let local_var_retry_delay =
156            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
157        let local_var_content = local_var_resp.text().await?;
158        let local_var_entity: Option<GetInstructionSetArchitectureError> =
159            serde_json::from_str(&local_var_content).ok();
160        let local_var_error = ResponseContent {
161            status: local_var_status,
162            content: local_var_content,
163            entity: local_var_entity,
164            retry_delay: local_var_retry_delay,
165        };
166        Err(Error::ResponseError(local_var_error))
167    }
168}
169
170pub async fn get_instruction_set_architecture(
171    configuration: &configuration::Configuration,
172    quantum_processor_id: &str,
173) -> Result<crate::models::InstructionSetArchitecture, Error<GetInstructionSetArchitectureError>> {
174    let mut backoff = configuration.backoff.clone();
175    let mut refreshed_credentials = false;
176    let method = reqwest::Method::GET;
177    loop {
178        let result = get_instruction_set_architecture_inner(
179            configuration,
180            &mut backoff,
181            quantum_processor_id.clone(),
182        )
183        .await;
184
185        match result {
186            Ok(result) => return Ok(result),
187            Err(Error::ResponseError(response)) => {
188                if !refreshed_credentials
189                    && matches!(
190                        response.status,
191                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
192                    )
193                {
194                    configuration.qcs_config.refresh().await?;
195                    refreshed_credentials = true;
196                    continue;
197                } else if let Some(duration) = response.retry_delay {
198                    tokio::time::sleep(duration).await;
199                    continue;
200                }
201
202                return Err(Error::ResponseError(response));
203            }
204            Err(Error::Reqwest(error)) => {
205                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
206                    tokio::time::sleep(duration).await;
207                    continue;
208                }
209
210                return Err(Error::Reqwest(error));
211            }
212            Err(Error::Io(error)) => {
213                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
214                    tokio::time::sleep(duration).await;
215                    continue;
216                }
217
218                return Err(Error::Io(error));
219            }
220            Err(error) => return Err(error),
221        }
222    }
223}
224async fn get_quantum_processor_inner(
225    configuration: &configuration::Configuration,
226    backoff: &mut ExponentialBackoff,
227    quantum_processor_id: &str,
228) -> Result<crate::models::QuantumProcessor, Error<GetQuantumProcessorError>> {
229    let local_var_configuration = configuration;
230
231    let local_var_client = &local_var_configuration.client;
232
233    let local_var_uri_str = format!(
234        "{}/v1/quantumProcessors/{quantum_processor_id}",
235        local_var_configuration.qcs_config.api_url(),
236        quantum_processor_id = crate::apis::urlencode(quantum_processor_id)
237    );
238    let mut local_var_req_builder =
239        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
240
241    #[cfg(feature = "tracing")]
242    {
243        // Ignore parsing errors if the URL is invalid for some reason.
244        // If it is invalid, it will turn up as an error later when actually making the request.
245        let local_var_do_tracing = local_var_uri_str
246            .parse::<::url::Url>()
247            .ok()
248            .is_none_or(|url| {
249                configuration
250                    .qcs_config
251                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
252            });
253
254        if local_var_do_tracing {
255            ::tracing::debug!(
256                url=%local_var_uri_str,
257                method="GET",
258                "making get_quantum_processor request",
259            );
260        }
261    }
262
263    // Use the QCS Bearer token if a client OAuthSession is present,
264    // but do not require one when the security schema says it is optional.
265    {
266        use qcs_api_client_common::configuration::TokenError;
267
268        #[allow(
269            clippy::nonminimal_bool,
270            clippy::eq_op,
271            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
272        )]
273        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
274
275        let token = local_var_configuration
276            .qcs_config
277            .get_bearer_access_token()
278            .await;
279
280        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
281            // the client is configured without any OAuthSession, but this call does not require one.
282            #[cfg(feature = "tracing")]
283            tracing::debug!(
284                "No client credentials found, but this call does not require authentication."
285            );
286        } else {
287            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
288        }
289    }
290
291    let local_var_req = local_var_req_builder.build()?;
292    let local_var_resp = local_var_client.execute(local_var_req).await?;
293
294    let local_var_status = local_var_resp.status();
295
296    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
297        let local_var_content = local_var_resp.text().await?;
298        serde_json::from_str(&local_var_content).map_err(Error::from)
299    } else {
300        let local_var_retry_delay =
301            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
302        let local_var_content = local_var_resp.text().await?;
303        let local_var_entity: Option<GetQuantumProcessorError> =
304            serde_json::from_str(&local_var_content).ok();
305        let local_var_error = ResponseContent {
306            status: local_var_status,
307            content: local_var_content,
308            entity: local_var_entity,
309            retry_delay: local_var_retry_delay,
310        };
311        Err(Error::ResponseError(local_var_error))
312    }
313}
314
315/// Retrieve a single `QuantumProcessor` by ID.
316pub async fn get_quantum_processor(
317    configuration: &configuration::Configuration,
318    quantum_processor_id: &str,
319) -> Result<crate::models::QuantumProcessor, Error<GetQuantumProcessorError>> {
320    let mut backoff = configuration.backoff.clone();
321    let mut refreshed_credentials = false;
322    let method = reqwest::Method::GET;
323    loop {
324        let result =
325            get_quantum_processor_inner(configuration, &mut backoff, quantum_processor_id.clone())
326                .await;
327
328        match result {
329            Ok(result) => return Ok(result),
330            Err(Error::ResponseError(response)) => {
331                if !refreshed_credentials
332                    && matches!(
333                        response.status,
334                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
335                    )
336                {
337                    configuration.qcs_config.refresh().await?;
338                    refreshed_credentials = true;
339                    continue;
340                } else if let Some(duration) = response.retry_delay {
341                    tokio::time::sleep(duration).await;
342                    continue;
343                }
344
345                return Err(Error::ResponseError(response));
346            }
347            Err(Error::Reqwest(error)) => {
348                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
349                    tokio::time::sleep(duration).await;
350                    continue;
351                }
352
353                return Err(Error::Reqwest(error));
354            }
355            Err(Error::Io(error)) => {
356                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
357                    tokio::time::sleep(duration).await;
358                    continue;
359                }
360
361                return Err(Error::Io(error));
362            }
363            Err(error) => return Err(error),
364        }
365    }
366}
367async fn list_instruction_set_architectures_inner(
368    configuration: &configuration::Configuration,
369    backoff: &mut ExponentialBackoff,
370    page_size: Option<i64>,
371    page_token: Option<&str>,
372) -> Result<
373    crate::models::ListInstructionSetArchitectureResponse,
374    Error<ListInstructionSetArchitecturesError>,
375> {
376    let local_var_configuration = configuration;
377
378    let local_var_client = &local_var_configuration.client;
379
380    let local_var_uri_str = format!(
381        "{}/v1/instructionSetArchitectures",
382        local_var_configuration.qcs_config.api_url()
383    );
384    let mut local_var_req_builder =
385        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
386
387    #[cfg(feature = "tracing")]
388    {
389        // Ignore parsing errors if the URL is invalid for some reason.
390        // If it is invalid, it will turn up as an error later when actually making the request.
391        let local_var_do_tracing = local_var_uri_str
392            .parse::<::url::Url>()
393            .ok()
394            .is_none_or(|url| {
395                configuration
396                    .qcs_config
397                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
398            });
399
400        if local_var_do_tracing {
401            ::tracing::debug!(
402                url=%local_var_uri_str,
403                method="GET",
404                "making list_instruction_set_architectures request",
405            );
406        }
407    }
408
409    if let Some(ref local_var_str) = page_size {
410        local_var_req_builder =
411            local_var_req_builder.query(&[("pageSize", &local_var_str.to_string())]);
412    }
413    if let Some(ref local_var_str) = page_token {
414        local_var_req_builder =
415            local_var_req_builder.query(&[("pageToken", &local_var_str.to_string())]);
416    }
417
418    // Use the QCS Bearer token if a client OAuthSession is present,
419    // but do not require one when the security schema says it is optional.
420    {
421        use qcs_api_client_common::configuration::TokenError;
422
423        #[allow(
424            clippy::nonminimal_bool,
425            clippy::eq_op,
426            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
427        )]
428        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
429
430        let token = local_var_configuration
431            .qcs_config
432            .get_bearer_access_token()
433            .await;
434
435        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
436            // the client is configured without any OAuthSession, but this call does not require one.
437            #[cfg(feature = "tracing")]
438            tracing::debug!(
439                "No client credentials found, but this call does not require authentication."
440            );
441        } else {
442            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
443        }
444    }
445
446    let local_var_req = local_var_req_builder.build()?;
447    let local_var_resp = local_var_client.execute(local_var_req).await?;
448
449    let local_var_status = local_var_resp.status();
450
451    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
452        let local_var_content = local_var_resp.text().await?;
453        serde_json::from_str(&local_var_content).map_err(Error::from)
454    } else {
455        let local_var_retry_delay =
456            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
457        let local_var_content = local_var_resp.text().await?;
458        let local_var_entity: Option<ListInstructionSetArchitecturesError> =
459            serde_json::from_str(&local_var_content).ok();
460        let local_var_error = ResponseContent {
461            status: local_var_status,
462            content: local_var_content,
463            entity: local_var_entity,
464            retry_delay: local_var_retry_delay,
465        };
466        Err(Error::ResponseError(local_var_error))
467    }
468}
469
470pub async fn list_instruction_set_architectures(
471    configuration: &configuration::Configuration,
472    page_size: Option<i64>,
473    page_token: Option<&str>,
474) -> Result<
475    crate::models::ListInstructionSetArchitectureResponse,
476    Error<ListInstructionSetArchitecturesError>,
477> {
478    let mut backoff = configuration.backoff.clone();
479    let mut refreshed_credentials = false;
480    let method = reqwest::Method::GET;
481    loop {
482        let result = list_instruction_set_architectures_inner(
483            configuration,
484            &mut backoff,
485            page_size.clone(),
486            page_token.clone(),
487        )
488        .await;
489
490        match result {
491            Ok(result) => return Ok(result),
492            Err(Error::ResponseError(response)) => {
493                if !refreshed_credentials
494                    && matches!(
495                        response.status,
496                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
497                    )
498                {
499                    configuration.qcs_config.refresh().await?;
500                    refreshed_credentials = true;
501                    continue;
502                } else if let Some(duration) = response.retry_delay {
503                    tokio::time::sleep(duration).await;
504                    continue;
505                }
506
507                return Err(Error::ResponseError(response));
508            }
509            Err(Error::Reqwest(error)) => {
510                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
511                    tokio::time::sleep(duration).await;
512                    continue;
513                }
514
515                return Err(Error::Reqwest(error));
516            }
517            Err(Error::Io(error)) => {
518                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
519                    tokio::time::sleep(duration).await;
520                    continue;
521                }
522
523                return Err(Error::Io(error));
524            }
525            Err(error) => return Err(error),
526        }
527    }
528}
529async fn list_quantum_processor_accessors_inner(
530    configuration: &configuration::Configuration,
531    backoff: &mut ExponentialBackoff,
532    quantum_processor_id: &str,
533    page_size: Option<i64>,
534    page_token: Option<&str>,
535) -> Result<
536    crate::models::ListQuantumProcessorAccessorsResponse,
537    Error<ListQuantumProcessorAccessorsError>,
538> {
539    let local_var_configuration = configuration;
540
541    let local_var_client = &local_var_configuration.client;
542
543    let local_var_uri_str = format!(
544        "{}/v1/quantumProcessors/{quantumProcessorId}/accessors",
545        local_var_configuration.qcs_config.api_url(),
546        quantumProcessorId = crate::apis::urlencode(quantum_processor_id)
547    );
548    let mut local_var_req_builder =
549        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
550
551    #[cfg(feature = "tracing")]
552    {
553        // Ignore parsing errors if the URL is invalid for some reason.
554        // If it is invalid, it will turn up as an error later when actually making the request.
555        let local_var_do_tracing = local_var_uri_str
556            .parse::<::url::Url>()
557            .ok()
558            .is_none_or(|url| {
559                configuration
560                    .qcs_config
561                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
562            });
563
564        if local_var_do_tracing {
565            ::tracing::debug!(
566                url=%local_var_uri_str,
567                method="GET",
568                "making list_quantum_processor_accessors request",
569            );
570        }
571    }
572
573    if let Some(ref local_var_str) = page_size {
574        local_var_req_builder =
575            local_var_req_builder.query(&[("pageSize", &local_var_str.to_string())]);
576    }
577    if let Some(ref local_var_str) = page_token {
578        local_var_req_builder =
579            local_var_req_builder.query(&[("pageToken", &local_var_str.to_string())]);
580    }
581
582    // Use the QCS Bearer token if a client OAuthSession is present,
583    // but do not require one when the security schema says it is optional.
584    {
585        use qcs_api_client_common::configuration::TokenError;
586
587        #[allow(
588            clippy::nonminimal_bool,
589            clippy::eq_op,
590            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
591        )]
592        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
593
594        let token = local_var_configuration
595            .qcs_config
596            .get_bearer_access_token()
597            .await;
598
599        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
600            // the client is configured without any OAuthSession, but this call does not require one.
601            #[cfg(feature = "tracing")]
602            tracing::debug!(
603                "No client credentials found, but this call does not require authentication."
604            );
605        } else {
606            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
607        }
608    }
609
610    let local_var_req = local_var_req_builder.build()?;
611    let local_var_resp = local_var_client.execute(local_var_req).await?;
612
613    let local_var_status = local_var_resp.status();
614
615    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
616        let local_var_content = local_var_resp.text().await?;
617        serde_json::from_str(&local_var_content).map_err(Error::from)
618    } else {
619        let local_var_retry_delay =
620            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
621        let local_var_content = local_var_resp.text().await?;
622        let local_var_entity: Option<ListQuantumProcessorAccessorsError> =
623            serde_json::from_str(&local_var_content).ok();
624        let local_var_error = ResponseContent {
625            status: local_var_status,
626            content: local_var_content,
627            entity: local_var_entity,
628            retry_delay: local_var_retry_delay,
629        };
630        Err(Error::ResponseError(local_var_error))
631    }
632}
633
634/// List all means of accessing a QuantumProcessor available to the user.
635pub async fn list_quantum_processor_accessors(
636    configuration: &configuration::Configuration,
637    quantum_processor_id: &str,
638    page_size: Option<i64>,
639    page_token: Option<&str>,
640) -> Result<
641    crate::models::ListQuantumProcessorAccessorsResponse,
642    Error<ListQuantumProcessorAccessorsError>,
643> {
644    let mut backoff = configuration.backoff.clone();
645    let mut refreshed_credentials = false;
646    let method = reqwest::Method::GET;
647    loop {
648        let result = list_quantum_processor_accessors_inner(
649            configuration,
650            &mut backoff,
651            quantum_processor_id.clone(),
652            page_size.clone(),
653            page_token.clone(),
654        )
655        .await;
656
657        match result {
658            Ok(result) => return Ok(result),
659            Err(Error::ResponseError(response)) => {
660                if !refreshed_credentials
661                    && matches!(
662                        response.status,
663                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
664                    )
665                {
666                    configuration.qcs_config.refresh().await?;
667                    refreshed_credentials = true;
668                    continue;
669                } else if let Some(duration) = response.retry_delay {
670                    tokio::time::sleep(duration).await;
671                    continue;
672                }
673
674                return Err(Error::ResponseError(response));
675            }
676            Err(Error::Reqwest(error)) => {
677                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
678                    tokio::time::sleep(duration).await;
679                    continue;
680                }
681
682                return Err(Error::Reqwest(error));
683            }
684            Err(Error::Io(error)) => {
685                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
686                    tokio::time::sleep(duration).await;
687                    continue;
688                }
689
690                return Err(Error::Io(error));
691            }
692            Err(error) => return Err(error),
693        }
694    }
695}
696async fn list_quantum_processors_inner(
697    configuration: &configuration::Configuration,
698    backoff: &mut ExponentialBackoff,
699    page_size: Option<i64>,
700    page_token: Option<&str>,
701) -> Result<crate::models::ListQuantumProcessorsResponse, Error<ListQuantumProcessorsError>> {
702    let local_var_configuration = configuration;
703
704    let local_var_client = &local_var_configuration.client;
705
706    let local_var_uri_str = format!(
707        "{}/v1/quantumProcessors",
708        local_var_configuration.qcs_config.api_url()
709    );
710    let mut local_var_req_builder =
711        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
712
713    #[cfg(feature = "tracing")]
714    {
715        // Ignore parsing errors if the URL is invalid for some reason.
716        // If it is invalid, it will turn up as an error later when actually making the request.
717        let local_var_do_tracing = local_var_uri_str
718            .parse::<::url::Url>()
719            .ok()
720            .is_none_or(|url| {
721                configuration
722                    .qcs_config
723                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
724            });
725
726        if local_var_do_tracing {
727            ::tracing::debug!(
728                url=%local_var_uri_str,
729                method="GET",
730                "making list_quantum_processors request",
731            );
732        }
733    }
734
735    if let Some(ref local_var_str) = page_size {
736        local_var_req_builder =
737            local_var_req_builder.query(&[("pageSize", &local_var_str.to_string())]);
738    }
739    if let Some(ref local_var_str) = page_token {
740        local_var_req_builder =
741            local_var_req_builder.query(&[("pageToken", &local_var_str.to_string())]);
742    }
743
744    // Use the QCS Bearer token if a client OAuthSession is present,
745    // but do not require one when the security schema says it is optional.
746    {
747        use qcs_api_client_common::configuration::TokenError;
748
749        #[allow(
750            clippy::nonminimal_bool,
751            clippy::eq_op,
752            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
753        )]
754        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
755
756        let token = local_var_configuration
757            .qcs_config
758            .get_bearer_access_token()
759            .await;
760
761        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
762            // the client is configured without any OAuthSession, but this call does not require one.
763            #[cfg(feature = "tracing")]
764            tracing::debug!(
765                "No client credentials found, but this call does not require authentication."
766            );
767        } else {
768            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
769        }
770    }
771
772    let local_var_req = local_var_req_builder.build()?;
773    let local_var_resp = local_var_client.execute(local_var_req).await?;
774
775    let local_var_status = local_var_resp.status();
776
777    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
778        let local_var_content = local_var_resp.text().await?;
779        serde_json::from_str(&local_var_content).map_err(Error::from)
780    } else {
781        let local_var_retry_delay =
782            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
783        let local_var_content = local_var_resp.text().await?;
784        let local_var_entity: Option<ListQuantumProcessorsError> =
785            serde_json::from_str(&local_var_content).ok();
786        let local_var_error = ResponseContent {
787            status: local_var_status,
788            content: local_var_content,
789            entity: local_var_entity,
790            retry_delay: local_var_retry_delay,
791        };
792        Err(Error::ResponseError(local_var_error))
793    }
794}
795
796/// List the [`QuantumProcessor`]s that this user is authorized to access.  If no auth token is provided, only public processors will be returned.
797pub async fn list_quantum_processors(
798    configuration: &configuration::Configuration,
799    page_size: Option<i64>,
800    page_token: Option<&str>,
801) -> Result<crate::models::ListQuantumProcessorsResponse, Error<ListQuantumProcessorsError>> {
802    let mut backoff = configuration.backoff.clone();
803    let mut refreshed_credentials = false;
804    let method = reqwest::Method::GET;
805    loop {
806        let result = list_quantum_processors_inner(
807            configuration,
808            &mut backoff,
809            page_size.clone(),
810            page_token.clone(),
811        )
812        .await;
813
814        match result {
815            Ok(result) => return Ok(result),
816            Err(Error::ResponseError(response)) => {
817                if !refreshed_credentials
818                    && matches!(
819                        response.status,
820                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
821                    )
822                {
823                    configuration.qcs_config.refresh().await?;
824                    refreshed_credentials = true;
825                    continue;
826                } else if let Some(duration) = response.retry_delay {
827                    tokio::time::sleep(duration).await;
828                    continue;
829                }
830
831                return Err(Error::ResponseError(response));
832            }
833            Err(Error::Reqwest(error)) => {
834                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
835                    tokio::time::sleep(duration).await;
836                    continue;
837                }
838
839                return Err(Error::Reqwest(error));
840            }
841            Err(Error::Io(error)) => {
842                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
843                    tokio::time::sleep(duration).await;
844                    continue;
845                }
846
847                return Err(Error::Io(error));
848            }
849            Err(error) => return Err(error),
850        }
851    }
852}