availability 0.1.4

Rust library for describing availability of items.
Documentation
use bitflags::bitflags;
use chrono::{NaiveDate, NaiveTime};
use serde::{Deserialize, Serialize};

bitflags! {
    #[derive(Serialize, Deserialize)]
    pub struct Weekdays: u32 {
        const ALL                         = 0b1111111;
        const MONDAY                      = 0b0000001;
        const TUESDAY                     = 0b0000010;
        const WEDNESDAY                   = 0b0000100;
        const THURSDAY                    = 0b0001000;
        const FRIDAY                      = 0b0010000;
        const SATURDAY                    = 0b0100000;
        const SUNDAY                      = 0b1000000;
    }
}

impl Weekdays {
    pub fn from_chrono_weekday(weekday: chrono::Weekday) -> Self {
        match weekday {
            chrono::Weekday::Mon => Self::MONDAY,
            chrono::Weekday::Tue => Self::TUESDAY,
            chrono::Weekday::Wed => Self::WEDNESDAY,
            chrono::Weekday::Thu => Self::THURSDAY,
            chrono::Weekday::Fri => Self::FRIDAY,
            chrono::Weekday::Sat => Self::SATURDAY,
            chrono::Weekday::Sun => Self::SUNDAY,
        }
    }
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Rule<T: Serialize> {
    pub start_date: NaiveDate,

    pub end_date: NaiveDate,

    pub start_time: NaiveTime,

    pub end_time: NaiveTime,

    #[serde(with = "integer_representation")]
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub weekdays: Option<Weekdays>,

    pub state: bool,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub payload: Option<T>,
}

mod integer_representation {
    use super::Weekdays;
    use serde::{self, Deserialize, Deserializer, Serialize, Serializer};
    type IntRep = u32;
    type Flags = Option<Weekdays>;

    pub fn serialize<S>(flags: &Flags, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if let Some(flags) = flags {
            flags.bits().serialize(serializer)
        } else {
            serializer.serialize_none()
        }
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<Flags, D::Error>
    where
        D: Deserializer<'de>,
    {
        let raw: IntRep = IntRep::deserialize(deserializer)?;
        Ok(Some(Weekdays::from_bits(raw).ok_or(
            serde::de::Error::custom(format!("Unexpected flags value {}", raw)),
        )?))
    }
}