use std::borrow::Cow;
use std::fmt;
use std::str::FromStr;
use derive_more::{Deref, From};
use humantime_serde::re::humantime;
use schemars::JsonSchema;
use serde::de::Deserializer;
use serde::{Deserialize, Serialize};
use crate::Validate;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deref, From)]
pub struct Duration(std::time::Duration);
impl FromStr for Duration {
type Err = humantime::DurationError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
humantime::parse_duration(s).map(Self)
}
}
impl fmt::Display for Duration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", humantime::format_duration(self.0))
}
}
impl<'de> Deserialize<'de> for Duration {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
humantime::parse_duration(&s)
.map(Self)
.map_err(serde::de::Error::custom)
}
}
impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
humantime_serde::serialize(&self.0, serializer)
}
}
impl JsonSchema for Duration {
fn schema_name() -> Cow<'static, str> {
Cow::Borrowed("Duration")
}
fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
String::json_schema(generator)
}
}
impl Validate for Duration {}
#[cfg(test)]
mod tests {
use super::Duration;
use std::str::FromStr as _;
#[test]
fn parse_from_str() {
assert_eq!(
Duration::from_str("5m 20s")
.expect("should parse")
.as_secs(),
320
);
let _err = Duration::from_str("5q").expect_err("should not parse");
}
}