blob: 9b581d11d7bda88c79dccd2c0e89b27b6fbfdfe3 [file]
use humantime::format_duration;
use humantime::Duration as HumanDuration;
use serde::{Deserialize, Serialize};
use std::{
fmt::{Display, Formatter},
ops::Add,
str::FromStr,
time::Duration,
};
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Eq, PartialEq)]
pub struct IggyDuration {
duration: Duration,
}
impl IggyDuration {
pub fn new(duration: Duration) -> IggyDuration {
IggyDuration { duration }
}
pub fn as_human_time_string(&self) -> String {
format!("{}", format_duration(self.duration))
}
pub fn as_secs(&self) -> u32 {
self.duration.as_secs() as u32
}
pub fn as_secs_f64(&self) -> f64 {
self.duration.as_secs_f64()
}
pub fn as_micros(&self) -> u64 {
self.duration.as_micros() as u64
}
pub fn get_duration(&self) -> Duration {
self.duration
}
pub fn is_zero(&self) -> bool {
self.duration.as_secs() == 0
}
//TODO(numinex) - Replace it with std::time::Duration::abs_diff when it becomes stable
pub fn abs_diff(&self, other: IggyDuration) -> IggyDuration {
let diff = self.duration.as_nanos().abs_diff(other.duration.as_nanos());
IggyDuration {
duration: Duration::from_nanos(diff as u64),
}
}
}
impl FromStr for IggyDuration {
type Err = humantime::DurationError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = &s.to_lowercase();
if s == "0" || s == "unlimited" || s == "disabled" || s == "none" {
Ok(IggyDuration {
duration: Duration::new(0, 0),
})
} else {
Ok(IggyDuration {
duration: humantime::parse_duration(s)?,
})
}
}
}
impl From<Option<u64>> for IggyDuration {
fn from(byte_size: Option<u64>) -> Self {
match byte_size {
Some(value) => IggyDuration {
duration: Duration::from_secs(value),
},
None => IggyDuration {
duration: Duration::new(0, 0),
},
}
}
}
impl From<u64> for IggyDuration {
fn from(value: u64) -> Self {
IggyDuration {
duration: Duration::from_secs(value),
}
}
}
impl From<Duration> for IggyDuration {
fn from(duration: Duration) -> Self {
IggyDuration { duration }
}
}
impl From<HumanDuration> for IggyDuration {
fn from(human_duration: HumanDuration) -> Self {
Self {
duration: human_duration.into(),
}
}
}
impl From<IggyDuration> for u64 {
fn from(iggy_duration: IggyDuration) -> u64 {
iggy_duration.duration.as_secs()
}
}
impl Default for IggyDuration {
fn default() -> Self {
IggyDuration {
duration: Duration::new(0, 0),
}
}
}
impl Display for IggyDuration {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_human_time_string())
}
}
impl Add for IggyDuration {
type Output = IggyDuration;
fn add(self, rhs: Self) -> Self::Output {
IggyDuration {
duration: self.duration + rhs.duration,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_new() {
let duration = Duration::new(60, 0); // 60 seconds
let iggy_duration = IggyDuration::new(duration);
assert_eq!(iggy_duration.as_secs(), 60);
}
#[test]
fn test_as_human_time_string() {
let duration = Duration::new(3661, 0); // 1 hour, 1 minute and 1 second
let iggy_duration = IggyDuration::new(duration);
assert_eq!(iggy_duration.as_human_time_string(), "1h 1m 1s");
}
#[test]
fn test_long_duration_as_human_time_string() {
let duration = Duration::new(36611233, 0); // 1year 1month 28days 1hour 13minutes 37seconds
let iggy_duration = IggyDuration::new(duration);
assert_eq!(
iggy_duration.as_human_time_string(),
"1year 1month 28days 1h 13m 37s"
);
}
#[test]
fn test_from_str() {
let iggy_duration: IggyDuration = "1h 1m 1s".parse().unwrap();
assert_eq!(iggy_duration.as_secs(), 3661);
}
#[test]
fn test_display() {
let duration = Duration::new(3661, 0);
let iggy_duration = IggyDuration::new(duration);
let duration_string = format!("{}", iggy_duration);
assert_eq!(duration_string, "1h 1m 1s");
}
#[test]
fn test_invalid_duration() {
let result: Result<IggyDuration, _> = "1 hour and 30 minutes".parse();
assert!(result.is_err());
}
#[test]
fn test_zero_seconds_duration() {
let iggy_duration: IggyDuration = "0s".parse().unwrap();
assert_eq!(iggy_duration.as_secs(), 0);
}
#[test]
fn test_zero_duration() {
let iggy_duration: IggyDuration = "0".parse().unwrap();
assert_eq!(iggy_duration.as_secs(), 0);
}
#[test]
fn test_unlimited() {
let iggy_duration: IggyDuration = "unlimited".parse().unwrap();
assert_eq!(iggy_duration.as_secs(), 0);
}
#[test]
fn test_disabled() {
let iggy_duration: IggyDuration = "disabled".parse().unwrap();
assert_eq!(iggy_duration.as_secs(), 0);
}
#[test]
fn test_add_duration() {
let iggy_duration1: IggyDuration = "6s".parse().unwrap();
let iggy_duration2: IggyDuration = "1m".parse().unwrap();
let result: IggyDuration = iggy_duration1 + iggy_duration2;
assert_eq!(result.as_secs(), 66);
}
}