#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct YearMonth
{
year: u16,
one_based_month: u8,
}
impl<'de> Deserialize<'de> for YearMonth
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
{
struct YearMonthVisitor;
impl<'de> Visitor<'de> for YearMonthVisitor
{
type Value = YearMonth;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result
{
formatter.write_str("a year-month string")
}
fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E>
{
let mut split = v.split('-');
let year = match split.next()
{
None => return Err(E::custom("no year")),
Some(value) => if value.len() != 4
{
return Err(E::custom("year wasn't 4 characters"));
}
else
{
match value.parse::<u16>()
{
Err(parseError) => return Err(E::custom(parseError)),
Ok(year) => if year < 2000 || year > 2100
{
return Err(E::custom("year seems suspect"))
}
else
{
year
}
}
}
};
let one_based_month = match split.next()
{
None => return Err(E::custom("no month")),
Some(value) => if value.len() != 2
{
return Err(E::custom("month wasn't 2 characters"));
}
else
{
match value.parse::<u8>()
{
Err(parseError) => return Err(E::custom(parseError)),
Ok(one_based_month) => if one_based_month < 1 || one_based_month > 12
{
return Err(E::custom("month seems suspect"))
}
else
{
one_based_month
}
}
}
};
if split.next().is_some()
{
return Err(E::custom("additional data after month"));
}
Ok
(
YearMonth
{
year,
one_based_month,
}
)
}
}
deserializer.deserialize_str(YearMonthVisitor)
}
}
impl YearMonth
{
#[inline(always)]
pub fn year(&self) -> u16
{
self.year
}
#[inline(always)]
pub fn one_based_month(&self) -> u8
{
self.one_based_month
}
#[inline(always)]
pub fn zero_based_month(&self) -> u8
{
self.one_based_month() - 1
}
}