1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
//! Various `prodash` types along with various utilities for comfort.
use std::io;
#[cfg(feature = "progress-unit-bytes")]
pub use bytesize;
pub use prodash::{
self,
messages::MessageLevel,
progress::{Discard, DoOrDiscard, Either, Id, Step, StepShared, Task, ThroughputOnDrop, Value, UNKNOWN},
unit, Progress, RawProgress, Unit,
};
/// A stub for the portions of the `bytesize` crate that we use internally in `gitoxide`.
#[cfg(not(feature = "progress-unit-bytes"))]
pub mod bytesize {
/// A stub for the `ByteSize` wrapper.
pub struct ByteSize(pub u64);
impl std::fmt::Display for ByteSize {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
}
/// A unit for displaying bytes with throughput and progress percentage.
#[cfg(feature = "progress-unit-bytes")]
pub fn bytes() -> Option<Unit> {
Some(unit::dynamic_and_mode(
unit::Bytes,
unit::display::Mode::with_throughput().and_percentage(),
))
}
/// A unit for displaying bytes with throughput and progress percentage.
#[cfg(not(feature = "progress-unit-bytes"))]
pub fn bytes() -> Option<Unit> {
Some(unit::label_and_mode(
"B",
unit::display::Mode::with_throughput().and_percentage(),
))
}
/// A unit for displaying human readable numbers with throughput and progress percentage, and a single decimal place.
pub fn count(name: &'static str) -> Option<Unit> {
count_with_decimals(name, 1)
}
/// A unit for displaying human readable numbers with `name` suffix,
/// with throughput and progress percentage, and `decimals` decimal places.
#[cfg(feature = "progress-unit-human-numbers")]
pub fn count_with_decimals(name: &'static str, decimals: usize) -> Option<Unit> {
Some(unit::dynamic_and_mode(
unit::Human::new(
{
let mut f = unit::human::Formatter::new();
f.with_decimals(decimals);
f
},
name,
),
unit::display::Mode::with_throughput().and_percentage(),
))
}
/// A unit for displaying human readable numbers with `name` suffix,
/// with throughput and progress percentage, and `decimals` decimal places.
#[cfg(not(feature = "progress-unit-human-numbers"))]
pub fn count_with_decimals(name: &'static str, _decimals: usize) -> Option<Unit> {
Some(unit::label_and_mode(
name,
unit::display::Mode::with_throughput().and_percentage(),
))
}
/// A predefined unit for displaying a multi-step progress
pub fn steps() -> Option<Unit> {
Some(unit::dynamic(unit::Range::new("steps")))
}
/// A structure passing every [`read`][std::io::Read::read()] call through to the contained Progress instance using [`inc_by(bytes_read)`][Progress::inc_by()].
pub struct Read<T, P> {
/// The implementor of [`std::io::Read`] to which progress is added
pub inner: T,
/// The progress instance receiving progress information on each invocation of `reader`
pub progress: P,
}
impl<T, P> io::Read for Read<T, P>
where
T: io::Read,
P: Progress,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let bytes_read = self.inner.read(buf)?;
self.progress.inc_by(bytes_read);
Ok(bytes_read)
}
}
impl<T, P> io::BufRead for Read<T, P>
where
T: io::BufRead,
P: Progress,
{
fn fill_buf(&mut self) -> io::Result<&[u8]> {
self.inner.fill_buf()
}
fn consume(&mut self, amt: usize) {
self.inner.consume(amt)
}
}
/// A structure passing every [`write`][std::io::Write::write()] call through to the contained Progress instance using [`inc_by(bytes_written)`][Progress::inc_by()].
///
/// This is particularly useful if the final size of the bytes to write is known or can be estimated precisely enough.
pub struct Write<T, P> {
/// The implementor of [`std::io::Write`] to which progress is added
pub inner: T,
/// The progress instance receiving progress information on each invocation of `reader`
pub progress: P,
}
impl<T, P> io::Write for Write<T, P>
where
T: io::Write,
P: Progress,
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let written = self.inner.write(buf)?;
self.progress.inc_by(written);
Ok(written)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}