execution_time/traits/
format_value.rsuse crate::{SingularPlural, Unit};
pub trait FormatFloatValue {
fn format_float_unit(&self, decimal: usize, unit: Unit) -> String;
}
impl FormatFloatValue for f64 {
fn format_float_unit(&self, decimal: usize, unit: Unit) -> String {
let unit = if *self >= 2.0 {
unit.plural()
} else {
unit.singular()
};
format!("{self:.decimal$} {unit}")
}
}
pub trait FormatIntegerValue {
fn format_unit(&self, unit: Unit) -> String;
}
impl<T> FormatIntegerValue for T
where
T: std::fmt::Display + PartialOrd + From<u8>,
{
fn format_unit(&self, unit: Unit) -> String {
let unit = if *self >= T::from(2u8) {
unit.plural()
} else {
unit.singular()
};
format!("{self} {unit}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_integer_formatting() {
assert_eq!(0u64.format_unit(Unit::Day), "0 day");
assert_eq!(1u64.format_unit(Unit::Foot), "1 foot");
assert_eq!(2u64.format_unit(Unit::Foot), "2 feet");
assert_eq!(8u8.format_unit(Unit::Ox), "8 oxen");
}
#[test]
fn test_floating_point_formatting() {
assert_eq!(1.5f64.format_float_unit(1, Unit::Second), "1.5 second");
assert_eq!(2.0f64.format_float_unit(0, Unit::Hour), "2 hours");
assert_eq!(1.0.format_float_unit(1, Unit::Foot), "1.0 foot");
assert_eq!(7.123501.format_float_unit(3, Unit::Foot), "7.124 feet");
}
}