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(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}