Skip to main content

qubit_budget/resource/error/
insufficient_budget_error.rs

1// =============================================================================
2//    Copyright (c) 2025 - 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Defines cumulative-budget failures for finite resource constraints.
9
10use std::fmt::Debug;
11
12use thiserror::Error;
13
14/// Structured facts for a cumulative request that exceeded remaining capacity.
15///
16/// # Type Parameters
17///
18/// * `R` - Caller-defined resource value retained for diagnostics.
19/// * `Q` - Copyable measurement value used by the failed constraint.
20///
21/// # Examples
22///
23/// ```
24/// use qubit_budget::ResourceBudget;
25///
26/// let mut budget = ResourceBudget::new("bytes", 2_u64);
27/// let error = budget.try_consume(3).expect_err("three bytes should not fit");
28/// assert_eq!(error.remaining(), 2);
29/// assert_eq!(error.requested(), 3);
30/// ```
31#[must_use]
32#[derive(Debug, Error, Clone, PartialEq, Eq)]
33#[error("resource {resource:?} requested {requested:?}, but only {remaining:?} of {limit:?} remains")]
34pub struct InsufficientBudgetError<R, Q = u64>
35where
36    Q: Copy + Debug,
37{
38    /// Resource associated with the failed consumption request.
39    pub resource: R,
40    /// Configured finite limit.
41    pub limit: Q,
42    /// Capacity remaining before the failed request.
43    pub remaining: Q,
44    /// Quantity requested by the failed operation.
45    pub requested: Q,
46}
47
48impl<R, Q> InsufficientBudgetError<R, Q>
49where
50    Q: Copy + Debug,
51{
52    /// Returns the resource associated with this failure.
53    ///
54    /// # Returns
55    ///
56    /// Returns the resource associated with this failure.
57    #[must_use]
58    #[inline(always)]
59    pub const fn resource(&self) -> &R {
60        &self.resource
61    }
62
63    /// Consumes this error and returns its associated resource.
64    ///
65    /// # Returns
66    ///
67    /// Consumes this error and returns its associated resource.
68    #[must_use]
69    #[inline(always)]
70    pub fn into_resource(self) -> R {
71        self.resource
72    }
73
74    /// Returns the configured finite limit.
75    ///
76    /// # Returns
77    ///
78    /// Returns the configured finite limit.
79    #[must_use]
80    #[inline(always)]
81    pub const fn limit(&self) -> Q {
82        self.limit
83    }
84
85    /// Returns the capacity remaining before the failed request.
86    ///
87    /// # Returns
88    ///
89    /// Returns the capacity remaining before the failed request.
90    #[must_use]
91    #[inline(always)]
92    pub const fn remaining(&self) -> Q {
93        self.remaining
94    }
95
96    /// Returns the quantity requested by the failed operation.
97    ///
98    /// # Returns
99    ///
100    /// Returns the quantity requested by the failed operation.
101    #[must_use]
102    #[inline(always)]
103    pub const fn requested(&self) -> Q {
104        self.requested
105    }
106}
107
108impl<R, Q> InsufficientBudgetError<R, Q>
109where
110    Q: crate::ResourceQuantity,
111{
112    /// Returns the amount already consumed before the failed request.
113    ///
114    /// # Returns
115    ///
116    /// Returns the amount already consumed before the failed request.
117    #[must_use]
118    #[inline]
119    pub fn used(&self) -> Q {
120        self.limit - self.remaining
121    }
122}