use std::{
any::type_name,
fmt::{Display, Formatter},
marker::PhantomData,
};
use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
use serde::de;
pub(crate) struct DateTimeVisitor(pub &'static str);
impl de::Visitor<'_> for DateTimeVisitor {
type Value = DateTime<Utc>;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
write!(formatter, "a date and time formatted as '{}'", self.0)
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
NaiveDateTime::parse_from_str(s, self.0)
.map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))
.map(|naive_date_time| Utc.from_utc_datetime(&naive_date_time))
}
}
pub(crate) struct WhitespaceListVisitor<T>(PhantomData<T>);
impl<T> WhitespaceListVisitor<T> {
pub(crate) fn new() -> Self {
Self(PhantomData)
}
}
impl<T> serde::de::Visitor<'_> for WhitespaceListVisitor<T>
where
for<'a> T: TryFrom<&'a str>,
for<'a> <T as TryFrom<&'a str>>::Error: Display,
{
type Value = Vec<T>;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
write!(formatter, "a list of {}", type_name::<T>())
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
s.split_whitespace()
.map(|a| T::try_from(a).map_err(E::custom))
.collect()
}
}
pub(crate) struct TryFromStrVisitor<T> {
expecting_message: &'static str,
phantom: PhantomData<T>,
}
impl<T> TryFromStrVisitor<T> {
pub(crate) fn new(expecting_message: &'static str) -> Self {
Self {
expecting_message,
phantom: PhantomData,
}
}
}
impl<T> serde::de::Visitor<'_> for TryFromStrVisitor<T>
where
for<'a> T: TryFrom<&'a str>,
for<'a> <T as TryFrom<&'a str>>::Error: Display,
{
type Value = T;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
write!(formatter, "{}", self.expecting_message)
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
T::try_from(s).map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))
}
}