use std::fmt::Debug;
use std::fmt::Display;
use std::ops::Add;
use std::ops::Sub;
use super::internal::ResourceQuantitySealed;
use crate::resource::QuantityConversionError;
use crate::resource::QuantityMeasurement;
pub trait ResourceQuantity:
ResourceQuantitySealed + Copy + Debug + Display + Eq + Ord + Add<Output = Self> + Sub<Output = Self>
{
const ZERO: Self;
const ONE: Self;
fn checked_add(self, other: Self) -> Option<Self>;
fn try_from_usize(value: usize) -> Result<Self, QuantityConversionError>;
fn try_from_u64(value: u64) -> Result<Self, QuantityConversionError>;
}
macro_rules! impl_resource_quantity {
($($quantity:ty),+ $(,)?) => {
$(
impl ResourceQuantitySealed for $quantity {
#[inline]
fn as_u128(self) -> u128 {
self as u128
}
}
impl ResourceQuantity for $quantity {
const ZERO: Self = 0;
const ONE: Self = 1;
#[inline]
fn checked_add(self, other: Self) -> Option<Self> {
Self::checked_add(self, other)
}
#[inline]
fn try_from_usize(value: usize) -> Result<Self, QuantityConversionError> {
<$quantity>::try_from(value).map_err(|_| {
QuantityConversionError::new(
QuantityMeasurement::Usize(value),
stringify!($quantity),
)
})
}
#[inline]
fn try_from_u64(value: u64) -> Result<Self, QuantityConversionError> {
<$quantity>::try_from(value).map_err(|_| {
QuantityConversionError::new(
QuantityMeasurement::U64(value),
stringify!($quantity),
)
})
}
}
)+
};
}
impl_resource_quantity!(u8, u16, u32, u64, u128, usize);
#[inline]
#[cfg(feature = "big-integer")]
pub(crate) fn quantity_as_u128<Q: ResourceQuantity>(value: Q) -> u128 {
value.as_u128()
}
#[cfg(all(test, feature = "big-integer"))]
mod tests {
use super::ResourceQuantity;
use super::quantity_as_u128;
macro_rules! assert_widens_exactly {
($quantity:ty) => {
assert_eq!(quantity_as_u128(<$quantity>::ZERO), 0);
assert_eq!(quantity_as_u128(<$quantity>::ONE), 1);
assert_eq!(quantity_as_u128(<$quantity>::MAX), <$quantity>::MAX as u128);
};
}
#[test]
fn test_supported_quantities_widen_exactly() {
assert_widens_exactly!(u8);
assert_widens_exactly!(u16);
assert_widens_exactly!(u32);
assert_widens_exactly!(u64);
assert_widens_exactly!(u128);
assert_widens_exactly!(usize);
}
}