use std::{
borrow::Cow,
marker::PhantomData,
sync::{
Arc,
atomic::{AtomicU64, Ordering},
},
};
use crate::Step;
pub trait NamedStep: 'static + Send + Sync + Default {
fn name(&self) -> &'static str;
}
#[derive(Debug, Clone)]
pub struct AtomicSubStep<Name: NamedStep> {
unit_name: Name,
current: Arc<AtomicU64>,
total: u64,
}
impl<Name: NamedStep> AtomicSubStep<Name> {
pub fn new(total: u64) -> (Arc<AtomicU64>, Self) {
let current = Arc::new(AtomicU64::new(0));
(
current.clone(),
Self {
current,
total,
unit_name: Name::default(),
},
)
}
}
impl<Name: NamedStep> Step for AtomicSubStep<Name> {
fn name(&self) -> Cow<'static, str> {
self.unit_name.name().into()
}
fn current(&self) -> u64 {
self.current.load(Ordering::Relaxed)
}
fn total(&self) -> u64 {
self.total
}
}
#[macro_export]
macro_rules! make_enum_progress {
($visibility:vis enum $name:ident { $($variant:ident,)+ }) => {
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(clippy::enum_variant_names)]
$visibility enum $name {
$($variant),+
}
impl $crate::Step for $name {
fn name(&self) -> std::borrow::Cow<'static, str> {
use $crate::_private_convert_case::Casing;
match self {
$(
$name::$variant => stringify!($variant).from_case($crate::_private_convert_case::Case::Camel).to_case($crate::_private_convert_case::Case::Lower).into()
),+
}
}
fn current(&self) -> u64 {
*self as u64
}
fn total(&self) -> u64 {
use $crate::_internal_count;
$crate::_internal_count!($($variant)+) as u64
}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! _internal_count {
() => (0u64);
( $x:ident ) => (1u64);
( $x:ident $($xs:ident)* ) => (1u64 + $crate::_internal_count!($($xs)*));
}
#[macro_export]
macro_rules! make_atomic_progress {
($struct_name:ident alias $atomic_struct_name:ident => $step_name:literal) => {
#[derive(Default, Debug, Clone, Copy)]
pub struct $struct_name {}
impl $crate::NamedStep for $struct_name {
fn name(&self) -> &'static str {
$step_name
}
}
pub type $atomic_struct_name = $crate::AtomicSubStep<$struct_name>;
};
}
#[derive(Debug, Clone)]
pub struct VariableNameStep<U: Send + Sync + 'static> {
name: String,
current: u64,
total: u64,
phantom: PhantomData<U>,
}
impl<U: Send + Sync + 'static> VariableNameStep<U> {
pub fn new(name: impl Into<String>, current: u64, total: u64) -> Self {
Self {
name: name.into(),
current,
total,
phantom: PhantomData,
}
}
}
impl<U: Send + Sync + 'static> Step for VariableNameStep<U> {
fn name(&self) -> Cow<'static, str> {
self.name.clone().into()
}
fn current(&self) -> u64 {
self.current
}
fn total(&self) -> u64 {
self.total
}
}