use alloc::string::String;
use core::time::Duration;
pub trait MillisecondFormatter {
type Output;
fn pretty_with(&self, opt: MillisecondOption) -> Self::Output;
fn pretty(&self) -> Self::Output {
self.pretty_with(MillisecondOption::default())
}
#[deprecated(since = "0.4.0", note = "use the `pretty` instead")]
fn to_short_string(&self) -> Self::Output {
self.pretty()
}
#[deprecated(since = "0.4.0", note = "use the `pretty_with` function instead")]
fn to_long_string(&self) -> Self::Output {
self.pretty_with(MillisecondOption::long())
}
}
impl MillisecondFormatter for Duration {
type Output = String;
fn pretty_with(&self, opt: MillisecondOption) -> Self::Output {
let parts = super::parser::parse_duration(self, &opt);
super::parser::ms_parts_to_string(&parts, &opt)
}
}
#[derive(Debug, Copy, Clone, Default)]
pub struct MillisecondOption<'a> {
pub format: OutputFormat,
pub days_instead_of_years: bool,
pub dominant_only: bool,
pub format_sub_milliseconds: bool,
pub seconds: SecondsOptions,
pub unit_count: Option<usize>,
pub separator: Separator<'a>,
}
impl<'a> MillisecondOption<'a> {
pub fn long() -> Self {
Self {
format: OutputFormat::Long,
..Default::default()
}
}
pub fn colon() -> Self {
Self {
format: OutputFormat::Colon,
seconds: SecondsOptions::Combine,
format_sub_milliseconds: false,
dominant_only: false,
..Default::default()
}
}
pub fn sub_milliseconds() -> Self {
Self {
format_sub_milliseconds: true,
..Default::default()
}
}
pub fn get_separator(&self) -> &str {
match self.separator {
Separator::Default => match self.format {
OutputFormat::Colon => ":",
_ => self.separator.as_ref(),
},
_ => self.separator.as_ref(),
}
}
pub fn get_unit_count(&self) -> usize {
let dominant = if self.dominant_only { 1 } else { 8 };
self.unit_count.unwrap_or(dominant).clamp(1, 8)
}
#[cfg(test)]
pub(crate) fn backward_compatible() -> Self {
Self {
format_sub_milliseconds: true,
seconds: SecondsOptions::Separate,
..Self::default()
}
}
}
#[derive(Debug, Copy, Clone, Default)]
pub enum SecondsOptions {
#[default]
Separate,
Combine,
CombineWith {
precision: Option<u8>,
fixed_width: bool,
},
Hide,
}
impl SecondsOptions {
pub fn precision(&self) -> u8 {
let p = match self {
Self::CombineWith { precision, .. } => (*precision).unwrap_or(1).clamp(0, 3),
_ => 1,
};
if self.is_fixed_width() { p.min(3) } else { p }
}
pub fn is_fixed_width(&self) -> bool {
match self {
Self::CombineWith { fixed_width, .. } => *fixed_width,
_ => false,
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub enum OutputFormat {
#[default]
Short,
Long,
Colon,
}
#[derive(Debug, Clone, Copy, Default)]
pub enum Separator<'a> {
#[default]
Default,
None,
Space,
Dash,
Custom(&'a str),
}
impl<'a> AsRef<str> for Separator<'a> {
fn as_ref(&self) -> &str {
match self {
Self::Default => " ",
Self::Space => " ",
Self::None => "",
Self::Dash => "-",
Self::Custom(x) => x,
}
}
}