Crate progressor

Source
Expand description

A modern, async-first progress tracking library for Rust.

This crate provides types and utilities for tracking progress of long-running operations in an async context. It uses Rust’s Stream API to emit progress updates with support for different states (working, paused, completed, cancelled).

§Features

  • Async-first: Built around Rust’s async/await and Stream APIs
  • Zero-allocation progress updates: Efficient progress reporting
  • Flexible progress tracking: Support for current/total, messages, and cancellation
  • Type-safe: Full Rust type safety with meaningful error messages
  • Lightweight: Minimal dependencies and fast compilation
  • Convenient observing: Extension methods for easy progress monitoring

§Examples

The ProgressExt::observe method provides a convenient way to monitor progress without manually managing streams and select macros:

use progressor::{progress, ProgressExt};

let result = progress(100, |mut updater| async move {
    for i in 0..=100 {
        // Update progress
        updater.update(i);
         
        // Add messages for important milestones
        if i % 25 == 0 {
            updater.update_with_message(i, format!("Milestone: {}%", i));
        }
    }
    "Task completed!"
})
.observe(|update| {
    println!("Progress: {}%", (update.completed_fraction() * 100.0) as u32);
    if let Some(message) = update.message() {
        println!("  {}", message);
    }
})
.await;

println!("Result: {}", result);

§Manual stream monitoring with tokio::select!

For more control, you can manually monitor the progress stream:

use progressor::{progress, Progress};
use futures_util::StreamExt;

let task = progress(100, |mut updater| async move {
    for i in 0..=100 {
        // Update progress
        updater.update(i);
         
        // Add messages for important milestones
        if i % 25 == 0 {
            updater.update_with_message(i, format!("Milestone: {}%", i));
        }
    }
    "Task completed!"
});

// Monitor progress concurrently
let mut progress_stream = task.progress();
tokio::select! {
    result = task => {
        println!("Result: {}", result);
    }
    _ = async {
        while let Some(update) = progress_stream.next().await {
            println!("Progress: {}%", (update.completed_fraction() * 100.0) as u32);
            if let Some(message) = update.message() {
                println!("  {}", message);
            }
        }
    } => {}
}

§Advanced usage with state handling

Monitor different progress states and handle pause/cancel operations:

use progressor::{progress, ProgressExt, State};

let result = progress(100, |mut updater| async move {
    for i in 0..=100 {
        // Update progress
        updater.update(i);
         
        // Pause at 50%
        if i == 50 {
            updater.pause();
            // Simulate some async work during pause
            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
        }
    }
    "Task completed!"
})
.observe(|update| {
    match update.state() {
        State::Working => println!("Working: {}%", (update.completed_fraction() * 100.0) as u32),
        State::Paused => println!("Paused at {}%", (update.completed_fraction() * 100.0) as u32),
        State::Completed => println!("Completed!"),
        State::Cancelled => println!("Cancelled!"),
    }
})
.await;

println!("Result: {}", result);

Structs§

ProgressUpdate
Represents a single progress update with current status, total, and optional metadata.
ProgressUpdaterstd
A handle for updating progress during execution of a future.

Enums§

State
Represents the state of a progress-tracked operation.

Traits§

Progress
A trait for futures that can report progress updates.
ProgressExt
Extension trait providing convenient methods for observing progress updates.

Functions§

progressstd
Creates a progress-tracked future from a closure.