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(
101 name: &str,
102 source: ProviderCreateError,
103 ) -> Result<Self, ProviderRegistryError> {
104 Ok(Self::unavailable_error(ProviderName::new(name)?, source))
105 }
106
107 /// Creates a provider-creation failure from a provider-level error.
108 ///
109 /// # Parameters
110 /// - `name`: Candidate provider name.
111 /// - `source`: Provider-level creation error.
112 ///
113 /// # Returns
114 /// Provider-creation failure preserving the source error.
115 ///
116 /// # Errors
117 /// Returns [`ProviderRegistryError`] when `name` is not valid.
118 #[inline]
119 pub fn create_failed_from_error(
120 name: &str,
121 source: ProviderCreateError,
122 ) -> Result<Self, ProviderRegistryError> {
123 Ok(Self::create_failed_error(ProviderName::new(name)?, source))
124 }
125
126 /// Gets the candidate provider name.
127 ///
128 /// # Returns
129 /// Candidate name associated with this failure.
130 #[inline]
131 pub fn name(&self) -> &str {
132 self.provider_name().as_str()
133 }
134
135 /// Gets the candidate provider name.
136 ///
137 /// # Returns
138 /// Candidate name associated with this failure.
139 #[inline]
140 pub fn provider_name(&self) -> &ProviderName {
141 match self {
142 Self::UnknownProvider { name }
143 | Self::Unavailable { name, .. }
144 | Self::CreateFailed { name, .. } => name,
145 }
146 }
147
148 /// Creates an unknown-provider failure from a validated provider name.
149 ///
150 /// # Parameters
151 /// - `name`: Validated candidate provider name.
152 ///
153 /// # Returns
154 /// Unknown-provider failure.
155 #[inline]
156 pub(crate) fn unknown_name(name: ProviderName) -> Self {
157 Self::UnknownProvider { name }
158 }
159
160 /// Creates an unavailable-provider failure from a validated provider name.
161 ///
162 /// # Parameters
163 /// - `name`: Validated candidate provider name.
164 /// - `reason`: Human-readable unavailability reason.
165 ///
166 /// # Returns
167 /// Unavailable-provider failure.
168 #[inline]
169 pub(crate) fn unavailable_name(name: ProviderName, reason: &str) -> Self {
170 Self::unavailable_error(name, ProviderCreateError::unavailable(reason))
171 }
172
173 /// Creates an unavailable-provider failure from a provider error.
174 ///
175 /// # Parameters
176 /// - `name`: Validated candidate provider name.
177 /// - `source`: Provider-level unavailability error.
178 ///
179 /// # Returns
180 /// Unavailable-provider failure.
181 #[inline]
182 pub(crate) fn unavailable_error(name: ProviderName, source: ProviderCreateError) -> Self {
183 Self::Unavailable { name, source }
184 }
185
186 /// Creates a creation failure from a provider error.
187 ///
188 /// # Parameters
189 /// - `name`: Validated candidate provider name.
190 /// - `source`: Provider-level creation error.
191 ///
192 /// # Returns
193 /// Provider-creation failure.
194 #[inline]
195 pub(crate) fn create_failed_error(name: ProviderName, source: ProviderCreateError) -> Self {
196 Self::CreateFailed { name, source }
197 }
198}
199
200impl Display for ProviderFailure {
201 #[inline]
202 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
203 match self {
204 Self::UnknownProvider { name } => {
205 write!(formatter, "unknown provider: {name}")
206 }
207 Self::Unavailable { name, source } => {
208 write!(
209 formatter,
210 "provider '{name}' is unavailable: {}",
211 source.reason(),
212 )
213 }
214 Self::CreateFailed { name, source } => {
215 write!(
216 formatter,
217 "provider '{name}' failed to create service: {}",
218 source.reason(),
219 )
220 }
221 }
222 }
223}
224
225impl Error for ProviderFailure {
226 #[inline]
227 fn source(&self) -> Option<&(dyn Error + 'static)> {
228 match self {
229 Self::UnknownProvider { .. } => None,
230 Self::Unavailable { source, .. } | Self::CreateFailed { source, .. } => Some(source),
231 }
232 }
233}