use std::fmt::Debug;
use crate::resource::BudgetError;
use crate::resource::LimitExceededError;
use crate::resource::MeasuredBudgetError;
use crate::resource::Observation;
use crate::resource::ResourceQuantity;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ResourceLimit<R, Q = u64>
where
Q: Copy + Debug,
{
resource: R,
maximum: Q,
}
impl<R, Q> ResourceLimit<R, Q>
where
Q: Copy + Debug,
{
#[inline]
#[must_use]
pub const fn new(resource: R, maximum: Q) -> Self {
Self { resource, maximum }
}
#[inline(always)]
#[must_use]
pub const fn resource(&self) -> &R {
&self.resource
}
#[inline(always)]
#[must_use]
pub const fn maximum(&self) -> Q {
self.maximum
}
#[inline]
pub fn check(&self, actual: Q) -> Result<(), LimitExceededError<R, Q>>
where
R: Clone,
Q: Ord,
{
if actual > self.maximum {
Err(LimitExceededError {
resource: self.resource.clone(),
observed: Observation::Exact(actual),
maximum: self.maximum,
})
} else {
Ok(())
}
}
}
impl<R, Q> ResourceLimit<R, Q>
where
Q: ResourceQuantity,
{
#[inline]
pub fn check_usize(&self, actual: usize) -> Result<(), MeasuredBudgetError<R, Q>>
where
R: Clone,
{
let actual =
Q::try_from_usize(actual).map_err(|source| MeasuredBudgetError::quantity(self.resource.clone(), source))?;
self.check(actual).map_err(MeasuredBudgetError::from)
}
#[inline]
pub fn check_u64(&self, actual: u64) -> Result<(), MeasuredBudgetError<R, Q>>
where
R: Clone,
{
let actual =
Q::try_from_u64(actual).map_err(|source| MeasuredBudgetError::quantity(self.resource.clone(), source))?;
self.check(actual).map_err(MeasuredBudgetError::from)
}
}
#[inline]
pub(crate) fn check_limit<R, Q>(limit: Option<&ResourceLimit<R, Q>>, actual: Q) -> Result<(), BudgetError<R, Q>>
where
R: Clone,
Q: Copy + Debug + Ord,
{
match limit {
Some(limit) => limit.check(actual).map_err(BudgetError::from),
None => Ok(()),
}
}