synd-support 0.4.0

shared support utilities for syndicationd crates
Documentation
use std::time::Duration;

use serde::{Deserialize, Deserializer};

use crate::time::humantime;

pub fn parse_duration_opt<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
where
    D: Deserializer<'de>,
{
    match Option::<String>::deserialize(deserializer)? {
        Some(duration) => match humantime::parse_duration(&duration) {
            Ok(duration) => Ok(Some(duration)),
            Err(err) => Err(serde::de::Error::custom(err)),
        },
        None => Ok(None),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn should_parse() {
        #[derive(Deserialize)]
        struct Data {
            #[serde(default, deserialize_with = "parse_duration_opt")]
            d: Option<Duration>,
        }

        let s = r#"{"d": "30sec" }"#;
        let data: Data = serde_json::from_str(s).unwrap();
        assert_eq!(data.d, Some(Duration::from_secs(30)));

        let s = r#"{"d": null }"#;
        let data: Data = serde_json::from_str(s).unwrap();
        assert_eq!(data.d, None);
    }
}