use std::{any::Any, mem};
mod any_counter;
mod collection;
mod into_counter;
mod sealed;
mod uint;
pub(crate) use self::{
any_counter::{AnyCounter, KnownCounterKind},
collection::{CounterCollection, CounterSet},
sealed::Sealed,
uint::{AsCountUInt, CountUInt, MaxCountUInt},
};
pub use into_counter::IntoCounter;
#[doc(alias = "throughput")]
pub trait Counter: Sized + Any + Sealed {}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct BytesCount {
count: MaxCountUInt,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct CharsCount {
count: MaxCountUInt,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ItemsCount {
count: MaxCountUInt,
}
impl Sealed for BytesCount {}
impl Sealed for CharsCount {}
impl Sealed for ItemsCount {}
impl Counter for BytesCount {}
impl Counter for CharsCount {}
impl Counter for ItemsCount {}
impl<C: AsCountUInt> From<C> for BytesCount {
#[inline]
fn from(count: C) -> Self {
Self::new(count.as_max_uint())
}
}
impl<C: AsCountUInt> From<C> for CharsCount {
#[inline]
fn from(count: C) -> Self {
Self::new(count.as_max_uint())
}
}
impl<C: AsCountUInt> From<C> for ItemsCount {
#[inline]
fn from(count: C) -> Self {
Self::new(count.as_max_uint())
}
}
impl BytesCount {
#[inline]
pub fn new<N: CountUInt>(count: N) -> Self {
Self { count: count.into_max_uint() }
}
#[inline]
#[doc(alias = "size_of")]
pub const fn of<T>() -> Self {
Self { count: mem::size_of::<T>() as MaxCountUInt }
}
#[inline]
#[doc(alias = "size_of")]
pub const fn of_many<T>(n: usize) -> Self {
match (mem::size_of::<T>() as MaxCountUInt).checked_mul(n as MaxCountUInt) {
Some(count) => Self { count },
None => panic!("overflow"),
}
}
#[inline]
#[doc(alias = "size_of_val")]
pub fn of_val<T: ?Sized>(val: &T) -> Self {
Self { count: mem::size_of_val(val) as MaxCountUInt }
}
#[inline]
pub fn of_iter<T, I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
Self::new(mem::size_of::<T>() * iter.into_iter().count())
}
#[inline]
pub fn of_str<S: ?Sized + AsRef<str>>(s: &S) -> Self {
Self::of_val(s.as_ref())
}
#[inline]
pub fn of_slice<T, S: ?Sized + AsRef<[T]>>(s: &S) -> Self {
Self::of_val(s.as_ref())
}
}
macro_rules! type_bytes {
($ty:ident) => {
#[doc = concat!("[`", stringify!($ty), "`s](", stringify!($ty), ").")]
#[inline]
pub const fn $ty(n: usize) -> Self {
Self::of_many::<$ty>(n)
}
};
}
impl BytesCount {
type_bytes!(f32);
type_bytes!(f64);
type_bytes!(i8);
type_bytes!(u8);
type_bytes!(i16);
type_bytes!(u16);
type_bytes!(i32);
type_bytes!(u32);
type_bytes!(i64);
type_bytes!(u64);
type_bytes!(i128);
type_bytes!(u128);
type_bytes!(isize);
type_bytes!(usize);
}
impl CharsCount {
#[inline]
pub fn new<N: CountUInt>(count: N) -> Self {
Self { count: count.into_max_uint() }
}
#[inline]
pub fn of_str<S: ?Sized + AsRef<str>>(s: &S) -> Self {
Self::new(s.as_ref().chars().count())
}
}
impl ItemsCount {
#[inline]
pub fn new<N: CountUInt>(count: N) -> Self {
Self { count: count.into_max_uint() }
}
#[inline]
pub fn of_iter<T, I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
Self::new(iter.into_iter().count())
}
}
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum BytesFormat {
#[default]
Decimal,
Binary,
}
#[derive(Clone, Copy)]
pub(crate) struct PrivBytesFormat(pub BytesFormat);
impl clap::ValueEnum for PrivBytesFormat {
fn value_variants<'a>() -> &'a [Self] {
&[Self(BytesFormat::Decimal), Self(BytesFormat::Binary)]
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
let name = match self.0 {
BytesFormat::Decimal => "decimal",
BytesFormat::Binary => "binary",
};
Some(clap::builder::PossibleValue::new(name))
}
}
#[cfg(test)]
mod tests {
use super::*;
mod bytes_count {
use super::*;
#[test]
fn of_iter() {
assert_eq!(BytesCount::of_iter::<i32, _>([1, 2, 3]), BytesCount::of_slice(&[1, 2, 3]));
}
}
}