use {
crate::{DateTime, Sha1Hash},
core::fmt::{self, Display},
std::io,
thiserror::Error,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DataComponent {
LastUpdate,
ExpirationDate,
Hash,
}
impl Display for DataComponent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let result = match self {
Self::LastUpdate => "last update",
Self::ExpirationDate => "expiration date",
Self::Hash => "hash",
};
write!(f, "{result}")
}
}
#[derive(Debug, Error)]
pub enum ParseFileError {
#[error(transparent)]
IoError(#[from] io::Error),
#[error(transparent)]
ParseLineError(#[from] ParseLineError),
#[error("incorrect hash: calculated = {calculated}, found = {found}")]
InvalidHash {
calculated: Sha1Hash,
found: Sha1Hash,
},
#[error("missing data: {0}")]
MissingData(DataComponent),
#[error("duplicate data on lines {line1} and {line2}: {data_component}")]
DuplicateData {
data_component: DataComponent,
line1: usize,
line2: usize,
},
}
#[derive(Clone, Debug, Error, Eq, PartialEq)]
pub enum InvalidDate {
#[error("day out of range: {0}")]
MonthOutOfRange(u8),
#[error("month out of range: {0}")]
DayOutOfRange(u8),
}
#[derive(Clone, Copy, Debug, Error, Eq, PartialEq)]
pub enum InvalidTime {
#[error("hours out of range: {0}")]
HoursOutOfRange(u8),
#[error("minutes out of range: {0}")]
MinutesOutOfRange(u8),
#[error("seconds out of range: {0}")]
SecondsOutOfRange(u8),
}
#[derive(Clone, Debug, Error, Eq, PartialEq)]
pub struct DateTimeNotRepresentable {
pub(crate) date_time: DateTime,
}
impl DateTimeNotRepresentable {
#[must_use]
pub const fn date_time(self) -> DateTime {
self.date_time
}
}
impl Display for DateTimeNotRepresentable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DateTime is not representable as 64-bit timestamp")
}
}
#[derive(Debug, Error)]
pub struct ParseLineError {
pub(crate) cause: ParseLineErrorKind,
pub(crate) line: String,
pub(crate) line_number: usize,
}
impl ParseLineError {
#[must_use]
pub const fn cause(&self) -> ParseLineErrorKind {
self.cause
}
#[must_use]
pub fn line(&self) -> &str {
&self.line
}
#[must_use]
pub const fn line_number(&self) -> usize {
self.line_number
}
}
impl Display for ParseLineError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{} on line {}: \"{}\"",
self.cause, self.line_number, self.line
)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ParseLineErrorKind {
InvalidTimestamp,
InvalidLeapSecondLine,
InvalidTaiDiff,
InvalidHash,
}
impl Display for ParseLineErrorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let output = match self {
Self::InvalidTimestamp => "invalid timestamp",
Self::InvalidLeapSecondLine => "invalid leapsecond line",
Self::InvalidTaiDiff => "invalid TAI difference",
Self::InvalidHash => "invalid hash",
};
write!(f, "{output}")
}
}