Simplify SerdeError

This commit is contained in:
Paul Dicker 2024-02-24 20:52:45 +01:00 committed by Paul Dicker
parent 0b68d19a3e
commit bbdc332958
3 changed files with 51 additions and 91 deletions

View File

@ -147,8 +147,8 @@ pub mod ts_nanoseconds {
use core::fmt; use core::fmt;
use serde::{de, ser}; use serde::{de, ser};
use crate::serde::serde_from; use crate::serde::invalid_ts;
use crate::{DateTime, TimeZone, Utc}; use crate::{DateTime, Utc};
use super::NanoSecondsTimestampVisitor; use super::NanoSecondsTimestampVisitor;
@ -239,13 +239,11 @@ pub mod ts_nanoseconds {
where where
E: de::Error, E: de::Error,
{ {
serde_from( DateTime::from_timestamp(
Utc.timestamp_opt( value.div_euclid(1_000_000_000),
value.div_euclid(1_000_000_000), (value.rem_euclid(1_000_000_000)) as u32,
(value.rem_euclid(1_000_000_000)) as u32,
),
&value,
) )
.ok_or_else(|| invalid_ts(value))
} }
/// Deserialize a timestamp in nanoseconds since the epoch /// Deserialize a timestamp in nanoseconds since the epoch
@ -253,10 +251,8 @@ pub mod ts_nanoseconds {
where where
E: de::Error, E: de::Error,
{ {
serde_from( DateTime::from_timestamp((value / 1_000_000_000) as i64, (value % 1_000_000_000) as u32)
Utc.timestamp_opt((value / 1_000_000_000) as i64, (value % 1_000_000_000) as u32), .ok_or_else(|| invalid_ts(value))
&value,
)
} }
} }
} }
@ -447,8 +443,8 @@ pub mod ts_microseconds {
use core::fmt; use core::fmt;
use serde::{de, ser}; use serde::{de, ser};
use crate::serde::serde_from; use crate::serde::invalid_ts;
use crate::{DateTime, TimeZone, Utc}; use crate::{DateTime, Utc};
use super::MicroSecondsTimestampVisitor; use super::MicroSecondsTimestampVisitor;
@ -529,13 +525,11 @@ pub mod ts_microseconds {
where where
E: de::Error, E: de::Error,
{ {
serde_from( DateTime::from_timestamp(
Utc.timestamp_opt( value.div_euclid(1_000_000),
value.div_euclid(1_000_000), (value.rem_euclid(1_000_000) * 1000) as u32,
(value.rem_euclid(1_000_000) * 1_000) as u32,
),
&value,
) )
.ok_or_else(|| invalid_ts(value))
} }
/// Deserialize a timestamp in milliseconds since the epoch /// Deserialize a timestamp in milliseconds since the epoch
@ -543,10 +537,11 @@ pub mod ts_microseconds {
where where
E: de::Error, E: de::Error,
{ {
serde_from( DateTime::from_timestamp(
Utc.timestamp_opt((value / 1_000_000) as i64, ((value % 1_000_000) * 1_000) as u32), (value / 1_000_000) as i64,
&value, ((value % 1_000_000) * 1_000) as u32,
) )
.ok_or_else(|| invalid_ts(value))
} }
} }
} }
@ -726,8 +721,8 @@ pub mod ts_milliseconds {
use core::fmt; use core::fmt;
use serde::{de, ser}; use serde::{de, ser};
use crate::serde::serde_from; use crate::serde::invalid_ts;
use crate::{DateTime, TimeZone, Utc}; use crate::{DateTime, Utc};
use super::MilliSecondsTimestampVisitor; use super::MilliSecondsTimestampVisitor;
@ -808,7 +803,7 @@ pub mod ts_milliseconds {
where where
E: de::Error, E: de::Error,
{ {
serde_from(Utc.timestamp_millis_opt(value), &value) DateTime::from_timestamp_millis(value).ok_or_else(|| invalid_ts(value))
} }
/// Deserialize a timestamp in milliseconds since the epoch /// Deserialize a timestamp in milliseconds since the epoch
@ -816,10 +811,8 @@ pub mod ts_milliseconds {
where where
E: de::Error, E: de::Error,
{ {
serde_from( DateTime::from_timestamp((value / 1000) as i64, ((value % 1000) * 1_000_000) as u32)
Utc.timestamp_opt((value / 1000) as i64, ((value % 1000) * 1_000_000) as u32), .ok_or_else(|| invalid_ts(value))
&value,
)
} }
} }
} }
@ -1006,8 +999,8 @@ pub mod ts_seconds {
use core::fmt; use core::fmt;
use serde::{de, ser}; use serde::{de, ser};
use crate::serde::serde_from; use crate::serde::invalid_ts;
use crate::{DateTime, LocalResult, TimeZone, Utc}; use crate::{DateTime, Utc};
use super::SecondsTimestampVisitor; use super::SecondsTimestampVisitor;
@ -1078,7 +1071,7 @@ pub mod ts_seconds {
where where
E: de::Error, E: de::Error,
{ {
serde_from(Utc.timestamp_opt(value, 0), &value) DateTime::from_timestamp(value, 0).ok_or_else(|| invalid_ts(value))
} }
/// Deserialize a timestamp in seconds since the epoch /// Deserialize a timestamp in seconds since the epoch
@ -1086,14 +1079,11 @@ pub mod ts_seconds {
where where
E: de::Error, E: de::Error,
{ {
serde_from( if value > i64::MAX as u64 {
if value > i64::MAX as u64 { Err(invalid_ts(value))
LocalResult::None } else {
} else { DateTime::from_timestamp(value as i64, 0).ok_or_else(|| invalid_ts(value))
Utc.timestamp_opt(value as i64, 0) }
},
&value,
)
} }
} }
} }

View File

@ -629,56 +629,30 @@ pub use naive::__BenchYearFlags;
/// [2]: https://serde.rs/field-attrs.html#with /// [2]: https://serde.rs/field-attrs.html#with
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
pub mod serde { pub mod serde {
use crate::offset::LocalResult;
use core::fmt; use core::fmt;
use serde::de; use serde::de;
pub use super::datetime::serde::*; pub use super::datetime::serde::*;
// lik? function to convert a LocalResult into a serde-ish Result /// Create a custom `de::Error` with `SerdeError::InvalidTimestamp`.
pub(crate) fn serde_from<T, E, V>(me: LocalResult<T>, ts: &V) -> Result<T, E> pub(crate) fn invalid_ts<E, T>(value: T) -> E
where where
E: de::Error, E: de::Error,
V: fmt::Display,
T: fmt::Display, T: fmt::Display,
{ {
match me { E::custom(SerdeError::InvalidTimestamp(value))
LocalResult::None => Err(E::custom(ne_timestamp(ts))),
LocalResult::Ambiguous(min, max) => {
Err(E::custom(SerdeError::Ambiguous { timestamp: ts, min, max }))
}
LocalResult::Single(val) => Ok(val),
}
} }
pub(crate) enum SerdeError<V: fmt::Display, D: fmt::Display> { enum SerdeError<T: fmt::Display> {
NonExistent { timestamp: V }, InvalidTimestamp(T),
Ambiguous { timestamp: V, min: D, max: D },
} }
/// Construct a [`SerdeError::NonExistent`] impl<T: fmt::Display> fmt::Display for SerdeError<T> {
pub(crate) fn ne_timestamp<T: fmt::Display>(ts: T) -> SerdeError<T, u8> {
SerdeError::NonExistent::<T, u8> { timestamp: ts }
}
impl<V: fmt::Display, D: fmt::Display> fmt::Debug for SerdeError<V, D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ChronoSerdeError({})", self)
}
}
// impl<V: fmt::Display, D: fmt::Debug> core::error::Error for SerdeError<V, D> {}
impl<V: fmt::Display, D: fmt::Display> fmt::Display for SerdeError<V, D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
SerdeError::NonExistent { timestamp } => { SerdeError::InvalidTimestamp(ts) => {
write!(f, "value is not a legal timestamp: {}", timestamp) write!(f, "value is not a legal timestamp: {}", ts)
} }
SerdeError::Ambiguous { timestamp, min, max } => write!(
f,
"value is an ambiguous timestamp: {}, could be either of {}, {}",
timestamp, min, max
),
} }
} }
} }

View File

@ -82,7 +82,7 @@ pub mod ts_nanoseconds {
use core::fmt; use core::fmt;
use serde::{de, ser}; use serde::{de, ser};
use crate::serde::ne_timestamp; use crate::serde::invalid_ts;
use crate::NaiveDateTime; use crate::NaiveDateTime;
/// Serialize a datetime into an integer number of nanoseconds since the epoch /// Serialize a datetime into an integer number of nanoseconds since the epoch
@ -175,7 +175,7 @@ pub mod ts_nanoseconds {
value.div_euclid(1_000_000_000), value.div_euclid(1_000_000_000),
(value.rem_euclid(1_000_000_000)) as u32, (value.rem_euclid(1_000_000_000)) as u32,
) )
.ok_or_else(|| E::custom(ne_timestamp(value))) .ok_or_else(|| invalid_ts(value))
} }
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
@ -186,7 +186,7 @@ pub mod ts_nanoseconds {
(value / 1_000_000_000) as i64, (value / 1_000_000_000) as i64,
(value % 1_000_000_000) as u32, (value % 1_000_000_000) as u32,
) )
.ok_or_else(|| E::custom(ne_timestamp(value))) .ok_or_else(|| invalid_ts(value))
} }
} }
} }
@ -371,7 +371,7 @@ pub mod ts_microseconds {
use core::fmt; use core::fmt;
use serde::{de, ser}; use serde::{de, ser};
use crate::serde::ne_timestamp; use crate::serde::invalid_ts;
use crate::NaiveDateTime; use crate::NaiveDateTime;
/// Serialize a datetime into an integer number of microseconds since the epoch /// Serialize a datetime into an integer number of microseconds since the epoch
@ -450,8 +450,7 @@ pub mod ts_microseconds {
where where
E: de::Error, E: de::Error,
{ {
NaiveDateTime::from_timestamp_micros(value) NaiveDateTime::from_timestamp_micros(value).ok_or_else(|| invalid_ts(value))
.ok_or_else(|| E::custom(ne_timestamp(value)))
} }
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
@ -462,7 +461,7 @@ pub mod ts_microseconds {
(value / 1_000_000) as i64, (value / 1_000_000) as i64,
((value % 1_000_000) * 1_000) as u32, ((value % 1_000_000) * 1_000) as u32,
) )
.ok_or_else(|| E::custom(ne_timestamp(value))) .ok_or_else(|| invalid_ts(value))
} }
} }
} }
@ -635,7 +634,7 @@ pub mod ts_milliseconds {
use core::fmt; use core::fmt;
use serde::{de, ser}; use serde::{de, ser};
use crate::serde::ne_timestamp; use crate::serde::invalid_ts;
use crate::NaiveDateTime; use crate::NaiveDateTime;
/// Serialize a datetime into an integer number of milliseconds since the epoch /// Serialize a datetime into an integer number of milliseconds since the epoch
@ -714,8 +713,7 @@ pub mod ts_milliseconds {
where where
E: de::Error, E: de::Error,
{ {
NaiveDateTime::from_timestamp_millis(value) NaiveDateTime::from_timestamp_millis(value).ok_or_else(|| invalid_ts(value))
.ok_or_else(|| E::custom(ne_timestamp(value)))
} }
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
@ -726,7 +724,7 @@ pub mod ts_milliseconds {
(value / 1000) as i64, (value / 1000) as i64,
((value % 1000) * 1_000_000) as u32, ((value % 1000) * 1_000_000) as u32,
) )
.ok_or_else(|| E::custom(ne_timestamp(value))) .ok_or_else(|| invalid_ts(value))
} }
} }
} }
@ -895,7 +893,7 @@ pub mod ts_seconds {
use core::fmt; use core::fmt;
use serde::{de, ser}; use serde::{de, ser};
use crate::serde::ne_timestamp; use crate::serde::invalid_ts;
use crate::NaiveDateTime; use crate::NaiveDateTime;
/// Serialize a datetime into an integer number of seconds since the epoch /// Serialize a datetime into an integer number of seconds since the epoch
@ -967,16 +965,14 @@ pub mod ts_seconds {
where where
E: de::Error, E: de::Error,
{ {
NaiveDateTime::from_timestamp_opt(value, 0) NaiveDateTime::from_timestamp_opt(value, 0).ok_or_else(|| invalid_ts(value))
.ok_or_else(|| E::custom(ne_timestamp(value)))
} }
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where where
E: de::Error, E: de::Error,
{ {
NaiveDateTime::from_timestamp_opt(value as i64, 0) NaiveDateTime::from_timestamp_opt(value as i64, 0).ok_or_else(|| invalid_ts(value))
.ok_or_else(|| E::custom(ne_timestamp(value)))
} }
} }
} }