Skip to content

Commit

Permalink
feat: Add new trait DynProgress & type BoxedDynProgress
Browse files Browse the repository at this point in the history
Fixed Byron#21

`DynProgress` is sealed and implemented for any type that implements
`Progress`.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
  • Loading branch information
NobodyXu committed Aug 19, 2023
1 parent 3ad8226 commit 44c3773
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub mod messages;
pub mod progress;

mod traits;
pub use traits::{Progress, RawProgress, Root, WeakRoot};
pub use traits::{BoxedDynProgress, DynProgress, Progress, RawProgress, Root, WeakRoot};

mod throughput;
pub use crate::throughput::Throughput;
Expand Down
170 changes: 168 additions & 2 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,79 @@ pub trait Progress: Send + Sync {
}
}

/// An object-safe trait for describing hierarchical progress.
///
/// This will be automatically implemented for any type that implements
/// [`Progress`].
pub trait DynProgress: Send + Sync + impls::Sealed {
/// See [`Progress::add_child`]
fn add_child(&mut self, name: String) -> BoxedDynProgress<'_>;

/// See [`Progress::add_child_with_id`]
fn add_child_with_id(&mut self, name: String, id: Id) -> BoxedDynProgress<'_>;

/// See [`Progress::init`]
fn init(&mut self, max: Option<progress::Step>, unit: Option<Unit>);

/// See [`Progress::set`]
fn set(&mut self, step: progress::Step);

/// See [`Progress::unit`]
fn unit(&self) -> Option<Unit>;

/// See [`Progress::max`]
fn max(&self) -> Option<progress::Step>;

/// See [`Progress::set_max`]
fn set_max(&mut self, _max: Option<progress::Step>) -> Option<progress::Step>;

/// See [`Progress::step`]
fn step(&self) -> progress::Step;

/// See [`Progress::inc_by`]
fn inc_by(&mut self, step: progress::Step);

/// See [`Progress::inc`]
fn inc(&mut self);

/// See [`Progress::set_name`]
fn set_name(&mut self, name: String);

/// See [`Progress::name`]
fn name(&self) -> Option<String>;

/// See [`Progress::id`]
fn id(&self) -> Id;

/// See [`Progress::message`]
fn message(&self, level: MessageLevel, message: String);

/// See [`Progress::counter`]
fn counter(&self) -> Option<StepShared>;

/// See [`Progress::info`]
fn info(&self, message: String);

/// See [`Progress::done`]
fn done(&self, message: String);

/// See [`Progress::fail`]
fn fail(&self, message: String);

/// See [`Progress::show_throughput`]
fn show_throughput(&self, start: Instant);

/// See [`Progress::show_throughput_with`]
fn show_throughput_with(&self, start: Instant, step: progress::Step, unit: Unit, level: MessageLevel);
}

//#[derive(Debug)]
//pub struct DynProgressWrapper<T: ?Sized>(T);

/// An opaque type so that `gix` can internally change its implementation details,
/// e.g. use an `Arc` instead of `Box`, or even inlining the progress.
pub struct BoxedDynProgress<'a>(Box<dyn DynProgress + 'a>);

/// A trait for describing non-hierarchical progress.
///
/// It differs by not being able to add child progress dynamically, but in turn is object safe. It's recommended to
Expand Down Expand Up @@ -345,13 +418,15 @@ mod impls {
time::Instant,
};

use crate::traits::RawProgress;
use crate::{
messages::MessageLevel,
progress::{Id, Step, StepShared},
Progress, Unit,
traits::RawProgress,
BoxedDynProgress, DynProgress, Progress, Unit,
};

pub trait Sealed {}

impl<T> RawProgress for T
where
T: Progress,
Expand Down Expand Up @@ -515,4 +590,95 @@ mod impls {
self.deref().show_throughput_with(start, step, unit, level)
}
}

impl<T> Sealed for T where T: Progress + ?Sized {}

impl<T> DynProgress for T
where
T: Progress + ?Sized,
{
fn add_child(&mut self, name: String) -> BoxedDynProgress<'_> {
BoxedDynProgress::new(self.add_child(name))
}

fn add_child_with_id(&mut self, name: String, id: Id) -> BoxedDynProgress<'_> {
BoxedDynProgress::new(self.add_child_with_id(name, id))
}

fn init(&mut self, max: Option<Step>, unit: Option<Unit>) {
self.init(max, unit)
}

fn set(&mut self, step: Step) {
self.set(step)
}

fn unit(&self) -> Option<Unit> {
self.unit()
}

fn max(&self) -> Option<Step> {
self.max()
}

fn set_max(&mut self, max: Option<Step>) -> Option<Step> {
self.set_max(max)
}

fn step(&self) -> Step {
self.step()
}

fn inc_by(&mut self, step: Step) {
self.inc_by(step)
}

fn inc(&mut self) {
self.inc()
}

fn set_name(&mut self, name: String) {
self.set_name(name)
}

fn name(&self) -> Option<String> {
self.name()
}

fn id(&self) -> Id {
self.id()
}

fn message(&self, level: MessageLevel, message: String) {
self.message(level, message)
}

fn counter(&self) -> Option<StepShared> {
self.counter()
}

fn info(&self, message: String) {
self.info(message)
}
fn done(&self, message: String) {
self.done(message)
}
fn fail(&self, message: String) {
self.fail(message)
}

fn show_throughput(&self, start: Instant) {
self.show_throughput(start)
}
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
self.show_throughput_with(start, step, unit, level)
}
}

impl<'a> BoxedDynProgress<'a> {
/// Create new boxed dyn Progress
pub fn new(progress: impl DynProgress + 'a) -> Self {
Self(Box::new(progress))
}
}
}

0 comments on commit 44c3773

Please sign in to comment.