Skip to content

Commit 24d0b2a

Browse files
committed
feat: Add new trait DynProgress & type BoxedDynProgress
Fixed #21 `DynProgress` is sealed and implemented for any type that implements `Progress`. Signed-off-by: Jiahao XU <[email protected]>
1 parent 3ad8226 commit 24d0b2a

File tree

2 files changed

+341
-3
lines changed

2 files changed

+341
-3
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub mod messages;
6464
pub mod progress;
6565

6666
mod traits;
67-
pub use traits::{Progress, RawProgress, Root, WeakRoot};
67+
pub use traits::{BoxedDynProgress, DynProgress, DynProgressToProgressBridge, Progress, RawProgress, Root, WeakRoot};
6868

6969
mod throughput;
7070
pub use crate::throughput::Throughput;

src/traits.rs

Lines changed: 340 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,79 @@ pub trait Progress: Send + Sync {
154154
}
155155
}
156156

157+
/// An object-safe trait for describing hierarchical progress.
158+
///
159+
/// This will be automatically implemented for any type that implements
160+
/// [`Progress`].
161+
pub trait DynProgress: Send + Sync + impls::Sealed {
162+
/// See [`Progress::add_child`]
163+
fn add_child(&mut self, name: String) -> BoxedDynProgress;
164+
165+
/// See [`Progress::add_child_with_id`]
166+
fn add_child_with_id(&mut self, name: String, id: Id) -> BoxedDynProgress;
167+
168+
/// See [`Progress::init`]
169+
fn init(&mut self, max: Option<progress::Step>, unit: Option<Unit>);
170+
171+
/// See [`Progress::set`]
172+
fn set(&mut self, step: progress::Step);
173+
174+
/// See [`Progress::unit`]
175+
fn unit(&self) -> Option<Unit>;
176+
177+
/// See [`Progress::max`]
178+
fn max(&self) -> Option<progress::Step>;
179+
180+
/// See [`Progress::set_max`]
181+
fn set_max(&mut self, _max: Option<progress::Step>) -> Option<progress::Step>;
182+
183+
/// See [`Progress::step`]
184+
fn step(&self) -> progress::Step;
185+
186+
/// See [`Progress::inc_by`]
187+
fn inc_by(&mut self, step: progress::Step);
188+
189+
/// See [`Progress::inc`]
190+
fn inc(&mut self);
191+
192+
/// See [`Progress::set_name`]
193+
fn set_name(&mut self, name: String);
194+
195+
/// See [`Progress::name`]
196+
fn name(&self) -> Option<String>;
197+
198+
/// See [`Progress::id`]
199+
fn id(&self) -> Id;
200+
201+
/// See [`Progress::message`]
202+
fn message(&self, level: MessageLevel, message: String);
203+
204+
/// See [`Progress::counter`]
205+
fn counter(&self) -> Option<StepShared>;
206+
207+
/// See [`Progress::info`]
208+
fn info(&self, message: String);
209+
210+
/// See [`Progress::done`]
211+
fn done(&self, message: String);
212+
213+
/// See [`Progress::fail`]
214+
fn fail(&self, message: String);
215+
216+
/// See [`Progress::show_throughput`]
217+
fn show_throughput(&self, start: Instant);
218+
219+
/// See [`Progress::show_throughput_with`]
220+
fn show_throughput_with(&self, start: Instant, step: progress::Step, unit: Unit, level: MessageLevel);
221+
}
222+
223+
/// An opaque type for storing [`DynProgress`].
224+
pub struct BoxedDynProgress(Box<dyn DynProgress>);
225+
226+
/// A bridge type that implements [`Progress`] for any type that implements
227+
/// [`DynProgress`].
228+
pub struct DynProgressToProgressBridge<T: ?Sized>(T);
229+
157230
/// A trait for describing non-hierarchical progress.
158231
///
159232
/// It differs by not being able to add child progress dynamically, but in turn is object safe. It's recommended to
@@ -345,13 +418,15 @@ mod impls {
345418
time::Instant,
346419
};
347420

348-
use crate::traits::RawProgress;
349421
use crate::{
350422
messages::MessageLevel,
351423
progress::{Id, Step, StepShared},
352-
Progress, Unit,
424+
traits::RawProgress,
425+
BoxedDynProgress, DynProgress, DynProgressToProgressBridge, Progress, Unit,
353426
};
354427

428+
pub trait Sealed {}
429+
355430
impl<T> RawProgress for T
356431
where
357432
T: Progress,
@@ -515,4 +590,267 @@ mod impls {
515590
self.deref().show_throughput_with(start, step, unit, level)
516591
}
517592
}
593+
594+
impl<T> Sealed for T where T: Progress + ?Sized {}
595+
596+
impl<T, SubP> DynProgress for T
597+
where
598+
T: Progress<SubProgress = SubP> + ?Sized,
599+
SubP: Progress + 'static,
600+
{
601+
fn add_child(&mut self, name: String) -> BoxedDynProgress {
602+
BoxedDynProgress::new(self.add_child(name))
603+
}
604+
605+
fn add_child_with_id(&mut self, name: String, id: Id) -> BoxedDynProgress {
606+
BoxedDynProgress::new(self.add_child_with_id(name, id))
607+
}
608+
609+
fn init(&mut self, max: Option<Step>, unit: Option<Unit>) {
610+
self.init(max, unit)
611+
}
612+
613+
fn set(&mut self, step: Step) {
614+
self.set(step)
615+
}
616+
617+
fn unit(&self) -> Option<Unit> {
618+
self.unit()
619+
}
620+
621+
fn max(&self) -> Option<Step> {
622+
self.max()
623+
}
624+
625+
fn set_max(&mut self, max: Option<Step>) -> Option<Step> {
626+
self.set_max(max)
627+
}
628+
629+
fn step(&self) -> Step {
630+
self.step()
631+
}
632+
633+
fn inc_by(&mut self, step: Step) {
634+
self.inc_by(step)
635+
}
636+
637+
fn inc(&mut self) {
638+
self.inc()
639+
}
640+
641+
fn set_name(&mut self, name: String) {
642+
self.set_name(name)
643+
}
644+
645+
fn name(&self) -> Option<String> {
646+
self.name()
647+
}
648+
649+
fn id(&self) -> Id {
650+
self.id()
651+
}
652+
653+
fn message(&self, level: MessageLevel, message: String) {
654+
self.message(level, message)
655+
}
656+
657+
fn counter(&self) -> Option<StepShared> {
658+
self.counter()
659+
}
660+
661+
fn info(&self, message: String) {
662+
self.info(message)
663+
}
664+
fn done(&self, message: String) {
665+
self.done(message)
666+
}
667+
fn fail(&self, message: String) {
668+
self.fail(message)
669+
}
670+
671+
fn show_throughput(&self, start: Instant) {
672+
self.show_throughput(start)
673+
}
674+
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
675+
self.show_throughput_with(start, step, unit, level)
676+
}
677+
}
678+
679+
impl BoxedDynProgress {
680+
/// Create new boxed dyn Progress
681+
pub fn new(progress: impl DynProgress + 'static) -> Self {
682+
Self(Box::new(progress))
683+
}
684+
}
685+
686+
impl Progress for BoxedDynProgress {
687+
type SubProgress = Self;
688+
689+
fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress {
690+
self.0.add_child(name.into())
691+
}
692+
693+
fn add_child_with_id(&mut self, name: impl Into<String>, id: Id) -> Self::SubProgress {
694+
self.0.add_child_with_id(name.into(), id)
695+
}
696+
697+
fn init(&mut self, max: Option<Step>, unit: Option<Unit>) {
698+
self.0.init(max, unit)
699+
}
700+
701+
fn set(&mut self, step: Step) {
702+
self.0.set(step)
703+
}
704+
705+
fn unit(&self) -> Option<Unit> {
706+
self.0.unit()
707+
}
708+
709+
fn max(&self) -> Option<Step> {
710+
self.0.max()
711+
}
712+
713+
fn set_max(&mut self, max: Option<Step>) -> Option<Step> {
714+
self.0.set_max(max)
715+
}
716+
717+
fn step(&self) -> Step {
718+
self.0.step()
719+
}
720+
721+
fn inc_by(&mut self, step: Step) {
722+
self.0.inc_by(step)
723+
}
724+
725+
fn inc(&mut self) {
726+
self.0.inc()
727+
}
728+
729+
fn set_name(&mut self, name: impl Into<String>) {
730+
self.0.set_name(name.into())
731+
}
732+
733+
fn name(&self) -> Option<String> {
734+
self.0.name()
735+
}
736+
737+
fn id(&self) -> Id {
738+
self.0.id()
739+
}
740+
741+
fn message(&self, level: MessageLevel, message: impl Into<String>) {
742+
self.0.message(level, message.into())
743+
}
744+
745+
fn counter(&self) -> Option<StepShared> {
746+
self.0.counter()
747+
}
748+
749+
fn info(&self, message: impl Into<String>) {
750+
self.0.info(message.into())
751+
}
752+
753+
fn done(&self, message: impl Into<String>) {
754+
self.0.done(message.into())
755+
}
756+
757+
fn fail(&self, message: impl Into<String>) {
758+
self.0.fail(message.into())
759+
}
760+
761+
fn show_throughput(&self, start: Instant) {
762+
self.0.show_throughput(start)
763+
}
764+
765+
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
766+
self.0.show_throughput_with(start, step, unit, level)
767+
}
768+
}
769+
770+
impl<T> Progress for DynProgressToProgressBridge<T>
771+
where
772+
T: DynProgress + ?Sized,
773+
{
774+
type SubProgress = BoxedDynProgress;
775+
776+
fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress {
777+
self.0.add_child(name.into())
778+
}
779+
780+
fn add_child_with_id(&mut self, name: impl Into<String>, id: Id) -> Self::SubProgress {
781+
self.0.add_child_with_id(name.into(), id)
782+
}
783+
784+
fn init(&mut self, max: Option<Step>, unit: Option<Unit>) {
785+
self.0.init(max, unit)
786+
}
787+
788+
fn set(&mut self, step: Step) {
789+
self.0.set(step)
790+
}
791+
792+
fn unit(&self) -> Option<Unit> {
793+
self.0.unit()
794+
}
795+
796+
fn max(&self) -> Option<Step> {
797+
self.0.max()
798+
}
799+
800+
fn set_max(&mut self, max: Option<Step>) -> Option<Step> {
801+
self.0.set_max(max)
802+
}
803+
804+
fn step(&self) -> Step {
805+
self.0.step()
806+
}
807+
808+
fn inc_by(&mut self, step: Step) {
809+
self.0.inc_by(step)
810+
}
811+
812+
fn inc(&mut self) {
813+
self.0.inc()
814+
}
815+
816+
fn set_name(&mut self, name: impl Into<String>) {
817+
self.0.set_name(name.into())
818+
}
819+
820+
fn name(&self) -> Option<String> {
821+
self.0.name()
822+
}
823+
824+
fn id(&self) -> Id {
825+
self.0.id()
826+
}
827+
828+
fn message(&self, level: MessageLevel, message: impl Into<String>) {
829+
self.0.message(level, message.into())
830+
}
831+
832+
fn counter(&self) -> Option<StepShared> {
833+
self.0.counter()
834+
}
835+
836+
fn info(&self, message: impl Into<String>) {
837+
self.0.info(message.into())
838+
}
839+
840+
fn done(&self, message: impl Into<String>) {
841+
self.0.done(message.into())
842+
}
843+
844+
fn fail(&self, message: impl Into<String>) {
845+
self.0.fail(message.into())
846+
}
847+
848+
fn show_throughput(&self, start: Instant) {
849+
self.0.show_throughput(start)
850+
}
851+
852+
fn show_throughput_with(&self, start: Instant, step: Step, unit: Unit, level: MessageLevel) {
853+
self.0.show_throughput_with(start, step, unit, level)
854+
}
855+
}
518856
}

0 commit comments

Comments
 (0)