Skip to content

Commit

Permalink
archive derive of PartialEq for rkyv - 0.4.x (#959)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkatychev committed Oct 10, 2023
1 parent 0f19d6b commit 02bdd1d
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
- run: |
cargo hack check --feature-powerset --optional-deps serde,rkyv \
cargo hack check --feature-powerset --optional-deps serde \
--skip __internal_bench,iana-time-zone,pure-rust-locales,libc,winapi \
--all-targets
# run using `bash` on all platforms for consistent
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ clock = ["std", "winapi", "iana-time-zone", "android-tzdata"]
oldtime = []
wasmbind = ["wasm-bindgen", "js-sys"]
unstable-locales = ["pure-rust-locales"]
rkyv-validation = ["rkyv/validation"]
__internal_bench = []

[dependencies]
num-traits = { version = "0.2", default-features = false }
rustc-serialize = { version = "0.3.20", optional = true }
serde = { version = "1.0.99", default-features = false, optional = true }
pure-rust-locales = { version = "0.7", optional = true }
rkyv = { version = "0.7", optional = true }
rkyv = { version = "0.7.41", optional = true }
arbitrary = { version = "1.0.0", features = ["derive"], optional = true }

[target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion src/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ impl<Tz: TimeZone> Eq for Date<Tz> {}

impl<Tz: TimeZone> PartialOrd for Date<Tz> {
fn partial_cmp(&self, other: &Date<Tz>) -> Option<Ordering> {
self.date.partial_cmp(&other.date)
Some(self.cmp(other))
}
}

Expand Down
27 changes: 27 additions & 0 deletions src/datetime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ mod tests;
/// [`TimeZone`](./offset/trait.TimeZone.html) implementations.
#[derive(Clone)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "rkyv", archive(compare(PartialEq, PartialOrd)))]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
pub struct DateTime<Tz: TimeZone> {
datetime: NaiveDateTime,
offset: Tz::Offset,
Expand Down Expand Up @@ -1504,6 +1506,31 @@ impl<Tz: TimeZone> fmt::Debug for DateTime<Tz> {
}
}

// `fmt::Debug` is hand implemented for the `rkyv::Archive` variant of `DateTime` because
// deriving a trait recursively does not propagate trait defined associated types with their own
// constraints:
// In our case `<<Tz as offset::TimeZone>::Offset as Archive>::Archived`
// cannot be formatted using `{:?}` because it doesn't implement `Debug`.
// See below for further discussion:
// * https://github.com/rust-lang/rust/issues/26925
// * https://github.com/rkyv/rkyv/issues/333
// * https://github.com/dtolnay/syn/issues/370
#[cfg(feature = "rkyv-validation")]
impl<Tz: TimeZone> fmt::Debug for ArchivedDateTime<Tz>
where
Tz: Archive,
<Tz as Archive>::Archived: fmt::Debug,
<<Tz as TimeZone>::Offset as Archive>::Archived: fmt::Debug,
<Tz as TimeZone>::Offset: fmt::Debug + Archive,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ArchivedDateTime")
.field("datetime", &self.datetime)
.field("offset", &self.offset)
.finish()
}
}

impl<Tz: TimeZone> fmt::Display for DateTime<Tz>
where
Tz::Offset: fmt::Display,
Expand Down
10 changes: 10 additions & 0 deletions src/duration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ macro_rules! try_opt {
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(
feature = "rkyv",
archive(compare(PartialEq, PartialOrd)),
archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
pub struct Duration {
secs: i64,
nanos: i32, // Always 0 <= nanos < NANOS_PER_SEC
Expand Down Expand Up @@ -795,4 +797,12 @@ mod tests {
Err(OutOfRangeError(()))
);
}

#[test]
#[cfg(feature = "rkyv-validation")]
fn test_rkyv_validation() {
let duration = Duration::seconds(1);
let bytes = rkyv::to_bytes::<_, 16>(&duration).unwrap();
assert_eq!(rkyv::from_bytes::<Duration>(&bytes).unwrap(), duration);
}
}
2 changes: 1 addition & 1 deletion src/format/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ where
};
s = match s.len() {
len if len >= 2 => &s[2..],
len if len == 0 => s,
0 => s,
_ => return Err(TOO_SHORT),
};

Expand Down
10 changes: 10 additions & 0 deletions src/month.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ use crate::OutOfRange;
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(
feature = "rkyv",
archive(compare(PartialEq)),
archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Month {
/// January
Expand Down Expand Up @@ -417,4 +419,12 @@ mod tests {
from_str::<Month>(string).unwrap_err();
}
}

#[test]
#[cfg(feature = "rkyv-validation")]
fn test_rkyv_validation() {
let month = Month::January;
let bytes = rkyv::to_bytes::<_, 1>(&month).unwrap();
assert_eq!(rkyv::from_bytes::<Month>(&bytes).unwrap(), month);
}
}
14 changes: 14 additions & 0 deletions src/naive/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,10 @@ impl Days {
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(
feature = "rkyv",
archive(compare(PartialEq, PartialOrd)),
archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
pub struct NaiveDate {
ymdf: DateImpl, // (year << 13) | of
}
Expand Down Expand Up @@ -3324,6 +3326,18 @@ mod tests {
}
}

#[test]
#[cfg(feature = "rkyv-validation")]
fn test_rkyv_validation() {
let date_min = NaiveDate::MIN;
let bytes = rkyv::to_bytes::<_, 4>(&date_min).unwrap();
assert_eq!(rkyv::from_bytes::<NaiveDate>(&bytes).unwrap(), date_min);

let date_max = NaiveDate::MAX;
let bytes = rkyv::to_bytes::<_, 4>(&date_max).unwrap();
assert_eq!(rkyv::from_bytes::<NaiveDate>(&bytes).unwrap(), date_max);
}

// MAX_YEAR-12-31 minus 0000-01-01
// = (MAX_YEAR-12-31 minus 0000-12-31) + (0000-12-31 - 0000-01-01)
// = MAX_YEAR * 365 + (# of leap years from 0001 to MAX_YEAR) + 365
Expand Down
2 changes: 2 additions & 0 deletions src/naive/datetime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ pub const MAX_DATETIME: NaiveDateTime = NaiveDateTime::MAX;
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(
feature = "rkyv",
archive(compare(PartialEq, PartialOrd)),
archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct NaiveDateTime {
date: NaiveDate,
Expand Down
12 changes: 12 additions & 0 deletions src/naive/datetime/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,3 +536,15 @@ fn test_and_timezone_min_max_dates() {
}
}
}

#[test]
#[cfg(feature = "rkyv-validation")]
fn test_rkyv_validation() {
let dt_min = NaiveDateTime::MIN;
let bytes = rkyv::to_bytes::<_, 12>(&dt_min).unwrap();
assert_eq!(rkyv::from_bytes::<NaiveDateTime>(&bytes).unwrap(), dt_min);

let dt_max = NaiveDateTime::MAX;
let bytes = rkyv::to_bytes::<_, 12>(&dt_max).unwrap();
assert_eq!(rkyv::from_bytes::<NaiveDateTime>(&bytes).unwrap(), dt_max);
}
16 changes: 16 additions & 0 deletions src/naive/isoweek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ use rkyv::{Archive, Deserialize, Serialize};
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(
feature = "rkyv",
archive(compare(PartialEq)),
archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
pub struct IsoWeek {
// note that this allows for larger year range than `NaiveDate`.
// this is crucial because we have an edge case for the first and last week supported,
Expand Down Expand Up @@ -151,6 +153,8 @@ impl fmt::Debug for IsoWeek {

#[cfg(test)]
mod tests {
#[cfg(feature = "rkyv-validation")]
use super::IsoWeek;
use crate::naive::{internals, NaiveDate};
use crate::Datelike;

Expand Down Expand Up @@ -205,4 +209,16 @@ mod tests {
assert!(monday.iso_week() >= friday.iso_week());
assert!(monday.iso_week() <= friday.iso_week());
}

#[test]
#[cfg(feature = "rkyv-validation")]
fn test_rkyv_validation() {
let minweek = NaiveDate::MIN.iso_week();
let bytes = rkyv::to_bytes::<_, 4>(&minweek).unwrap();
assert_eq!(rkyv::from_bytes::<IsoWeek>(&bytes).unwrap(), minweek);

let maxweek = NaiveDate::MAX.iso_week();
let bytes = rkyv::to_bytes::<_, 4>(&maxweek).unwrap();
assert_eq!(rkyv::from_bytes::<IsoWeek>(&bytes).unwrap(), maxweek);
}
}
2 changes: 2 additions & 0 deletions src/naive/time/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,10 @@ mod tests;
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(
feature = "rkyv",
archive(compare(PartialEq, PartialOrd)),
archive_attr(derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
pub struct NaiveTime {
secs: u32,
frac: u32,
Expand Down
12 changes: 12 additions & 0 deletions src/naive/time/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,3 +376,15 @@ fn test_overflowing_offset() {
assert_eq!(t.overflowing_add_offset(positive_offset).0, t + positive_offset);
assert_eq!(t.overflowing_sub_offset(positive_offset).0, t - positive_offset);
}

#[test]
#[cfg(feature = "rkyv-validation")]
fn test_rkyv_validation() {
let t_min = NaiveTime::MIN;
let bytes = rkyv::to_bytes::<_, 8>(&t_min).unwrap();
assert_eq!(rkyv::from_bytes::<NaiveTime>(&bytes).unwrap(), t_min);

let t_max = NaiveTime::MAX;
let bytes = rkyv::to_bytes::<_, 8>(&t_max).unwrap();
assert_eq!(rkyv::from_bytes::<NaiveTime>(&bytes).unwrap(), t_max);
}
15 changes: 14 additions & 1 deletion src/offset/fixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ use crate::naive::{NaiveDate, NaiveDateTime};
/// [`west_opt`](#method.west_opt) methods for examples.
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "rkyv", archive_attr(derive(Clone, Copy, PartialEq, Eq, Hash, Debug)))]
#[cfg_attr(
feature = "rkyv",
archive(compare(PartialEq)),
archive_attr(derive(Clone, Copy, PartialEq, Eq, Hash, Debug))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
pub struct FixedOffset {
local_minus_utc: i32,
}
Expand Down Expand Up @@ -222,4 +227,12 @@ mod tests {
let offset = FixedOffset::from_str("+06:30").unwrap();
assert_eq!(offset.local_minus_utc, (6 * 3600) + 1800);
}

#[test]
#[cfg(feature = "rkyv-validation")]
fn test_rkyv_validation() {
let offset = FixedOffset::from_str("-0500").unwrap();
let bytes = rkyv::to_bytes::<_, 4>(&offset).unwrap();
assert_eq!(rkyv::from_bytes::<FixedOffset>(&bytes).unwrap(), offset);
}
}
16 changes: 15 additions & 1 deletion src/offset/local/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ mod tz_info;
/// ```
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "rkyv", archive_attr(derive(Clone, Copy, Debug)))]
#[cfg_attr(feature = "rkyv", archive(compare(PartialEq)), archive_attr(derive(Clone, Copy, Debug)))]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Local;

Expand Down Expand Up @@ -258,4 +259,17 @@ mod tests {
);
}
}

#[test]
#[cfg(feature = "rkyv-validation")]
fn test_rkyv_validation() {
let local = Local;
// Local is a ZST and serializes to 0 bytes
let bytes = rkyv::to_bytes::<_, 0>(&local).unwrap();
assert_eq!(bytes.len(), 0);

// but is deserialized to an archived variant without a
// wrapping object
assert_eq!(rkyv::from_bytes::<Local>(&bytes).unwrap(), super::ArchivedLocal);
}
}
7 changes: 6 additions & 1 deletion src/offset/utc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ use crate::{Date, DateTime};
/// ```
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "rkyv", archive_attr(derive(Clone, Copy, PartialEq, Eq, Debug, Hash)))]
#[cfg_attr(
feature = "rkyv",
archive(compare(PartialEq)),
archive_attr(derive(Clone, Copy, PartialEq, Eq, Debug, Hash))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Utc;

Expand Down
16 changes: 15 additions & 1 deletion src/weekday.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ use crate::OutOfRange;
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "rkyv", archive_attr(derive(Clone, Copy, PartialEq, Eq, Debug, Hash)))]
#[cfg_attr(
feature = "rkyv",
archive(compare(PartialEq)),
archive_attr(derive(Clone, Copy, PartialEq, Eq, Debug, Hash))
)]
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Weekday {
/// Monday.
Expand Down Expand Up @@ -381,4 +386,13 @@ mod tests {
from_str::<Weekday>(str).unwrap_err();
}
}

#[test]
#[cfg(feature = "rkyv-validation")]
fn test_rkyv_validation() {
let mon = Weekday::Mon;
let bytes = rkyv::to_bytes::<_, 1>(&mon).unwrap();

assert_eq!(rkyv::from_bytes::<Weekday>(&bytes).unwrap(), mon);
}
}

0 comments on commit 02bdd1d

Please sign in to comment.