aboutsummaryrefslogtreecommitdiff
path: root/vendor/indicatif/src/progress_bar.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
committerValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
commita990de90fe41456a23e58bd087d2f107d321f3a1 (patch)
tree15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/indicatif/src/progress_bar.rs
parent3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff)
downloadfparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz
fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip
Deleted vendor folder
Diffstat (limited to 'vendor/indicatif/src/progress_bar.rs')
-rw-r--r--vendor/indicatif/src/progress_bar.rs808
1 files changed, 0 insertions, 808 deletions
diff --git a/vendor/indicatif/src/progress_bar.rs b/vendor/indicatif/src/progress_bar.rs
deleted file mode 100644
index 938668e..0000000
--- a/vendor/indicatif/src/progress_bar.rs
+++ /dev/null
@@ -1,808 +0,0 @@
-#[cfg(test)]
-use portable_atomic::{AtomicBool, Ordering};
-use std::borrow::Cow;
-use std::sync::{Arc, Condvar, Mutex, MutexGuard, Weak};
-use std::time::Duration;
-#[cfg(not(target_arch = "wasm32"))]
-use std::time::Instant;
-use std::{fmt, io, thread};
-
-#[cfg(target_arch = "wasm32")]
-use instant::Instant;
-#[cfg(test)]
-use once_cell::sync::Lazy;
-
-use crate::draw_target::ProgressDrawTarget;
-use crate::state::{AtomicPosition, BarState, ProgressFinish, Reset, TabExpandedString};
-use crate::style::ProgressStyle;
-use crate::{ProgressBarIter, ProgressIterator, ProgressState};
-
-/// A progress bar or spinner
-///
-/// The progress bar is an [`Arc`] around its internal state. When the progress bar is cloned it
-/// just increments the refcount (so the original and its clone share the same state).
-#[derive(Clone)]
-pub struct ProgressBar {
- state: Arc<Mutex<BarState>>,
- pos: Arc<AtomicPosition>,
- ticker: Arc<Mutex<Option<Ticker>>>,
-}
-
-impl fmt::Debug for ProgressBar {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("ProgressBar").finish()
- }
-}
-
-impl ProgressBar {
- /// Creates a new progress bar with a given length
- ///
- /// This progress bar by default draws directly to stderr, and refreshes a maximum of 15 times
- /// a second. To change the refresh rate, set the draw target to one with a different refresh
- /// rate.
- pub fn new(len: u64) -> Self {
- Self::with_draw_target(Some(len), ProgressDrawTarget::stderr())
- }
-
- /// Creates a completely hidden progress bar
- ///
- /// This progress bar still responds to API changes but it does not have a length or render in
- /// any way.
- pub fn hidden() -> Self {
- Self::with_draw_target(None, ProgressDrawTarget::hidden())
- }
-
- /// Creates a new progress bar with a given length and draw target
- pub fn with_draw_target(len: Option<u64>, draw_target: ProgressDrawTarget) -> Self {
- let pos = Arc::new(AtomicPosition::new());
- Self {
- state: Arc::new(Mutex::new(BarState::new(len, draw_target, pos.clone()))),
- pos,
- ticker: Arc::new(Mutex::new(None)),
- }
- }
-
- /// Get a clone of the current progress bar style.
- pub fn style(&self) -> ProgressStyle {
- self.state().style.clone()
- }
-
- /// A convenience builder-like function for a progress bar with a given style
- pub fn with_style(self, style: ProgressStyle) -> Self {
- self.set_style(style);
- self
- }
-
- /// A convenience builder-like function for a progress bar with a given tab width
- pub fn with_tab_width(self, tab_width: usize) -> Self {
- self.state().set_tab_width(tab_width);
- self
- }
-
- /// A convenience builder-like function for a progress bar with a given prefix
- ///
- /// For the prefix to be visible, the `{prefix}` placeholder must be present in the template
- /// (see [`ProgressStyle`]).
- pub fn with_prefix(self, prefix: impl Into<Cow<'static, str>>) -> Self {
- let mut state = self.state();
- state.state.prefix = TabExpandedString::new(prefix.into(), state.tab_width);
- drop(state);
- self
- }
-
- /// A convenience builder-like function for a progress bar with a given message
- ///
- /// For the message to be visible, the `{msg}` placeholder must be present in the template (see
- /// [`ProgressStyle`]).
- pub fn with_message(self, message: impl Into<Cow<'static, str>>) -> Self {
- let mut state = self.state();
- state.state.message = TabExpandedString::new(message.into(), state.tab_width);
- drop(state);
- self
- }
-
- /// A convenience builder-like function for a progress bar with a given position
- pub fn with_position(self, pos: u64) -> Self {
- self.state().state.set_pos(pos);
- self
- }
-
- /// A convenience builder-like function for a progress bar with a given elapsed time
- pub fn with_elapsed(self, elapsed: Duration) -> Self {
- self.state().state.started = Instant::now().checked_sub(elapsed).unwrap();
- self
- }
-
- /// Sets the finish behavior for the progress bar
- ///
- /// This behavior is invoked when [`ProgressBar`] or
- /// [`ProgressBarIter`] completes and
- /// [`ProgressBar::is_finished()`] is false.
- /// If you don't want the progress bar to be automatically finished then
- /// call `on_finish(None)`.
- ///
- /// [`ProgressBar`]: crate::ProgressBar
- /// [`ProgressBarIter`]: crate::ProgressBarIter
- /// [`ProgressBar::is_finished()`]: crate::ProgressBar::is_finished
- pub fn with_finish(self, finish: ProgressFinish) -> Self {
- self.state().on_finish = finish;
- self
- }
-
- /// Creates a new spinner
- ///
- /// This spinner by default draws directly to stderr. This adds the default spinner style to it.
- pub fn new_spinner() -> Self {
- let rv = Self::with_draw_target(None, ProgressDrawTarget::stderr());
- rv.set_style(ProgressStyle::default_spinner());
- rv
- }
-
- /// Overrides the stored style
- ///
- /// This does not redraw the bar. Call [`ProgressBar::tick()`] to force it.
- pub fn set_style(&self, style: ProgressStyle) {
- self.state().set_style(style);
- }
-
- /// Sets the tab width (default: 8). All tabs will be expanded to this many spaces.
- pub fn set_tab_width(&mut self, tab_width: usize) {
- let mut state = self.state();
- state.set_tab_width(tab_width);
- state.draw(true, Instant::now()).unwrap();
- }
-
- /// Spawns a background thread to tick the progress bar
- ///
- /// When this is enabled a background thread will regularly tick the progress bar in the given
- /// interval. This is useful to advance progress bars that are very slow by themselves.
- ///
- /// When steady ticks are enabled, calling [`ProgressBar::tick()`] on a progress bar does not
- /// have any effect.
- pub fn enable_steady_tick(&self, interval: Duration) {
- // The way we test for ticker termination is with a single static `AtomicBool`. Since cargo
- // runs tests concurrently, we have a `TICKER_TEST` lock to make sure tests using ticker
- // don't step on each other. This check catches attempts to use tickers in tests without
- // acquiring the lock.
- #[cfg(test)]
- {
- let guard = TICKER_TEST.try_lock();
- let lock_acquired = guard.is_ok();
- // Drop the guard before panicking to avoid poisoning the lock (which would cause other
- // ticker tests to fail)
- drop(guard);
- if lock_acquired {
- panic!("you must acquire the TICKER_TEST lock in your test to use this method");
- }
- }
-
- if interval.is_zero() {
- return;
- }
-
- self.stop_and_replace_ticker(Some(interval));
- }
-
- /// Undoes [`ProgressBar::enable_steady_tick()`]
- pub fn disable_steady_tick(&self) {
- self.stop_and_replace_ticker(None);
- }
-
- fn stop_and_replace_ticker(&self, interval: Option<Duration>) {
- let mut ticker_state = self.ticker.lock().unwrap();
- if let Some(ticker) = ticker_state.take() {
- ticker.stop();
- }
-
- *ticker_state = interval.map(|interval| Ticker::new(interval, &self.state));
- }
-
- /// Manually ticks the spinner or progress bar
- ///
- /// This automatically happens on any other change to a progress bar.
- pub fn tick(&self) {
- self.tick_inner(Instant::now());
- }
-
- fn tick_inner(&self, now: Instant) {
- // Only tick if a `Ticker` isn't installed
- if self.ticker.lock().unwrap().is_none() {
- self.state().tick(now);
- }
- }
-
- /// Advances the position of the progress bar by `delta`
- pub fn inc(&self, delta: u64) {
- self.pos.inc(delta);
- let now = Instant::now();
- if self.pos.allow(now) {
- self.tick_inner(now);
- }
- }
-
- /// A quick convenience check if the progress bar is hidden
- pub fn is_hidden(&self) -> bool {
- self.state().draw_target.is_hidden()
- }
-
- /// Indicates that the progress bar finished
- pub fn is_finished(&self) -> bool {
- self.state().state.is_finished()
- }
-
- /// Print a log line above the progress bar
- ///
- /// If the progress bar is hidden (e.g. when standard output is not a terminal), `println()`
- /// will not do anything. If you want to write to the standard output in such cases as well, use
- /// [`suspend`] instead.
- ///
- /// If the progress bar was added to a [`MultiProgress`], the log line will be
- /// printed above all other progress bars.
- ///
- /// [`suspend`]: ProgressBar::suspend
- /// [`MultiProgress`]: crate::MultiProgress
- pub fn println<I: AsRef<str>>(&self, msg: I) {
- self.state().println(Instant::now(), msg.as_ref());
- }
-
- /// Update the `ProgressBar`'s inner [`ProgressState`]
- pub fn update(&self, f: impl FnOnce(&mut ProgressState)) {
- self.state()
- .update(Instant::now(), f, self.ticker.lock().unwrap().is_none());
- }
-
- /// Sets the position of the progress bar
- pub fn set_position(&self, pos: u64) {
- self.pos.set(pos);
- let now = Instant::now();
- if self.pos.allow(now) {
- self.tick_inner(now);
- }
- }
-
- /// Sets the length of the progress bar
- pub fn set_length(&self, len: u64) {
- self.state().set_length(Instant::now(), len);
- }
-
- /// Increase the length of the progress bar
- pub fn inc_length(&self, delta: u64) {
- self.state().inc_length(Instant::now(), delta);
- }
-
- /// Sets the current prefix of the progress bar
- ///
- /// For the prefix to be visible, the `{prefix}` placeholder must be present in the template
- /// (see [`ProgressStyle`]).
- pub fn set_prefix(&self, prefix: impl Into<Cow<'static, str>>) {
- let mut state = self.state();
- state.state.prefix = TabExpandedString::new(prefix.into(), state.tab_width);
- state.update_estimate_and_draw(Instant::now());
- }
-
- /// Sets the current message of the progress bar
- ///
- /// For the message to be visible, the `{msg}` placeholder must be present in the template (see
- /// [`ProgressStyle`]).
- pub fn set_message(&self, msg: impl Into<Cow<'static, str>>) {
- let mut state = self.state();
- state.state.message = TabExpandedString::new(msg.into(), state.tab_width);
- state.update_estimate_and_draw(Instant::now());
- }
-
- /// Creates a new weak reference to this `ProgressBar`
- pub fn downgrade(&self) -> WeakProgressBar {
- WeakProgressBar {
- state: Arc::downgrade(&self.state),
- pos: Arc::downgrade(&self.pos),
- ticker: Arc::downgrade(&self.ticker),
- }
- }
-
- /// Resets the ETA calculation
- ///
- /// This can be useful if the progress bars made a large jump or was paused for a prolonged
- /// time.
- pub fn reset_eta(&self) {
- self.state().reset(Instant::now(), Reset::Eta);
- }
-
- /// Resets elapsed time and the ETA calculation
- pub fn reset_elapsed(&self) {
- self.state().reset(Instant::now(), Reset::Elapsed);
- }
-
- /// Resets all of the progress bar state
- pub fn reset(&self) {
- self.state().reset(Instant::now(), Reset::All);
- }
-
- /// Finishes the progress bar and leaves the current message
- pub fn finish(&self) {
- self.state()
- .finish_using_style(Instant::now(), ProgressFinish::AndLeave);
- }
-
- /// Finishes the progress bar and sets a message
- ///
- /// For the message to be visible, the `{msg}` placeholder must be present in the template (see
- /// [`ProgressStyle`]).
- pub fn finish_with_message(&self, msg: impl Into<Cow<'static, str>>) {
- self.state()
- .finish_using_style(Instant::now(), ProgressFinish::WithMessage(msg.into()));
- }
-
- /// Finishes the progress bar and completely clears it
- pub fn finish_and_clear(&self) {
- self.state()
- .finish_using_style(Instant::now(), ProgressFinish::AndClear);
- }
-
- /// Finishes the progress bar and leaves the current message and progress
- pub fn abandon(&self) {
- self.state()
- .finish_using_style(Instant::now(), ProgressFinish::Abandon);
- }
-
- /// Finishes the progress bar and sets a message, and leaves the current progress
- ///
- /// For the message to be visible, the `{msg}` placeholder must be present in the template (see
- /// [`ProgressStyle`]).
- pub fn abandon_with_message(&self, msg: impl Into<Cow<'static, str>>) {
- self.state().finish_using_style(
- Instant::now(),
- ProgressFinish::AbandonWithMessage(msg.into()),
- );
- }
-
- /// Finishes the progress bar using the behavior stored in the [`ProgressStyle`]
- ///
- /// See [`ProgressBar::with_finish()`].
- pub fn finish_using_style(&self) {
- let mut state = self.state();
- let finish = state.on_finish.clone();
- state.finish_using_style(Instant::now(), finish);
- }
-
- /// Sets a different draw target for the progress bar
- ///
- /// This can be used to draw the progress bar to stderr (this is the default):
- ///
- /// ```rust,no_run
- /// # use indicatif::{ProgressBar, ProgressDrawTarget};
- /// let pb = ProgressBar::new(100);
- /// pb.set_draw_target(ProgressDrawTarget::stderr());
- /// ```
- ///
- /// **Note:** Calling this method on a [`ProgressBar`] linked with a [`MultiProgress`] (after
- /// running [`MultiProgress::add`]) will unlink this progress bar. If you don't want this
- /// behavior, call [`MultiProgress::set_draw_target`] instead.
- ///
- /// [`MultiProgress`]: crate::MultiProgress
- /// [`MultiProgress::add`]: crate::MultiProgress::add
- /// [`MultiProgress::set_draw_target`]: crate::MultiProgress::set_draw_target
- pub fn set_draw_target(&self, target: ProgressDrawTarget) {
- let mut state = self.state();
- state.draw_target.disconnect(Instant::now());
- state.draw_target = target;
- }
-
- /// Hide the progress bar temporarily, execute `f`, then redraw the progress bar
- ///
- /// Useful for external code that writes to the standard output.
- ///
- /// If the progress bar was added to a MultiProgress, it will suspend the entire MultiProgress
- ///
- /// **Note:** The internal lock is held while `f` is executed. Other threads trying to print
- /// anything on the progress bar will be blocked until `f` finishes.
- /// Therefore, it is recommended to avoid long-running operations in `f`.
- ///
- /// ```rust,no_run
- /// # use indicatif::ProgressBar;
- /// let mut pb = ProgressBar::new(3);
- /// pb.suspend(|| {
- /// println!("Log message");
- /// })
- /// ```
- pub fn suspend<F: FnOnce() -> R, R>(&self, f: F) -> R {
- self.state().suspend(Instant::now(), f)
- }
-
- /// Wraps an [`Iterator`] with the progress bar
- ///
- /// ```rust,no_run
- /// # use indicatif::ProgressBar;
- /// let v = vec![1, 2, 3];
- /// let pb = ProgressBar::new(3);
- /// for item in pb.wrap_iter(v.iter()) {
- /// // ...
- /// }
- /// ```
- pub fn wrap_iter<It: Iterator>(&self, it: It) -> ProgressBarIter<It> {
- it.progress_with(self.clone())
- }
-
- /// Wraps an [`io::Read`] with the progress bar
- ///
- /// ```rust,no_run
- /// # use std::fs::File;
- /// # use std::io;
- /// # use indicatif::ProgressBar;
- /// # fn test () -> io::Result<()> {
- /// let source = File::open("work.txt")?;
- /// let mut target = File::create("done.txt")?;
- /// let pb = ProgressBar::new(source.metadata()?.len());
- /// io::copy(&mut pb.wrap_read(source), &mut target);
- /// # Ok(())
- /// # }
- /// ```
- pub fn wrap_read<R: io::Read>(&self, read: R) -> ProgressBarIter<R> {
- ProgressBarIter {
- progress: self.clone(),
- it: read,
- }
- }
-
- /// Wraps an [`io::Write`] with the progress bar
- ///
- /// ```rust,no_run
- /// # use std::fs::File;
- /// # use std::io;
- /// # use indicatif::ProgressBar;
- /// # fn test () -> io::Result<()> {
- /// let mut source = File::open("work.txt")?;
- /// let target = File::create("done.txt")?;
- /// let pb = ProgressBar::new(source.metadata()?.len());
- /// io::copy(&mut source, &mut pb.wrap_write(target));
- /// # Ok(())
- /// # }
- /// ```
- pub fn wrap_write<W: io::Write>(&self, write: W) -> ProgressBarIter<W> {
- ProgressBarIter {
- progress: self.clone(),
- it: write,
- }
- }
-
- #[cfg(feature = "tokio")]
- #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
- /// Wraps an [`tokio::io::AsyncWrite`] with the progress bar
- ///
- /// ```rust,no_run
- /// # use tokio::fs::File;
- /// # use tokio::io;
- /// # use indicatif::ProgressBar;
- /// # async fn test() -> io::Result<()> {
- /// let mut source = File::open("work.txt").await?;
- /// let mut target = File::open("done.txt").await?;
- /// let pb = ProgressBar::new(source.metadata().await?.len());
- /// io::copy(&mut source, &mut pb.wrap_async_write(target)).await?;
- /// # Ok(())
- /// # }
- /// ```
- pub fn wrap_async_write<W: tokio::io::AsyncWrite + Unpin>(
- &self,
- write: W,
- ) -> ProgressBarIter<W> {
- ProgressBarIter {
- progress: self.clone(),
- it: write,
- }
- }
-
- #[cfg(feature = "tokio")]
- #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
- /// Wraps an [`tokio::io::AsyncRead`] with the progress bar
- ///
- /// ```rust,no_run
- /// # use tokio::fs::File;
- /// # use tokio::io;
- /// # use indicatif::ProgressBar;
- /// # async fn test() -> io::Result<()> {
- /// let mut source = File::open("work.txt").await?;
- /// let mut target = File::open("done.txt").await?;
- /// let pb = ProgressBar::new(source.metadata().await?.len());
- /// io::copy(&mut pb.wrap_async_read(source), &mut target).await?;
- /// # Ok(())
- /// # }
- /// ```
- pub fn wrap_async_read<R: tokio::io::AsyncRead + Unpin>(&self, read: R) -> ProgressBarIter<R> {
- ProgressBarIter {
- progress: self.clone(),
- it: read,
- }
- }
-
- /// Wraps a [`futures::Stream`](https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html) with the progress bar
- ///
- /// ```
- /// # use indicatif::ProgressBar;
- /// # futures::executor::block_on(async {
- /// use futures::stream::{self, StreamExt};
- /// let pb = ProgressBar::new(10);
- /// let mut stream = pb.wrap_stream(stream::iter('a'..='z'));
- ///
- /// assert_eq!(stream.next().await, Some('a'));
- /// assert_eq!(stream.count().await, 25);
- /// # }); // block_on
- /// ```
- #[cfg(feature = "futures")]
- #[cfg_attr(docsrs, doc(cfg(feature = "futures")))]
- pub fn wrap_stream<S: futures_core::Stream>(&self, stream: S) -> ProgressBarIter<S> {
- ProgressBarIter {
- progress: self.clone(),
- it: stream,
- }
- }
-
- /// Returns the current position
- pub fn position(&self) -> u64 {
- self.state().state.pos()
- }
-
- /// Returns the current length
- pub fn length(&self) -> Option<u64> {
- self.state().state.len()
- }
-
- /// Returns the current ETA
- pub fn eta(&self) -> Duration {
- self.state().state.eta()
- }
-
- /// Returns the current rate of progress
- pub fn per_sec(&self) -> f64 {
- self.state().state.per_sec()
- }
-
- /// Returns the current expected duration
- pub fn duration(&self) -> Duration {
- self.state().state.duration()
- }
-
- /// Returns the current elapsed time
- pub fn elapsed(&self) -> Duration {
- self.state().state.elapsed()
- }
-
- /// Index in the `MultiState`
- pub(crate) fn index(&self) -> Option<usize> {
- self.state().draw_target.remote().map(|(_, idx)| idx)
- }
-
- /// Current message
- pub fn message(&self) -> String {
- self.state().state.message.expanded().to_string()
- }
-
- /// Current prefix
- pub fn prefix(&self) -> String {
- self.state().state.prefix.expanded().to_string()
- }
-
- #[inline]
- pub(crate) fn state(&self) -> MutexGuard<'_, BarState> {
- self.state.lock().unwrap()
- }
-}
-
-/// A weak reference to a `ProgressBar`.
-///
-/// Useful for creating custom steady tick implementations
-#[derive(Clone, Default)]
-pub struct WeakProgressBar {
- state: Weak<Mutex<BarState>>,
- pos: Weak<AtomicPosition>,
- ticker: Weak<Mutex<Option<Ticker>>>,
-}
-
-impl WeakProgressBar {
- /// Create a new `WeakProgressBar` that returns `None` when [`upgrade`] is called.
- ///
- /// [`upgrade`]: WeakProgressBar::upgrade
- pub fn new() -> Self {
- Self::default()
- }
-
- /// Attempts to upgrade the Weak pointer to a [`ProgressBar`], delaying dropping of the inner
- /// value if successful. Returns `None` if the inner value has since been dropped.
- ///
- /// [`ProgressBar`]: struct.ProgressBar.html
- pub fn upgrade(&self) -> Option<ProgressBar> {
- let state = self.state.upgrade()?;
- let pos = self.pos.upgrade()?;
- let ticker = self.ticker.upgrade()?;
- Some(ProgressBar { state, pos, ticker })
- }
-}
-
-pub(crate) struct Ticker {
- stopping: Arc<(Mutex<bool>, Condvar)>,
- join_handle: Option<thread::JoinHandle<()>>,
-}
-
-impl Drop for Ticker {
- fn drop(&mut self) {
- self.stop();
- self.join_handle.take().map(|handle| handle.join());
- }
-}
-
-#[cfg(test)]
-static TICKER_RUNNING: AtomicBool = AtomicBool::new(false);
-
-impl Ticker {
- pub(crate) fn new(interval: Duration, bar_state: &Arc<Mutex<BarState>>) -> Self {
- debug_assert!(!interval.is_zero());
-
- // A `Mutex<bool>` is used as a flag to indicate whether the ticker was requested to stop.
- // The `Condvar` is used a notification mechanism: when the ticker is dropped, we notify
- // the thread and interrupt the ticker wait.
- #[allow(clippy::mutex_atomic)]
- let stopping = Arc::new((Mutex::new(false), Condvar::new()));
- let control = TickerControl {
- stopping: stopping.clone(),
- state: Arc::downgrade(bar_state),
- };
-
- let join_handle = thread::spawn(move || control.run(interval));
- Self {
- stopping,
- join_handle: Some(join_handle),
- }
- }
-
- pub(crate) fn stop(&self) {
- *self.stopping.0.lock().unwrap() = true;
- self.stopping.1.notify_one();
- }
-}
-
-struct TickerControl {
- stopping: Arc<(Mutex<bool>, Condvar)>,
- state: Weak<Mutex<BarState>>,
-}
-
-impl TickerControl {
- fn run(&self, interval: Duration) {
- #[cfg(test)]
- TICKER_RUNNING.store(true, Ordering::SeqCst);
-
- while let Some(arc) = self.state.upgrade() {
- let mut state = arc.lock().unwrap();
- if state.state.is_finished() {
- break;
- }
-
- state.tick(Instant::now());
-
- drop(state); // Don't forget to drop the lock before sleeping
- drop(arc); // Also need to drop Arc otherwise BarState won't be dropped
-
- // Wait for `interval` but return early if we are notified to stop
- let (_, result) = self
- .stopping
- .1
- .wait_timeout_while(self.stopping.0.lock().unwrap(), interval, |stopped| {
- !*stopped
- })
- .unwrap();
-
- // If the wait didn't time out, it means we were notified to stop
- if !result.timed_out() {
- break;
- }
- }
-
- #[cfg(test)]
- TICKER_RUNNING.store(false, Ordering::SeqCst);
- }
-}
-
-// Tests using the global TICKER_RUNNING flag need to be serialized
-#[cfg(test)]
-pub(crate) static TICKER_TEST: Lazy<Mutex<()>> = Lazy::new(Mutex::default);
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[allow(clippy::float_cmp)]
- #[test]
- fn test_pbar_zero() {
- let pb = ProgressBar::new(0);
- assert_eq!(pb.state().state.fraction(), 1.0);
- }
-
- #[allow(clippy::float_cmp)]
- #[test]
- fn test_pbar_maxu64() {
- let pb = ProgressBar::new(!0);
- assert_eq!(pb.state().state.fraction(), 0.0);
- }
-
- #[test]
- fn test_pbar_overflow() {
- let pb = ProgressBar::new(1);
- pb.set_draw_target(ProgressDrawTarget::hidden());
- pb.inc(2);
- pb.finish();
- }
-
- #[test]
- fn test_get_position() {
- let pb = ProgressBar::new(1);
- pb.set_draw_target(ProgressDrawTarget::hidden());
- pb.inc(2);
- let pos = pb.position();
- assert_eq!(pos, 2);
- }
-
- #[test]
- fn test_weak_pb() {
- let pb = ProgressBar::new(0);
- let weak = pb.downgrade();
- assert!(weak.upgrade().is_some());
- ::std::mem::drop(pb);
- assert!(weak.upgrade().is_none());
- }
-
- #[test]
- fn it_can_wrap_a_reader() {
- let bytes = &b"I am an implementation of io::Read"[..];
- let pb = ProgressBar::new(bytes.len() as u64);
- let mut reader = pb.wrap_read(bytes);
- let mut writer = Vec::new();
- io::copy(&mut reader, &mut writer).unwrap();
- assert_eq!(writer, bytes);
- }
-
- #[test]
- fn it_can_wrap_a_writer() {
- let bytes = b"implementation of io::Read";
- let mut reader = &bytes[..];
- let pb = ProgressBar::new(bytes.len() as u64);
- let writer = Vec::new();
- let mut writer = pb.wrap_write(writer);
- io::copy(&mut reader, &mut writer).unwrap();
- assert_eq!(writer.it, bytes);
- }
-
- #[test]
- fn ticker_thread_terminates_on_drop() {
- let _guard = TICKER_TEST.lock().unwrap();
- assert!(!TICKER_RUNNING.load(Ordering::SeqCst));
-
- let pb = ProgressBar::new_spinner();
- pb.enable_steady_tick(Duration::from_millis(50));
-
- // Give the thread time to start up
- thread::sleep(Duration::from_millis(250));
-
- assert!(TICKER_RUNNING.load(Ordering::SeqCst));
-
- drop(pb);
- assert!(!TICKER_RUNNING.load(Ordering::SeqCst));
- }
-
- #[test]
- fn ticker_thread_terminates_on_drop_2() {
- let _guard = TICKER_TEST.lock().unwrap();
- assert!(!TICKER_RUNNING.load(Ordering::SeqCst));
-
- let pb = ProgressBar::new_spinner();
- pb.enable_steady_tick(Duration::from_millis(50));
- let pb2 = pb.clone();
-
- // Give the thread time to start up
- thread::sleep(Duration::from_millis(250));
-
- assert!(TICKER_RUNNING.load(Ordering::SeqCst));
-
- drop(pb);
- assert!(TICKER_RUNNING.load(Ordering::SeqCst));
-
- drop(pb2);
- assert!(!TICKER_RUNNING.load(Ordering::SeqCst));
- }
-}