-
-
Notifications
You must be signed in to change notification settings - Fork 283
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Guaranteed stable serde representation
This allows changing the internal representation of types without breaking backwards compatibility.
- Loading branch information
Showing
17 changed files
with
254 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
use core::convert::TryFrom; | ||
|
||
// (year, ordinal) | ||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub(crate) struct Date(pub(crate) i32, pub(crate) u16); | ||
|
||
impl From<crate::Date> for Date { | ||
#[inline] | ||
fn from(original: crate::Date) -> Self { | ||
Self(original.year(), original.ordinal()) | ||
} | ||
} | ||
|
||
impl TryFrom<Date> for crate::Date { | ||
type Error = &'static str; | ||
|
||
#[inline] | ||
fn try_from(original: Date) -> Result<Self, Self::Error> { | ||
Self::try_from_yo(original.0, original.1).map_err(|_| "invalid value") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// (seconds, nanoseconds) | ||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub(crate) struct Duration(i64, u32); | ||
|
||
impl From<crate::Duration> for Duration { | ||
#[inline] | ||
fn from(original: crate::Duration) -> Self { | ||
Self(original.whole_seconds(), original.subsec_nanoseconds()) | ||
} | ||
} | ||
|
||
impl From<Duration> for crate::Duration { | ||
#[inline] | ||
fn from(original: Duration) -> Self { | ||
Self::new(original.0, original.1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//! Types with guaranteed stable serde representations. | ||
//! | ||
//! This allows for the ability to change the internal structure of a type while | ||
//! maintaining backwards compatibility. | ||
//! | ||
//! Strings are avoided where possible to allow for optimal representations in | ||
//! various binary forms. | ||
#![allow(clippy::missing_docs_in_private_items)] | ||
|
||
// OffsetDateTime is in the primitive_date_time module. | ||
|
||
mod date; | ||
mod duration; | ||
mod primitive_date_time; | ||
mod sign; | ||
mod time; | ||
mod utc_offset; | ||
mod weekday; | ||
|
||
pub(crate) use self::time::Time; | ||
pub(crate) use date::Date; | ||
pub(crate) use duration::Duration; | ||
pub(crate) use primitive_date_time::PrimitiveDateTime; | ||
pub(crate) use sign::Sign; | ||
pub(crate) use utc_offset::UtcOffset; | ||
pub(crate) use weekday::Weekday; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
use core::convert::{TryFrom, TryInto}; | ||
|
||
// Date followed by Time | ||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub(crate) struct PrimitiveDateTime(i32, u16, u32, u32); | ||
|
||
impl From<crate::PrimitiveDateTime> for PrimitiveDateTime { | ||
#[inline] | ||
fn from(original: crate::PrimitiveDateTime) -> Self { | ||
let date: crate::serde::Date = original.date().into(); | ||
let time: crate::serde::Time = original.time().into(); | ||
Self(date.0, date.1, time.0, time.1) | ||
} | ||
} | ||
|
||
impl TryFrom<PrimitiveDateTime> for crate::PrimitiveDateTime { | ||
type Error = &'static str; | ||
|
||
#[inline] | ||
fn try_from(original: PrimitiveDateTime) -> Result<Self, Self::Error> { | ||
let date = crate::serde::Date(original.0, original.1); | ||
let time = crate::serde::Time(original.2, original.3); | ||
Ok(Self::new(date.try_into()?, time.into())) | ||
} | ||
} | ||
|
||
impl From<crate::OffsetDateTime> for PrimitiveDateTime { | ||
#[inline] | ||
fn from(original: crate::OffsetDateTime) -> Self { | ||
// Simplify handling by always using UTC. | ||
let original = original.to_offset(crate::UtcOffset::UTC); | ||
let date: crate::serde::Date = original.date().into(); | ||
let time: crate::serde::Time = original.time().into(); | ||
Self(date.0, date.1, time.0, time.1) | ||
} | ||
} | ||
|
||
impl TryFrom<PrimitiveDateTime> for crate::OffsetDateTime { | ||
type Error = &'static str; | ||
|
||
#[inline] | ||
fn try_from(original: PrimitiveDateTime) -> Result<Self, Self::Error> { | ||
let date = crate::serde::Date(original.0, original.1); | ||
let time = crate::serde::Time(original.2, original.3); | ||
Ok(crate::PrimitiveDateTime::new(date.try_into()?, time.into()) | ||
.using_offset(crate::UtcOffset::UTC)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
use core::convert::TryFrom; | ||
|
||
// positive => 1 | ||
// negative => -1 | ||
// zero => 0 | ||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub(crate) struct Sign(i8); | ||
|
||
impl From<crate::Sign> for Sign { | ||
#[inline] | ||
fn from(original: crate::Sign) -> Self { | ||
match original { | ||
crate::Sign::Positive => Self(1), | ||
crate::Sign::Negative => Self(-1), | ||
crate::Sign::Zero => Self(0), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<Sign> for crate::Sign { | ||
type Error = &'static str; | ||
|
||
#[inline] | ||
fn try_from(original: Sign) -> Result<Self, Self::Error> { | ||
match original { | ||
Sign(1) => Ok(Self::Positive), | ||
Sign(-1) => Ok(Self::Negative), | ||
Sign(0) => Ok(Self::Zero), | ||
_ => Err("invalid value"), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// (seconds since midnight, nanoseconds within second) | ||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub(crate) struct Time(pub(crate) u32, pub(crate) u32); | ||
|
||
impl From<crate::Time> for Time { | ||
#[inline] | ||
fn from(original: crate::Time) -> Self { | ||
Self( | ||
original.hour() as u32 * 3_600 | ||
+ original.minute() as u32 * 60 | ||
+ original.second() as u32, | ||
original.nanosecond(), | ||
) | ||
} | ||
} | ||
|
||
impl From<Time> for crate::Time { | ||
#[inline] | ||
fn from(original: Time) -> Self { | ||
Self::from_nanoseconds_since_midnight(original.0 as u64 * 1_000_000_000 + original.1 as u64) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// seconds offset from UTC, positive is east | ||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub(crate) struct UtcOffset(i32); | ||
|
||
impl From<crate::UtcOffset> for UtcOffset { | ||
#[inline] | ||
fn from(original: crate::UtcOffset) -> Self { | ||
Self(original.as_seconds()) | ||
} | ||
} | ||
|
||
impl From<UtcOffset> for crate::UtcOffset { | ||
#[inline] | ||
fn from(original: UtcOffset) -> Self { | ||
Self::seconds(original.0) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
use core::convert::TryFrom; | ||
|
||
// 1-indexed day from Monday | ||
#[derive(serde::Serialize, serde::Deserialize)] | ||
pub(crate) struct Weekday(u8); | ||
|
||
impl From<crate::Weekday> for Weekday { | ||
#[inline] | ||
fn from(original: crate::Weekday) -> Self { | ||
Self(original.iso_weekday_number()) | ||
} | ||
} | ||
|
||
impl TryFrom<Weekday> for crate::Weekday { | ||
type Error = &'static str; | ||
|
||
#[inline] | ||
fn try_from(original: Weekday) -> Result<Self, Self::Error> { | ||
match original { | ||
Weekday(1) => Ok(Self::Monday), | ||
Weekday(2) => Ok(Self::Tuesday), | ||
Weekday(3) => Ok(Self::Wednesday), | ||
Weekday(4) => Ok(Self::Thursday), | ||
Weekday(5) => Ok(Self::Friday), | ||
Weekday(6) => Ok(Self::Saturday), | ||
Weekday(7) => Ok(Self::Sunday), | ||
_ => Err("invalid value"), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters