qubit_budget/resource/error/resource_release_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 errors for invalid releasable-pool operations.
9
10use std::fmt::Debug;
11
12use thiserror::Error;
13
14/// Structured facts describing a pool release that exceeds current usage.
15///
16/// # Type Parameters
17///
18/// * `R` - Caller-defined resource identity retained by limits and errors.
19/// * `Q` - Exact unsigned quantity used for measurements and accounting.
20///
21/// # Examples
22///
23/// ```
24/// use qubit_budget::ResourcePool;
25///
26/// let mut pool = ResourcePool::new("workers", 2_u64);
27/// pool.try_acquire(1).expect("one worker should fit");
28/// let error = pool.release(2).expect_err("only one worker is in use");
29/// assert_eq!(error.in_use(), 1);
30/// assert_eq!(error.requested(), 2);
31/// ```
32#[non_exhaustive]
33#[must_use]
34#[derive(Debug, Error, Clone, PartialEq, Eq)]
35pub enum ResourceReleaseError<R, Q = u64>
36where
37 Q: Copy + Debug,
38{
39 /// A release request exceeded the amount currently in use.
40 #[error("resource {resource:?} has {in_use:?} in use, but {requested:?} was released")]
41 InvalidRelease {
42 /// Resource associated with the failed release request.
43 resource: R,
44 /// Configured finite limit.
45 limit: Q,
46 /// Quantity in use before the failed release.
47 in_use: Q,
48 /// Quantity requested by the failed operation.
49 requested: Q,
50 },
51}
52
53impl<R, Q> ResourceReleaseError<R, Q>
54where
55 Q: Copy + Debug,
56{
57 /// Returns the resource associated with this failure.
58 ///
59 /// # Returns
60 ///
61 /// Returns the resource associated with this failure.
62 #[must_use]
63 #[inline(always)]
64 pub const fn resource(&self) -> &R {
65 match self {
66 Self::InvalidRelease { resource, .. } => resource,
67 }
68 }
69
70 /// Consumes this error and returns its associated resource.
71 ///
72 /// # Returns
73 ///
74 /// Consumes this error and returns its associated resource.
75 #[inline(always)]
76 #[must_use]
77 pub fn into_resource(self) -> R {
78 match self {
79 Self::InvalidRelease { resource, .. } => resource,
80 }
81 }
82
83 /// Returns the finite pool limit.
84 ///
85 /// # Returns
86 ///
87 /// Returns the finite pool limit.
88 #[must_use]
89 #[inline(always)]
90 pub const fn limit(&self) -> Q {
91 match self {
92 Self::InvalidRelease { limit, .. } => *limit,
93 }
94 }
95
96 /// Returns the amount in use before the invalid release.
97 ///
98 /// # Returns
99 ///
100 /// Returns the amount in use before the invalid release.
101 #[must_use]
102 #[inline(always)]
103 pub const fn in_use(&self) -> Q {
104 match self {
105 Self::InvalidRelease { in_use, .. } => *in_use,
106 }
107 }
108
109 /// Returns the requested release amount.
110 ///
111 /// # Returns
112 ///
113 /// Returns the requested release amount.
114 #[must_use]
115 #[inline(always)]
116 pub const fn requested(&self) -> Q {
117 match self {
118 Self::InvalidRelease { requested, .. } => *requested,
119 }
120 }
121}