use super::{OSC94, ProgressState};
use std::io::{Result as IoResult, Stderr, Write};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Progress<W: Write> {
state: ProgressState,
#[allow(clippy::struct_field_names)]
progress: u8,
destination: W,
}
impl<W: Write> Progress<W> {
pub const fn new(destination: W) -> Self {
Self {
state: ProgressState::Hidden,
progress: 0,
destination,
}
}
pub fn flush(&mut self) -> IoResult<&mut Self> {
let raw = OSC94 {
state: self.state,
progress: self.progress,
};
write!(self.destination, "{raw}")?;
Ok(self)
}
pub const fn get_state(&self) -> ProgressState {
self.state
}
pub const fn state(&mut self, state: ProgressState) -> &mut Self {
self.state = state;
self
}
pub const fn start(&mut self) -> &mut Self {
self.normal()
}
pub const fn hidden(&mut self) -> &mut Self {
self.state(ProgressState::Hidden)
}
pub const fn normal(&mut self) -> &mut Self {
self.state(ProgressState::Normal)
}
pub const fn error(&mut self) -> &mut Self {
self.state(ProgressState::Error)
}
pub const fn indeterminate(&mut self) -> &mut Self {
self.state(ProgressState::Indeterminate)
}
pub const fn warning(&mut self) -> &mut Self {
self.state(ProgressState::Warning)
}
pub const fn get_progress(&self) -> u8 {
self.progress
}
pub const fn progress(&mut self, progress: u8) -> &mut Self {
self.progress = if progress > 100 { 100 } else { progress };
self
}
pub const fn increment(&mut self, by: u8) -> &mut Self {
self.progress(self.progress.saturating_add(by));
self
}
pub const fn is_finished(&self) -> bool {
self.progress == 100
}
}
impl<W: Write> Drop for Progress<W> {
fn drop(&mut self) {
let raw = OSC94::default();
let _ = write!(self.destination, "{raw}");
}
}
impl Default for Progress<Stderr> {
fn default() -> Self {
Self {
state: ProgressState::Hidden,
progress: 0,
destination: std::io::stderr(),
}
}
}