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}