use chrono::{NaiveDate, NaiveTime, Weekday};
use serde::de::{Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct PlaceOpeningHoursPeriodDetail {
#[serde(deserialize_with = "integer_as_weekday")]
pub day: Weekday,
#[serde(deserialize_with = "str_as_naive_time")]
pub time: NaiveTime,
#[serde(default)]
pub date: Option<NaiveDate>,
#[serde(default)]
pub truncated: Option<bool>,
}
fn integer_as_weekday<'de, D>(deserializer: D) -> Result<Weekday, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_u64(WeekdayVisitor)
}
struct WeekdayVisitor;
impl Visitor<'_> for WeekdayVisitor {
type Value = Weekday;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("integer representation of weekday") }
fn visit_u64<E>(self, value: u64) -> Result<Weekday, E>
where
E: serde::de::Error,
{
match value {
0 => Ok(Weekday::Sun),
1 => Ok(Weekday::Mon),
2 => Ok(Weekday::Tue),
3 => Ok(Weekday::Wed),
4 => Ok(Weekday::Thu),
5 => Ok(Weekday::Fri),
6 => Ok(Weekday::Sat),
_ => Err(
E::invalid_value(
Unexpected::Unsigned(value),
&"weekday between 0 and 6, where 0 is sunday",
), ), } } }
fn str_as_naive_time<'de, D>(deserializer: D) -> Result<NaiveTime, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(NaiveTimeVisitor)
}
struct NaiveTimeVisitor;
impl Visitor<'_> for NaiveTimeVisitor {
type Value = NaiveTime;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a string representation of time of day in 24-hour hhmm format")
}
fn visit_str<E>(self, value: &str) -> Result<NaiveTime, E>
where
E: serde::de::Error,
{
NaiveTime::parse_from_str(value, "%H%M").map_err(|_err| {
E::invalid_value(
Unexpected::Str(value),
&"time of day in 24-hour hhmm format. values are in the range 0000–2359",
) }) } }
impl std::str::FromStr for PlaceOpeningHoursPeriodDetail {
type Err = serde_json::Error;
fn from_str(s: &str) -> Result<Self, serde_json::Error> {
let bytes = s.to_string().into_bytes();
serde_json::from_slice(&bytes)
} }