qubit_spi/provider_failure.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! Candidate failure details collected during fallback selection.
11
12use std::error::Error;
13use std::fmt::{
14 Display,
15 Formatter,
16 Result as FmtResult,
17};
18
19use crate::{
20 ProviderCreateError,
21 ProviderName,
22 ProviderRegistryError,
23};
24
25/// Failure recorded for one provider candidate.
26#[derive(Debug, Clone)]
27pub enum ProviderFailure {
28 /// No provider matched the candidate name.
29 UnknownProvider {
30 /// Candidate provider name.
31 name: ProviderName,
32 },
33 /// A provider matched the candidate name but is unavailable.
34 Unavailable {
35 /// Candidate provider name.
36 name: ProviderName,
37 /// Provider-level unavailability error.
38 source: ProviderCreateError,
39 },
40 /// A provider matched the candidate name but failed while creating a service.
41 CreateFailed {
42 /// Candidate provider name.
43 name: ProviderName,
44 /// Provider-level creation error.
45 source: ProviderCreateError,
46 },
47}
48
49impl ProviderFailure {
50 /// Creates an unknown-provider failure.
51 ///
52 /// # Parameters
53 /// - `name`: Candidate provider name.
54 ///
55 /// # Returns
56 /// Unknown-provider failure.
57 #[inline]
58 pub fn unknown(name: &str) -> Result<Self, ProviderRegistryError> {
59 Ok(Self::unknown_name(ProviderName::new(name)?))
60 }
61
62 /// Creates an unavailable-provider failure.
63 ///
64 /// # Parameters
65 /// - `name`: Candidate provider name.
66 /// - `reason`: Human-readable unavailability reason.
67 ///
68 /// # Returns
69 /// Unavailable-provider failure.
70 #[inline]
71 pub fn unavailable(name: &str, reason: &str) -> Result<Self, ProviderRegistryError> {
72 Self::unavailable_from_error(name, ProviderCreateError::unavailable(reason))
73 }
74
75 /// Creates a provider-creation failure.
76 ///
77 /// # Parameters
78 /// - `name`: Candidate provider name.
79 /// - `reason`: Human-readable creation failure reason.
80 ///
81 /// # Returns
82 /// Provider-creation failure.
83 #[inline]
84 pub fn create_failed(name: &str, reason: &str) -> Result<Self, ProviderRegistryError> {
85 Self::create_failed_from_error(name, ProviderCreateError::failed(reason))
86 }
87
88 /// Creates an unavailable-provider failure from a provider-level error.
89 ///
90 /// # Parameters
91 /// - `name`: Candidate provider name.
92 /// - `source`: Provider-level unavailability error.
93 ///
94 /// # Returns
95 /// Unavailable-provider failure preserving the source error.
96 ///
97 /// # Errors
98 /// Returns [`ProviderRegistryError`] when `name` is not valid.
99 #[inline]
100 pub fn unavailable_from_error(name: &str, source: ProviderCreateError) -> Result<Self, ProviderRegistryError> {
101 Ok(Self::unavailable_error(ProviderName::new(name)?, source))
102 }
103
104 /// Creates a provider-creation failure from a provider-level error.
105 ///
106 /// # Parameters
107 /// - `name`: Candidate provider name.
108 /// - `source`: Provider-level creation error.
109 ///
110 /// # Returns
111 /// Provider-creation failure preserving the source error.
112 ///
113 /// # Errors
114 /// Returns [`ProviderRegistryError`] when `name` is not valid.
115 #[inline]
116 pub fn create_failed_from_error(name: &str, source: ProviderCreateError) -> Result<Self, ProviderRegistryError> {
117 Ok(Self::create_failed_error(ProviderName::new(name)?, source))
118 }
119
120 /// Gets the candidate provider name.
121 ///
122 /// # Returns
123 /// Candidate name associated with this failure.
124 #[inline]
125 pub fn name(&self) -> &str {
126 self.provider_name().as_str()
127 }
128
129 /// Gets the candidate provider name.
130 ///
131 /// # Returns
132 /// Candidate name associated with this failure.
133 #[inline]
134 pub fn provider_name(&self) -> &ProviderName {
135 match self {
136 Self::UnknownProvider { name } | Self::Unavailable { name, .. } | Self::CreateFailed { name, .. } => name,
137 }
138 }
139
140 /// Creates an unknown-provider failure from a validated provider name.
141 ///
142 /// # Parameters
143 /// - `name`: Validated candidate provider name.
144 ///
145 /// # Returns
146 /// Unknown-provider failure.
147 #[inline]
148 pub(crate) fn unknown_name(name: ProviderName) -> Self {
149 Self::UnknownProvider { name }
150 }
151
152 /// Creates an unavailable-provider failure from a validated provider name.
153 ///
154 /// # Parameters
155 /// - `name`: Validated candidate provider name.
156 /// - `reason`: Human-readable unavailability reason.
157 ///
158 /// # Returns
159 /// Unavailable-provider failure.
160 #[inline]
161 pub(crate) fn unavailable_name(name: ProviderName, reason: &str) -> Self {
162 Self::unavailable_error(name, ProviderCreateError::unavailable(reason))
163 }
164
165 /// Creates an unavailable-provider failure from a provider error.
166 ///
167 /// # Parameters
168 /// - `name`: Validated candidate provider name.
169 /// - `source`: Provider-level unavailability error.
170 ///
171 /// # Returns
172 /// Unavailable-provider failure.
173 #[inline]
174 pub(crate) fn unavailable_error(name: ProviderName, source: ProviderCreateError) -> Self {
175 Self::Unavailable { name, source }
176 }
177
178 /// Creates a creation failure from a provider error.
179 ///
180 /// # Parameters
181 /// - `name`: Validated candidate provider name.
182 /// - `source`: Provider-level creation error.
183 ///
184 /// # Returns
185 /// Provider-creation failure.
186 #[inline]
187 pub(crate) fn create_failed_error(name: ProviderName, source: ProviderCreateError) -> Self {
188 Self::CreateFailed { name, source }
189 }
190}
191
192impl Display for ProviderFailure {
193 #[inline]
194 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
195 match self {
196 Self::UnknownProvider { name } => {
197 write!(formatter, "unknown provider: {name}")
198 }
199 Self::Unavailable { name, source } => {
200 write!(formatter, "provider '{name}' is unavailable: {}", source.reason(),)
201 }
202 Self::CreateFailed { name, source } => {
203 write!(
204 formatter,
205 "provider '{name}' failed to create service: {}",
206 source.reason(),
207 )
208 }
209 }
210 }
211}
212
213impl Error for ProviderFailure {
214 #[inline]
215 fn source(&self) -> Option<&(dyn Error + 'static)> {
216 match self {
217 Self::UnknownProvider { .. } => None,
218 Self::Unavailable { source, .. } | Self::CreateFailed { source, .. } => Some(source),
219 }
220 }
221}