Skip to main content

qubit_dcl/double_checked/
callback_error.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! # Callback Error
11//!
12//! Provides callback error information for double-checked execution.
13//!
14
15use std::fmt;
16
17/// Common error information for prepare lifecycle callbacks.
18///
19/// This keeps a semantic callback type label together with the message so
20/// callers can classify failures without depending on fragile string matching.
21///
22/// # Examples
23///
24/// ```rust
25/// use qubit_dcl::double_checked::CallbackError;
26///
27/// let prepare_error = CallbackError::with_callback_type("prepare", "Resource is locked");
28/// assert_eq!(prepare_error.callback_type(), Some("prepare"));
29/// println!("prepare_error = {:?}", prepare_error);
30/// ```
31#[derive(Debug, Clone)]
32pub struct CallbackError {
33    /// Error message produced by the callback.
34    message: String,
35
36    /// Callback type label, when available.
37    callback_type: Option<&'static str>,
38}
39
40impl CallbackError {
41    /// Builds a callback error without type metadata.
42    ///
43    /// # Type Parameters
44    ///
45    /// * `T` - Displayable error or message value to store.
46    ///
47    /// # Parameters
48    ///
49    /// * `error` - Error value whose display text becomes this callback
50    ///   error's message.
51    ///
52    /// # Returns
53    ///
54    /// A callback error with no callback type label.
55    #[inline]
56    pub fn from_display<T: fmt::Display>(error: T) -> Self {
57        Self {
58            message: error.to_string(),
59            callback_type: None,
60        }
61    }
62
63    /// Builds a callback error with explicit callback type metadata.
64    ///
65    /// # Parameters
66    ///
67    /// * `callback_type` - Semantic callback type label, such as `"prepare"`
68    ///   or `"prepare_rollback"`.
69    /// * `error` - Error message or displayable error value produced by the
70    ///   callback.
71    ///
72    /// # Returns
73    ///
74    /// A callback error with `callback_type` stored as metadata.
75    #[inline]
76    pub fn with_callback_type<T: fmt::Display>(callback_type: &'static str, error: T) -> Self {
77        Self {
78            message: error.to_string(),
79            callback_type: Some(callback_type),
80        }
81    }
82
83    /// Returns the raw message.
84    ///
85    /// # Returns
86    ///
87    /// The message captured from the original displayable error value.
88    #[inline]
89    pub fn message(&self) -> &str {
90        &self.message
91    }
92
93    /// Returns the callback type label, when available.
94    ///
95    /// # Returns
96    ///
97    /// `Some(label)` when this error was built with callback type metadata, or
98    /// `None` when no metadata is available.
99    #[inline]
100    pub fn callback_type(&self) -> Option<&'static str> {
101        self.callback_type
102    }
103
104    /// Returns whether the callback type label is set.
105    ///
106    /// # Returns
107    ///
108    /// `true` when [`Self::callback_type`] would return [`Some`].
109    #[inline]
110    pub fn is_typed(&self) -> bool {
111        self.callback_type.is_some()
112    }
113}
114
115impl fmt::Display for CallbackError {
116    /// Formats this callback error for user-facing diagnostics.
117    ///
118    /// # Parameters
119    ///
120    /// * `f` - Formatter receiving the formatted callback error.
121    ///
122    /// # Returns
123    ///
124    /// [`fmt::Result`] from writing the callback label and message.
125    #[inline]
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        match self.callback_type {
128            Some(callback_type) => write!(f, "{}: {}", callback_type, self.message),
129            None => write!(f, "{}", self.message),
130        }
131    }
132}