use crate::{
errors::{NumberParsingError, TimeOfDayParsingError},
parse::DecimalNumber,
};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub(crate) struct TimeOfDay {
pub(crate) hour: u8,
pub(crate) minute: u8,
pub(crate) second: u8,
pub(crate) subseconds: DecimalNumber,
}
impl TimeOfDay {
pub(crate) fn parse_partial(mut string: &str) -> Result<(Self, &str), TimeOfDayParsingError> {
let (hour, consumed_bytes) = lexical_core::parse_partial(string.as_bytes())?;
if consumed_bytes != 2 {
return Err(TimeOfDayParsingError::HourRepresentationNotTwoDigits);
}
string = string.get(consumed_bytes..).unwrap();
if string.starts_with(':') {
string = string.get(1..).unwrap();
} else {
return Err(TimeOfDayParsingError::ExpectedHourMinuteDelimiter);
}
let (minute, consumed_bytes) = lexical_core::parse_partial(string.as_bytes())?;
if consumed_bytes != 2 {
return Err(TimeOfDayParsingError::MinuteRepresentationNotTwoDigits);
}
string = string.get(consumed_bytes..).unwrap();
if string.starts_with(':') {
string = string.get(1..).unwrap();
} else {
return Err(TimeOfDayParsingError::ExpectedMinuteSecondDelimiter);
}
let (second, consumed_bytes) = lexical_core::parse_partial(string.as_bytes())?;
if consumed_bytes != 2 {
return Err(TimeOfDayParsingError::IntegerSecondRepresentationNotTwoDigits);
}
string = string.get(consumed_bytes..).unwrap();
let subseconds = if string.starts_with('.') {
string = string.get(1..).unwrap();
let (fraction, fractional_digits) = lexical_core::parse_partial(string.as_bytes())?;
string = string.get(fractional_digits..).unwrap();
let fractional_digits = fractional_digits
.try_into()
.map_err(|_| NumberParsingError::TooManyFractionalDigits { fractional_digits })?;
DecimalNumber {
integer: 0,
fraction,
fractional_digits,
}
} else {
DecimalNumber::ZERO
};
Ok((
TimeOfDay {
hour,
minute,
second,
subseconds,
},
string,
))
}
}