qubit_budget/resource/error/budget_group_error.rs
1// =============================================================================
2// Copyright (c) 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Defines failures from atomic grouped budget consumption.
9
10use std::fmt::Debug;
11
12use thiserror::Error;
13
14use crate::resource::InsufficientBudgetError;
15
16/// Failure returned by an atomic grouped budget consumption.
17///
18/// The index identifies the first budget, in caller-provided order, that
19/// rejected the request. No member of the group is charged when this error is
20/// returned.
21///
22/// # Type Parameters
23///
24/// * `R` - Caller-defined resource identity retained by limits and errors.
25/// * `Q` - Exact unsigned quantity used for measurements and accounting.
26///
27/// # Examples
28///
29/// ```
30/// use qubit_budget::ResourceBudget;
31///
32/// let mut first = ResourceBudget::new("first", 2_u64);
33/// let mut second = ResourceBudget::new("second", 1_u64);
34/// let error = ResourceBudget::try_consume_group(&mut [&mut first, &mut second], 2)
35/// .expect_err("the second budget should reject the charge");
36/// assert_eq!(error.index(), 1);
37/// assert_eq!(first.remaining(), 2);
38/// ```
39#[must_use]
40#[derive(Debug, Error, Clone, PartialEq, Eq)]
41#[error("budget group member {index} rejected consumption: {source}")]
42pub struct BudgetGroupError<R, Q = u64>
43where
44 Q: Copy + Debug,
45{
46 /// Zero-based index of the first rejecting budget.
47 index: usize,
48
49 /// Structured failure returned by that budget.
50 #[source]
51 source: InsufficientBudgetError<R, Q>,
52}
53
54impl<R, Q> BudgetGroupError<R, Q>
55where
56 Q: Copy + Debug,
57{
58 /// Creates a grouped failure for the first rejecting budget.
59 ///
60 /// # Parameters
61 ///
62 /// * `index` - Zero-based position associated with the operation.
63 /// * `source` - Underlying failure retained as the error source.
64 ///
65 /// # Returns
66 ///
67 /// Creates a grouped failure for the first rejecting budget.
68 pub(crate) const fn new(index: usize, source: InsufficientBudgetError<R, Q>) -> Self {
69 Self { index, source }
70 }
71
72 /// Returns the zero-based index of the first rejecting budget.
73 ///
74 /// # Returns
75 ///
76 /// Returns the zero-based index of the first rejecting budget.
77 #[inline(always)]
78 #[must_use]
79 pub const fn index(&self) -> usize {
80 self.index
81 }
82
83 /// Returns the structured failure from the rejecting budget.
84 ///
85 /// # Returns
86 ///
87 /// Returns the structured failure from the rejecting budget.
88 #[inline(always)]
89 pub const fn source_error(&self) -> &InsufficientBudgetError<R, Q> {
90 &self.source
91 }
92
93 /// Consumes this error and returns the rejecting budget's failure.
94 ///
95 /// # Returns
96 ///
97 /// Consumes this error and returns the rejecting budget's failure.
98 #[inline(always)]
99 pub fn into_source_error(self) -> InsufficientBudgetError<R, Q> {
100 self.source
101 }
102}