use std::borrow::Cow;
use std::fmt::{Debug, Display};
use std::time::{Duration, Instant};
#[allow(unused)] use crate::View;
use crate::{estimate_remaining, percent_done, Model};
pub struct StringPair {
prefix: Cow<'static, str>,
suffix: Cow<'static, str>,
}
impl StringPair {
pub fn new<S1, S2>(prefix: S1, suffix: S2) -> StringPair
where
S1: Into<Cow<'static, str>>,
S2: Into<Cow<'static, str>>,
{
StringPair {
prefix: prefix.into(),
suffix: suffix.into(),
}
}
pub fn set_suffix<S>(&mut self, suffix: S)
where
S: Into<Cow<'static, str>>,
{
self.suffix = suffix.into();
}
}
impl Model for StringPair {
fn render(&mut self, _width: usize) -> String {
format!("{}{}", self.prefix, self.suffix)
}
}
#[derive(Debug)]
pub struct LinearModel {
done: usize,
total: usize,
message: Cow<'static, str>,
start: Instant,
}
impl LinearModel {
pub fn new<S: Into<Cow<'static, str>>>(message: S, total: usize) -> LinearModel {
LinearModel {
done: 0,
total,
message: message.into(),
start: Instant::now(),
}
}
pub fn set_total(&mut self, total: usize) {
self.total = total
}
pub fn total(&self) -> usize {
self.total
}
pub fn done(&self) -> usize {
self.done
}
pub fn set_done(&mut self, done: usize) {
self.done = done
}
pub fn increment(&mut self, i: usize) {
self.done += i
}
}
impl Model for LinearModel {
fn render(&mut self, _width: usize) -> String {
format!(
"{}: {}/{}, {}, {} remaining",
self.message,
self.done,
self.total,
percent_done(self.done, self.total),
estimate_remaining(&self.start, self.done, self.total)
)
}
}
pub struct UnboundedModel {
message: Cow<'static, str>,
done: usize,
start: Instant,
}
impl UnboundedModel {
pub fn new<S: Into<Cow<'static, str>>>(message: S) -> UnboundedModel {
UnboundedModel {
done: 0,
message: message.into(),
start: Instant::now(),
}
}
pub fn set_done(&mut self, done: usize) {
self.done = done
}
pub fn increment(&mut self, i: usize) {
self.done += i
}
}
impl Model for UnboundedModel {
fn render(&mut self, _width: usize) -> String {
format!(
"{}: {} in {}",
self.message,
self.done,
format_duration(self.start.elapsed())
)
}
}
fn format_duration(d: Duration) -> String {
let elapsed_secs = d.as_secs();
if elapsed_secs >= 3600 {
format!(
"{}:{:02}:{:02}",
elapsed_secs / 3600,
(elapsed_secs / 60) % 60,
elapsed_secs % 60
)
} else {
format!("{}:{:02}", (elapsed_secs / 60) % 60, elapsed_secs % 60)
}
}
pub struct BasicModel<T, R>
where
R: FnMut(&mut T) -> String,
{
pub value: T,
render_fn: R,
}
impl<T, R> BasicModel<T, R>
where
R: FnMut(&mut T) -> String,
{
pub fn new(value: T, render_fn: R) -> BasicModel<T, R> {
BasicModel { value, render_fn }
}
}
impl<T, R> Model for BasicModel<T, R>
where
R: FnMut(&mut T) -> String,
{
fn render(&mut self, _width: usize) -> String {
(self.render_fn)(&mut self.value)
}
}
#[derive(Debug)]
pub struct DisplayModel<T: Display + Debug>(pub T);
impl<T: Display + Debug> DisplayModel<T> {
pub fn new(value: T) -> DisplayModel<T> {
DisplayModel(value)
}
}
impl<T: Display + Debug> Model for DisplayModel<T> {
fn render(&mut self, _width: usize) -> String {
format!("{}", self.0)
}
}