use super::error::Variant;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
#[cfg_attr(feature = "testing", derive(Eq))]
pub enum Status {
Waiting {
#[serde(with = "time::serde::iso8601")]
timestamp: time::OffsetDateTime,
},
Sent {
#[serde(with = "time::serde::iso8601")]
timestamp: time::OffsetDateTime,
},
HeldBack {
errors: Vec<Error>,
},
Failed {
error: Error,
},
}
#[cfg(feature = "testing")]
impl PartialEq for Status {
#[inline]
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Sent { .. }, Self::Sent { .. })
| (Self::Waiting { .. }, Self::Waiting { .. }) => true,
(Self::HeldBack { errors: l_errors }, Self::HeldBack { errors: r_errors }) => {
l_errors == r_errors
}
(Self::Failed { error: l_error, .. }, Self::Failed { error: r_error, .. }) => {
l_error == r_error
}
_ => false,
}
}
}
impl Default for Status {
#[inline]
fn default() -> Self {
Self::Waiting {
timestamp: time::OffsetDateTime::now_utc(),
}
}
}
impl Status {
#[must_use]
#[inline]
pub const fn is_sendable(&self) -> bool {
match self {
Self::Waiting { .. } | Self::HeldBack { .. } => true,
Self::Sent { .. } | Self::Failed { .. } => false,
}
}
#[inline]
pub fn held_back(&mut self, error: impl Into<Variant>) {
let error = error.into();
#[allow(clippy::wildcard_enum_match_arm)]
match self {
Self::HeldBack { errors } => {
errors.push(Error::new(error));
}
_ => {
*self = Self::HeldBack {
errors: vec![(Error::new(error))],
}
}
}
}
#[inline]
#[must_use]
pub fn sent() -> Self {
Self::Sent {
timestamp: time::OffsetDateTime::now_utc(),
}
}
#[inline]
#[must_use]
pub fn failed(error: impl Into<Variant>) -> Self {
Self::Failed {
error: Error::new(error.into()),
}
}
}
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "testing", derive(Eq))]
pub struct Error {
variant: Variant,
#[serde(with = "time::serde::iso8601")]
timestamp: time::OffsetDateTime,
}
#[cfg(feature = "testing")]
impl PartialEq for Error {
#[inline]
#[allow(clippy::unneeded_field_pattern)]
fn eq(&self, other: &Self) -> bool {
let Self {
variant: self_variant,
timestamp: _,
} = self;
let Self {
variant: other_variant,
timestamp: _,
} = other;
self_variant == other_variant
}
}
impl Error {
#[must_use]
#[inline]
pub fn new(variant: Variant) -> Self {
Self {
variant,
timestamp: time::OffsetDateTime::now_utc(),
}
}
#[cfg(feature = "testing")]
#[must_use]
#[inline]
pub const fn variant(&self) -> &Variant {
&self.variant
}
#[must_use]
#[inline]
pub const fn timestamp(&self) -> &time::OffsetDateTime {
&self.timestamp
}
}