diff --git a/CHANGELOG.md b/CHANGELOG.md index 5365a38..891d294 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## Changes between the versions +### 0.5.7 (2023-05-11) + +* Fewer macros = faster compile times +* Update to Time Zone Database release [2023c](https://mm.icann.org/pipermail/tz-announce/2023-March/000079.html) + ### 0.5.6 (2023-03-24) * Update to Time Zone Database release [2023b](https://mm.icann.org/pipermail/tz-announce/2023-March/000078.html) diff --git a/Cargo.toml b/Cargo.toml index 34c7fb1..357ffba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tzdb" -version = "0.5.6" +version = "0.5.7" edition = "2018" authors = ["René Kijewski "] repository = "https://github.com/Kijewski/tzdb" @@ -16,31 +16,16 @@ tz-rs = { version = "^0.6.14", default-features = false, features = ["const", "s iana-time-zone = { version = "^0.1.50", default-features = false } [dev-dependencies] -criterion = { version = "^0.3.6", default-features = false } proptest = "=1.0" -rand = { version = "^0.8.5", default-features = false, features = ["std", "small_rng"] } test-strategy = "=0.1.2" structmeta = "=0.1.4" -# 1.15 is edition 2021, used (transitively) by criterion -once_cell = "=1.14" -# 1.2 is edition 2021, used (transitively) by criterion -csv = "=1.1" -# 1.7 has rust-version = "1.59", used (transitively) by criterion -rayon = "=1.6" -# 1.11 has rust-version = "1.59", used (transitively) by criterion -rayon-core = "=1.10" - [features] default = ["fallback"] # Do not fail to compile for unknown target platforms: fallback = ["iana-time-zone/fallback"] -[[bench]] -name = "by-name" -harness = false - [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] @@ -50,5 +35,4 @@ members = [ ".", "examples/current-time", "make-tzdb", - "fuzz", ] diff --git a/Makefile b/Makefile index a17235d..0daa1aa 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .DELETE_ON_ERROR: -TZDB_VERSION := tzdb-2023b +TZDB_VERSION := tzdb-2023c src/generated/mod.rs: tmp/${TZDB_VERSION}/usr/share/zoneinfo/ cargo r --package make-tzdb --bin make-tzdb -- $(@D) $< tzdb.tar.lz.sha diff --git a/README.md b/README.md index b12548d..5414f6c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Static time zone information for [tz-rs](https://crates.io/crates/tz-rs). This crate provides all time zones found in the [Time Zone Database](https://www.iana.org/time-zones), -currently in the version 2023b (released 2023-03-23). +currently in the version 2023c (released 2023-03-28). See the documentation for a full list the the contained time zones: diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml new file mode 100644 index 0000000..ec100fa --- /dev/null +++ b/benchmarks/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "tzdb-bench" +version = "0.0.0" +edition = "2021" +authors = ["René Kijewski "] +repository = "https://github.com/Kijewski/tzdb" +description = "… benchmarking …" +license = "Apache-2.0" +# rust-version = "1.56" +publish = false + +[dependencies] +tzdb = { version = "*", path = ".." } + +[dev-dependencies] +criterion = { version = "0.4.0", default-features = false } +rand = { version = "0.8.5", default-features = false, features = ["std"] } +rand_xoshiro = "0.6.0" +test-strategy = "0.3.0" +structmeta = "0.2.0" + +[[bench]] +name = "by-name" +harness = false + +[workspace] +members = ["."] diff --git a/benches/by-name.rs b/benchmarks/benches/by-name.rs similarity index 95% rename from benches/by-name.rs rename to benchmarks/benches/by-name.rs index 51d0f59..32dec8a 100644 --- a/benches/by-name.rs +++ b/benchmarks/benches/by-name.rs @@ -1,9 +1,9 @@ use std::convert::TryInto; use std::time::{Duration, Instant}; -use rand::rngs::SmallRng; use rand::seq::{IteratorRandom, SliceRandom}; use rand::SeedableRng; +use rand_xoshiro::Xoroshiro128PlusPlus; use tzdb::{raw_tz_by_name, TZ_NAMES}; fn benchmark_by_name(c: &mut criterion::Criterion) { @@ -57,7 +57,7 @@ fn benchmark_by_name(c: &mut criterion::Criterion) { // insert a bunch of unknown names for idx in 0..100 { - let mut rng = SmallRng::seed_from_u64(idx); + let mut rng = Xoroshiro128PlusPlus::seed_from_u64(idx); let mut continent = *b"abcdefghijklmnopqrstuvwxyz"; let mut city = *b"abcdefghijklmnopqrstuvwxyz"; @@ -84,7 +84,7 @@ fn benchmark_by_name(c: &mut criterion::Criterion) { b.iter_custom(|iters| { let mut nanos = 0; for i in 0..iters { - names.shuffle(&mut SmallRng::seed_from_u64(i)); + names.shuffle(&mut Xoroshiro128PlusPlus::seed_from_u64(i)); let start = Instant::now(); let names = criterion::black_box(&*names); diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 727d835..010cfff 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -38,3 +38,6 @@ path = "bin/libfuzzer.rs" test = false doc = false required-features = ["libfuzzer-sys"] + +[workspace] +members = ["."] diff --git a/make-tzdb/src/main.rs b/make-tzdb/src/main.rs index bf7268b..28442ac 100644 --- a/make-tzdb/src/main.rs +++ b/make-tzdb/src/main.rs @@ -223,24 +223,86 @@ pub fn main() -> anyhow::Result<()> { mod test_all_names; pub(crate) mod by_name; -use tz::TimeZoneRef; - -macro_rules! unwrap {{ - ($($tt:tt)*) => {{ - match $($tt)* {{ - Ok(value) => value, - Err(_) => {{ - #[allow(unconditional_panic)] - let err = [][0]; - err - }} - }} +pub(crate) const VERSION: &str = {version:?}; +pub(crate) const VERSION_HASH: &str = {hash:?}; + +pub(crate) const fn new_time_zone_ref( + transitions: &'static [tz::timezone::Transition], + local_time_types: &'static [tz::LocalTimeType], + leap_seconds: &'static [tz::timezone::LeapSecond], + extra_rule: &'static Option, +) -> tz::timezone::TimeZoneRef<'static> {{ + match tz::timezone::TimeZoneRef::new(transitions, local_time_types, leap_seconds, extra_rule) {{ + Ok(value) => value, + Err(_) => {{ + #[allow(unconditional_panic)] + let err = [][0]; + err + }}, }} }} -pub(crate) use unwrap; -pub(crate) const VERSION: &str = {version:?}; -pub(crate) const VERSION_HASH: &str = {hash:?}; +pub(crate) const fn new_local_time_type( + ut_offset: i32, + is_dst: bool, + time_zone_designation: Option<&[u8]>, +) -> tz::LocalTimeType {{ + match tz::LocalTimeType::new(ut_offset, is_dst, time_zone_designation) {{ + Ok(value) => value, + Err(_) => {{ + #[allow(unconditional_panic)] + let err = [][0]; + err + }}, + }} +}} + +pub(crate) const fn new_transition( + unix_leap_time: i64, + local_time_type_index: usize, +) -> tz::timezone::Transition {{ + tz::timezone::Transition::new(unix_leap_time, local_time_type_index) +}} + +pub(crate) const fn new_alternate_time( + std: tz::LocalTimeType, + dst: tz::LocalTimeType, + dst_start: tz::timezone::RuleDay, + dst_start_time: i32, + dst_end: tz::timezone::RuleDay, + dst_end_time: i32, +) -> tz::timezone::AlternateTime {{ + match tz::timezone::AlternateTime::new( + std, + dst, + dst_start, + dst_start_time, + dst_end, + dst_end_time, + ) {{ + Ok(value) => value, + Err(_) => {{ + #[allow(unconditional_panic)] + let err = [][0]; + err + }}, + }} +}} + +pub(crate) const fn new_month_week_day( + month: u8, + week: u8, + week_day: u8, +) -> tz::timezone::MonthWeekDay {{ + match tz::timezone::MonthWeekDay::new(month, week, week_day) {{ + Ok(value) => value, + Err(_) => {{ + #[allow(unconditional_panic)] + let err = [][0]; + err + }}, + }} +}} "# )?; @@ -369,26 +431,21 @@ pub(crate) const VERSION_HASH: &str = {hash:?}; // all known time zones as reference to (raw_)tzdata writeln!(f, "/// All defined time zones statically accessible")?; writeln!(f, "pub mod time_zone {{")?; - writeln!(f, " use super::*;")?; for (folder, entries) in &entries_by_major { - writeln!(f)?; if let Some(folder) = folder { writeln!(f, "/// {}", folder)?; writeln!(f, "pub mod {} {{", folder)?; - writeln!(f, " use super::*;")?; } for entry in entries { - writeln!(f)?; writeln!(f, " /// Time zone data for {},", entry.full)?; writeln!( f, - "pub const {}: TimeZoneRef<'static> = tzdata::{};", + "pub const {}: tz::TimeZoneRef<'static> = crate::generated::tzdata::{};", entry.minor, entry.canon, )?; } for entry in entries { - writeln!(f)?; writeln!( f, " /// Raw, unparsed time zone data for {},", @@ -396,7 +453,7 @@ pub(crate) const VERSION_HASH: &str = {hash:?}; )?; writeln!( f, - "pub const RAW_{}: &[u8] = raw_tzdata::{};", + "pub const RAW_{}: &[u8] = crate::generated::raw_tzdata::{};", entry.minor, entry.canon, )?; } @@ -436,9 +493,9 @@ pub(crate) const VERSION_HASH: &str = {hash:?}; writeln!(f)?; writeln!( f, - "pub(crate) const {}: TimeZoneRef<'static> = {};", + "pub(crate) const {}: tz::TimeZoneRef<'static> = {};", &entries[0].canon, - parse::Unwrap(&tz_convert(bytes)), + tz_convert(bytes), )?; } writeln!(f, "}}")?; diff --git a/make-tzdb/src/parse.rs b/make-tzdb/src/parse.rs index 6c13c25..3f95c1f 100644 --- a/make-tzdb/src/parse.rs +++ b/make-tzdb/src/parse.rs @@ -85,7 +85,7 @@ impl fmt::Display for Transition { } = &self; writeln!( f, - "Transition::new({}, {})", + "crate::generated::new_transition({}, {})", unix_leap_time, local_time_type_index )?; Ok(()) @@ -102,7 +102,7 @@ impl fmt::Display for LocalTimeType { let time_zone_designation = time_zone_designation.as_deref().map(DisplayTzd); writeln!( f, - "LocalTimeType::new({}, {}, {})", + "crate::generated::new_local_time_type({}, {}, {})", ut_offset, is_dst, DisplayOption(time_zone_designation.as_ref()), @@ -117,7 +117,11 @@ impl fmt::Display for LeapSecond { unix_leap_time, correction, } = self; - writeln!(f, "LeapSecond::new({}, {})", unix_leap_time, correction)?; + writeln!( + f, + "crate::generated::new_leap_second({}, {})", + unix_leap_time, correction + )?; Ok(()) } } @@ -125,9 +129,9 @@ impl fmt::Display for LeapSecond { impl fmt::Display for TransitionRule { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - TransitionRule::Fixed(t) => writeln!(f, "TransitionRule::Fixed({})", Unwrap(t))?, + TransitionRule::Fixed(t) => writeln!(f, "TransitionRule::Fixed({})", t)?, TransitionRule::Alternate(t) => { - writeln!(f, "TransitionRule::Alternate({})", Unwrap(t))?; + writeln!(f, "TransitionRule::Alternate({})", t)?; }, } Ok(()) @@ -146,13 +150,8 @@ impl fmt::Display for AlternateTime { } = self; writeln!( f, - "AlternateTime::new({}, {}, {}, {}, {}, {})", - Unwrap(std), - Unwrap(dst), - dst_start, - dst_start_time, - dst_end, - dst_end_time, + "crate::generated::new_alternate_time({}, {}, {}, {}, {}, {})", + std, dst, dst_start, dst_start_time, dst_end, dst_end_time, ) } } @@ -164,67 +163,41 @@ impl fmt::Display for MonthWeekDay { week, week_day, } = self; - writeln!(f, "MonthWeekDay::new({}, {}, {})", month, week, week_day) + writeln!( + f, + "crate::generated::new_month_week_day({}, {}, {})", + month, week, week_day + ) } } impl fmt::Display for Julian0WithLeap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Julian0WithLeap::Julian0WithLeap(t) = self; - writeln!(f, "Julian0WithLeap::new({})", t) + writeln!(f, "crate::generated::new_julian0_with_leap({})", t) } } impl fmt::Display for Julian1WithoutLeap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Julian1WithoutLeap::Julian1WithoutLeap(t) = self; - writeln!(f, "Julian1WithoutLeap::new({})", t) + writeln!(f, "crate::generated::new_julian1_without_leap({})", t) } } impl fmt::Display for RuleDay { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - RuleDay::Julian0WithLeap(t) => writeln!(f, "RuleDay::Julian0WithLeap({})", Unwrap(t))?, - RuleDay::Julian1WithoutLeap(t) => { - writeln!(f, "RuleDay::Julian1WithoutLeap({})", Unwrap(t))? - }, + RuleDay::Julian0WithLeap(t) => writeln!(f, "RuleDay::Julian0WithLeap({})", t)?, + RuleDay::Julian1WithoutLeap(t) => writeln!(f, "RuleDay::Julian1WithoutLeap({})", t)?, RuleDay::MonthWeekDay(t) => { - writeln!(f, "RuleDay::MonthWeekDay({})", Unwrap(t))?; + writeln!(f, "RuleDay::MonthWeekDay({})", t)?; }, } Ok(()) } } -pub(crate) struct Unwrap<'a, T: fmt::Display>(pub(crate) &'a T); - -impl<'a, T: fmt::Display> fmt::Display for Unwrap<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, r#"crate::generated::unwrap!({})"#, &self.0) - } -} - -pub(crate) struct ToConst<'a, T>(pub(crate) &'a str, pub(crate) &'a T); - -impl<'a, T: fmt::Display> fmt::Display for ToConst<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "{{ const V: {} = {}; V }}", &self.0, self.1) - } -} - -pub(crate) struct UnwrapToConst<'a, T>(pub(crate) &'a str, pub(crate) &'a [T]); - -impl<'a, T: fmt::Display> fmt::Display for UnwrapToConst<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "{{ const V: [{}; {}] = [", &self.0, self.1.len())?; - for elem in self.1 { - writeln!(f, " {},", Unwrap(elem))?; - } - writeln!(f, "]; V }}") - } -} - pub(crate) struct DisplayVec<'a, T>(pub(crate) &'a [T]); impl<'a, T: fmt::Display> fmt::Display for DisplayVec<'a, T> { @@ -264,12 +237,11 @@ impl fmt::Display for TimeZone { leap_seconds, extra_rule, } = self; - let extra_rule = extra_rule.as_ref().map(|s| ToConst("TransitionRule", s)); writeln!( f, - "TimeZoneRef::<'static>::new(&{}, &{}, &{}, &{})", + "crate::generated::new_time_zone_ref(&{}, &{}, &{}, &{})", DisplayVec(transitions), - UnwrapToConst("LocalTimeType", local_time_types), + DisplayVec(local_time_types), DisplayVec(leap_seconds), DisplayOption(extra_rule.as_ref()), ) diff --git a/src/generated b/src/generated index 9a3d52b..59300e8 160000 --- a/src/generated +++ b/src/generated @@ -1 +1 @@ -Subproject commit 9a3d52ba7fe892ecd78d8cc1e29666350737f232 +Subproject commit 59300e84f423ede8b5062f585265e5c8ce908464 diff --git a/src/lib.rs b/src/lib.rs index d6d7533..12ea2d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,7 @@ //! Static time zone information for [tz-rs](https://crates.io/crates/tz-rs). //! //! This crate provides all time zones found in the [Time Zone Database](https://www.iana.org/time-zones), -//! currently in the version 2023b (released 2023-03-23). +//! currently in the version 2023c (released 2023-03-28). //! //! See the documentation for a full list the the contained time zones: //! diff --git a/src/test_by_name.rs b/src/test_by_name.rs index ed0a1d5..99af2c6 100644 --- a/src/test_by_name.rs +++ b/src/test_by_name.rs @@ -2,8 +2,8 @@ use crate::{time_zone, tz_by_name}; #[test] fn test_by_name() { - let _ = tz_by_name("Europe/Berlin").unwrap(); - let _ = tz_by_name("America/Dominica").unwrap(); + let _: tz::TimeZoneRef<'static> = tz_by_name("Europe/Berlin").unwrap(); + let _: tz::TimeZoneRef<'static> = tz_by_name("America/Dominica").unwrap(); } #[test] diff --git a/src/test_proptest.rs b/src/test_proptest.rs index 35fd4d8..02d2988 100644 --- a/src/test_proptest.rs +++ b/src/test_proptest.rs @@ -16,36 +16,36 @@ fn random_bytes(size: impl Into) -> impl Strategy> { #[proptest] fn test_short_ascii_string(#[strategy(ascii_string(0..8))] s: String) { - let _ = crate::tz_by_name(&s); - let _ = crate::raw_tz_by_name(&s); + let _: Option> = crate::tz_by_name(&s); + let _: Option<&[u8]> = crate::raw_tz_by_name(&s); } #[proptest] fn test_ascii_string(#[strategy(ascii_string(8..40))] s: String) { - let _ = crate::tz_by_name(&s); - let _ = crate::raw_tz_by_name(&s); + let _: Option> = crate::tz_by_name(&s); + let _: Option<&[u8]> = crate::raw_tz_by_name(&s); } #[proptest] fn test_short_string(#[strategy(random_string(0..8))] s: String) { - let _ = crate::tz_by_name(&s); - let _ = crate::raw_tz_by_name(&s); + let _: Option> = crate::tz_by_name(&s); + let _: Option<&[u8]> = crate::raw_tz_by_name(&s); } #[proptest] fn test_string(#[strategy(random_string(8..40))] s: String) { - let _ = crate::tz_by_name(&s); - let _ = crate::raw_tz_by_name(&s); + let _: Option> = crate::tz_by_name(&s); + let _: Option<&[u8]> = crate::raw_tz_by_name(&s); } #[proptest] fn test_short_bytes(#[strategy(random_bytes(0..8))] s: Vec) { - let _ = crate::tz_by_name(&s); - let _ = crate::raw_tz_by_name(&s); + let _: Option> = crate::tz_by_name(&s); + let _: Option<&[u8]> = crate::raw_tz_by_name(&s); } #[proptest] fn test_bytes(#[strategy(random_bytes(8..40))] s: Vec) { - let _ = crate::tz_by_name(&s); - let _ = crate::raw_tz_by_name(&s); + let _: Option> = crate::tz_by_name(&s); + let _: Option<&[u8]> = crate::raw_tz_by_name(&s); } diff --git a/tzdb.tar.lz.sha b/tzdb.tar.lz.sha index 950588a..195c931 100644 --- a/tzdb.tar.lz.sha +++ b/tzdb.tar.lz.sha @@ -1 +1 @@ -286ab1bf768dda48d4066d2477de0f3db9c26e55e26c1a4f33b450268255f28d57360bffe602a3bc29f8a281b7e0ff17880fe1d14914d6361f62abb7526e5081 tmp/tzdb-2023b.tar.lz +b59dbfc598b98f325797ff587bd2e8b27aadc52924eeb0b26cd18cdaca56224c436a20950bc73de9b9b46e98d640a24d8cb797a8f49ada15ea2f42a70a6efe22 tmp/tzdb-2023c.tar.lz