Skip to main content

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}