Skip to main content

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}