use std::fmt;
use std::marker::PhantomData;
use std::str::FromStr;
use serde::{
Serialize,
Deserialize,
de::{self, Visitor}
};
use super::{
DateTime,
Date,
Time
};
struct FromStrVisitor<T>{
expect: &'static str,
marker: PhantomData<T>
}
impl<T> FromStrVisitor<T> {
pub fn expect(expect: &'static str) -> Self {
let marker = PhantomData;
Self { expect, marker }
}
}
impl<T, E> Visitor<'_> for FromStrVisitor<T>
where T: FromStr<Err = E>,
E: fmt::Display
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.expect)
}
fn visit_str<D>(self, value: &str) -> Result<Self::Value, D>
where D: de::Error,
{
value.parse::<T>().map_err(D::custom)
}
}
macro_rules! as_str {
($t:ty, $e:literal) => {
impl Serialize for $t {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for $t {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: serde::Deserializer<'de>
{
deserializer.deserialize_str(FromStrVisitor::expect($e))
}
}
};
}
as_str!(DateTime, "a properly formatted Date & Time");
as_str!(Date, "a properly formatted Date");
as_str!(Time, "a properly formatted Time");