use crate::error::ErrorKind;
use crate::ParseError;
use crate::ParseResult;
#[derive(Clone, Copy, Debug)]
pub struct RawDate {
pub(crate) year: Option<i16>,
pub(crate) month: Option<u8>,
pub(crate) day: Option<u8>,
}
impl RawDate {
fn new() -> Self {
Self { year: None, month: None, day: None }
}
#[inline]
pub fn year(&self) -> i16 {
self.year.unwrap()
}
#[inline]
pub fn month(&self) -> u8 {
self.month.unwrap()
}
#[inline]
pub fn day(&self) -> u8 {
self.day.unwrap()
}
pub(crate) fn assert_complete(&self, src: &str) -> ParseResult<()> {
if self.year.is_none() || self.month.is_none() || self.day.is_none() {
Err(ParseError { src: src.into(), index: None, kind: ErrorKind::IncompleteDate })?;
}
Ok(())
}
}
#[derive(Copy, Clone, Debug, Default)]
pub struct RawTime {
pub(crate) hour: u8,
pub(crate) minute: u8,
pub(crate) second: u8,
pub(crate) nanosecond: u64,
pub(crate) utc_offset: Option<i32>,
}
impl RawTime {
#[inline]
pub const fn hour(&self) -> u8 {
self.hour
}
#[inline]
pub const fn minute(&self) -> u8 {
self.minute
}
#[inline]
pub const fn second(&self) -> u8 {
self.second
}
#[inline]
pub const fn nanosecond(&self) -> u64 {
self.nanosecond
}
#[inline]
pub const fn utc_offset(&self) -> Option<i32> {
self.utc_offset
}
}
#[derive(Debug, Clone)]
pub struct RawDateTime {
pub(crate) src: String,
pub(crate) date: Option<RawDate>,
pub(crate) time: Option<RawTime>,
}
impl RawDateTime {
pub fn date(&self) -> ParseResult<RawDate> {
self.date.ok_or_else(|| ParseError::new(self.src.as_str(), ErrorKind::MissingDate))
}
pub fn time(&self) -> ParseResult<RawTime> {
self.time.ok_or_else(|| ParseError::new(self.src.as_str(), ErrorKind::MissingTime))
}
pub(crate) fn assert_complete(&self, src: &str) -> ParseResult<()> {
if let Some(date) = &self.date {
date.assert_complete(src)?;
}
Ok(())
}
}
macro_rules! set_date {
($($fn_name:ident($arg:ident: $arg_type:ty)),*) => {
impl RawDateTime {
$(pub(crate) fn $fn_name(&mut self, $arg: $arg_type) {
let mut date = self.date.take().unwrap_or_else(RawDate::new);
date.$arg = Some($arg);
self.date = Some(date);
})*
}
}
}
set_date! (
set_year(year: i16),
set_month(month: u8),
set_day(day: u8)
);
macro_rules! set_time {
($($fn_name:ident($arg:ident: $arg_type:ty)),*) => {
impl RawDateTime {
$(pub(crate) fn $fn_name(&mut self, $arg: $arg_type) {
let time = self.time.get_or_insert_with(RawTime::default);
time.$arg = $arg;
})*
}
}
}
set_time!(
set_hour(hour: u8),
set_minute(minute: u8),
set_second(second: u8),
set_nanosecond(nanosecond: u64)
);
impl RawDateTime {
pub(crate) fn set_utc_offset(&mut self, hhmm: i32) {
let hours = hhmm / 100;
let minutes = hhmm % 100;
let time = self.time.get_or_insert_with(RawTime::default);
time.utc_offset = Some(hours * 3600 + minutes * 60);
}
}