use std::time::Instant;
use crate::{messages::MessageLevel, progress, progress::Id, Unit};
pub trait NestedProgress: Progress {
type SubProgress: NestedProgress;
fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress;
fn add_child_with_id(&mut self, name: impl Into<String>, id: Id) -> Self::SubProgress;
}
pub trait Count {
fn set(&self, step: progress::Step);
fn step(&self) -> progress::Step;
fn inc_by(&self, step: progress::Step);
fn inc(&self) {
self.inc_by(1)
}
fn counter(&self) -> StepShared;
}
pub trait DynNestedProgress: Progress + impls::Sealed {
fn add_child(&mut self, name: String) -> BoxedDynNestedProgress;
fn add_child_with_id(&mut self, name: String, id: Id) -> BoxedDynNestedProgress;
}
pub struct BoxedDynNestedProgress(Box<dyn DynNestedProgress>);
pub type BoxedProgress = Box<dyn Progress>;
pub struct DynNestedProgressToNestedProgress<T: ?Sized>(pub T);
pub trait Progress: Count + Send + Sync {
fn init(&mut self, max: Option<progress::Step>, unit: Option<Unit>);
fn unit(&self) -> Option<Unit> {
None
}
fn max(&self) -> Option<progress::Step> {
None
}
fn set_max(&mut self, _max: Option<progress::Step>) -> Option<progress::Step> {
None
}
fn set_name(&mut self, name: String);
fn name(&self) -> Option<String>;
fn id(&self) -> Id;
fn message(&self, level: MessageLevel, message: String);
fn info(&self, message: String) {
self.message(MessageLevel::Info, message)
}
fn done(&self, message: String) {
self.message(MessageLevel::Success, message)
}
fn fail(&self, message: String) {
self.message(MessageLevel::Failure, message)
}
fn show_throughput(&self, start: Instant) {
let step = self.step();
match self.unit() {
Some(unit) => self.show_throughput_with(start, step, unit, MessageLevel::Info),
None => {
let elapsed = start.elapsed().as_secs_f32();
let steps_per_second = (step as f32 / elapsed) as progress::Step;
self.info(format!(
"done {} items in {:.02}s ({} items/s)",
step, elapsed, steps_per_second
))
}
};
}
fn show_throughput_with(&self, start: Instant, step: progress::Step, unit: Unit, level: MessageLevel) {
use std::fmt::Write;
let elapsed = start.elapsed().as_secs_f32();
let steps_per_second = (step as f32 / elapsed) as progress::Step;
let mut buf = String::with_capacity(128);
let unit = unit.as_display_value();
let push_unit = |buf: &mut String| {
buf.push(' ');
let len_before_unit = buf.len();
unit.display_unit(buf, step).ok();
if buf.len() == len_before_unit {
buf.pop();
}
};
buf.push_str("done ");
unit.display_current_value(&mut buf, step, None).ok();
push_unit(&mut buf);
buf.write_fmt(format_args!(" in {:.02}s (", elapsed)).ok();
unit.display_current_value(&mut buf, steps_per_second, None).ok();
push_unit(&mut buf);
buf.push_str("/s)");
self.message(level, buf);
}
}
use crate::{
messages::{Message, MessageCopyState},
progress::StepShared,
};
pub trait WeakRoot {
type Root: Root;
fn upgrade(&self) -> Option<Self::Root>;
}
pub trait Root {
type WeakRoot: WeakRoot;
fn messages_capacity(&self) -> usize;
fn num_tasks(&self) -> usize;
fn sorted_snapshot(&self, out: &mut Vec<(progress::Key, progress::Task)>);
fn copy_messages(&self, out: &mut Vec<Message>);
fn copy_new_messages(&self, out: &mut Vec<Message>, prev: Option<MessageCopyState>) -> MessageCopyState;
fn downgrade(&self) -> Self::WeakRoot;
}
mod impls {
use std::{
ops::{Deref, DerefMut},
time::Instant,
};
use crate::traits::{BoxedProgress, Progress};
use crate::{
messages::MessageLevel,
progress::{Id, Step, StepShared},
BoxedDynNestedProgress, Count, DynNestedProgress, DynNestedProgressToNestedProgress, NestedProgress, Unit,
};
pub trait Sealed {}
impl<T> Count for &T
where
T: Count + ?Sized,
{
fn set(&self, step: Step) {
(*self).set(step)
}
fn step(&self) -> Step {
(*self).step()
}
fn inc_by(&self, step: Step) {
(*self).inc_by(step)
}
fn inc(&self) {
(*self).inc()
}
fn counter(&self) -> StepShared {
(*self).counter()
}
}
impl<T> Count for &mut T
where
T: Count + ?Sized,
{
fn set(&self, step: Step) {
self.deref().set(step)
}
fn step(&self) -> Step {
self.deref().step()
}
fn inc_by(&self, step: Step) {
self.deref().inc_by(step)
}
fn inc(&self) {
self.deref().inc()
}
fn counter(&self) -> StepShared {
self.deref().counter()
}
}
impl<T> Progress for &mut T
where
T: Progress + ?Sized,
{
fn init(&mut self, max: Option<Step>, unit: Option<Unit>) {
self.deref_mut().init(max, unit)
}
fn unit(&self) -> Option<Unit> {
self.deref().unit()
}
fn max(&self) -> Option<Step> {
self.deref().max()
}
fn set_max(&mut self, max: Option<Step>) -> Option<Step> {
self.deref_mut().set_max(max)
}
fn set_name(&mut self, name: String) {
self.deref_mut().set_name(name)
}
fn name(&self) -> Option<String> {
self.deref().name()
}
fn id(&self) -> Id {
self.deref().id()
}
fn message(&self, level: MessageLevel, message: String) {
self.deref().message(level, message)
}
fn info(&self, message: String) {
self.deref().info(message)
}
fn done(&self, message: String) {
self.deref().done(message)
}
fn fail(&self, message: String) {
self.deref().fail(message)
}
fn show_throughput(&self, start: Instant) {
self.deref().show_throughput(start)
}
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
self.deref().show_throughput_with(start, step, unit, level)
}
}
impl<T> NestedProgress for &mut T
where
T: NestedProgress + ?Sized,
{
type SubProgress = T::SubProgress;
fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress {
self.deref_mut().add_child(name)
}
fn add_child_with_id(&mut self, name: impl Into<String>, id: Id) -> Self::SubProgress {
self.deref_mut().add_child_with_id(name, id)
}
}
impl<T> Sealed for T where T: NestedProgress + ?Sized {}
impl<T, SubP> DynNestedProgress for T
where
T: NestedProgress<SubProgress = SubP> + ?Sized,
SubP: NestedProgress + 'static,
{
fn add_child(&mut self, name: String) -> BoxedDynNestedProgress {
BoxedDynNestedProgress::new(self.add_child(name))
}
fn add_child_with_id(&mut self, name: String, id: Id) -> BoxedDynNestedProgress {
BoxedDynNestedProgress::new(self.add_child_with_id(name, id))
}
}
impl BoxedDynNestedProgress {
pub fn new(progress: impl DynNestedProgress + 'static) -> Self {
Self(Box::new(progress))
}
}
impl Progress for BoxedDynNestedProgress {
fn init(&mut self, max: Option<Step>, unit: Option<Unit>) {
self.0.init(max, unit)
}
fn unit(&self) -> Option<Unit> {
self.0.unit()
}
fn max(&self) -> Option<Step> {
self.0.max()
}
fn set_max(&mut self, max: Option<Step>) -> Option<Step> {
self.0.set_max(max)
}
fn set_name(&mut self, name: String) {
self.0.set_name(name)
}
fn name(&self) -> Option<String> {
self.0.name()
}
fn id(&self) -> Id {
self.0.id()
}
fn message(&self, level: MessageLevel, message: String) {
self.0.message(level, message)
}
fn show_throughput(&self, start: Instant) {
self.0.show_throughput(start)
}
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
self.0.show_throughput_with(start, step, unit, level)
}
}
impl Progress for BoxedProgress {
fn init(&mut self, max: Option<Step>, unit: Option<Unit>) {
self.deref_mut().init(max, unit)
}
fn unit(&self) -> Option<Unit> {
self.deref().unit()
}
fn max(&self) -> Option<Step> {
self.deref().max()
}
fn set_max(&mut self, max: Option<Step>) -> Option<Step> {
self.deref_mut().set_max(max)
}
fn set_name(&mut self, name: String) {
self.deref_mut().set_name(name)
}
fn name(&self) -> Option<String> {
self.deref().name()
}
fn id(&self) -> Id {
self.deref().id()
}
fn message(&self, level: MessageLevel, message: String) {
self.deref().message(level, message)
}
fn show_throughput(&self, start: Instant) {
self.deref().show_throughput(start)
}
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
self.deref().show_throughput_with(start, step, unit, level)
}
}
impl Count for BoxedDynNestedProgress {
fn set(&self, step: Step) {
self.0.set(step)
}
fn step(&self) -> Step {
self.0.step()
}
fn inc_by(&self, step: Step) {
self.0.inc_by(step)
}
fn inc(&self) {
self.0.inc()
}
fn counter(&self) -> StepShared {
self.0.counter()
}
}
impl Count for BoxedProgress {
fn set(&self, step: Step) {
self.deref().set(step)
}
fn step(&self) -> Step {
self.deref().step()
}
fn inc_by(&self, step: Step) {
self.deref().inc_by(step)
}
fn inc(&self) {
self.deref().inc()
}
fn counter(&self) -> StepShared {
self.deref().counter()
}
}
impl NestedProgress for BoxedDynNestedProgress {
type SubProgress = Self;
fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress {
self.0.add_child(name.into())
}
fn add_child_with_id(&mut self, name: impl Into<String>, id: Id) -> Self::SubProgress {
self.0.add_child_with_id(name.into(), id)
}
}
impl<T> Progress for DynNestedProgressToNestedProgress<T>
where
T: ?Sized + Progress,
{
fn init(&mut self, max: Option<Step>, unit: Option<Unit>) {
self.0.init(max, unit)
}
fn unit(&self) -> Option<Unit> {
self.0.unit()
}
fn max(&self) -> Option<Step> {
self.0.max()
}
fn set_max(&mut self, max: Option<Step>) -> Option<Step> {
self.0.set_max(max)
}
fn set_name(&mut self, name: String) {
self.0.set_name(name)
}
fn name(&self) -> Option<String> {
self.0.name()
}
fn id(&self) -> Id {
self.0.id()
}
fn message(&self, level: MessageLevel, message: String) {
self.0.message(level, message)
}
fn show_throughput(&self, start: Instant) {
self.0.show_throughput(start)
}
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
self.0.show_throughput_with(start, step, unit, level)
}
}
impl<T> Count for DynNestedProgressToNestedProgress<T>
where
T: ?Sized + Count,
{
fn set(&self, step: Step) {
self.0.set(step)
}
fn step(&self) -> Step {
self.0.step()
}
fn inc_by(&self, step: Step) {
self.0.inc_by(step)
}
fn inc(&self) {
self.0.inc()
}
fn counter(&self) -> StepShared {
self.0.counter()
}
}
impl<T> NestedProgress for DynNestedProgressToNestedProgress<T>
where
T: DynNestedProgress + ?Sized,
{
type SubProgress = BoxedDynNestedProgress;
fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress {
self.0.add_child(name.into())
}
fn add_child_with_id(&mut self, name: impl Into<String>, id: Id) -> Self::SubProgress {
self.0.add_child_with_id(name.into(), id)
}
}
}