use alloc::borrow::Cow;
use icu_pattern::{DoublePlaceholderPattern, SinglePlaceholderPattern};
use icu_provider::prelude::*;
use icu_time::{zone::TimeZoneVariant, TimeZone};
use zerovec::{ZeroMap, ZeroVec};
pub use icu_time::provider::MetazoneId;
pub(crate) mod tz {
pub(crate) use super::ExemplarCities;
pub(crate) use super::Locations;
pub(crate) use super::MetazoneGenericNames as MzGeneric;
pub(crate) use super::MetazoneSpecificNames as MzSpecific;
pub(crate) use super::TimeZoneEssentials as Essentials;
pub(crate) use super::TimezoneNamesCitiesOverrideV1 as CitiesOverrideV1;
pub(crate) use super::TimezoneNamesCitiesRootV1 as CitiesRootV1;
pub(crate) use super::TimezoneNamesEssentialsV1 as EssentialsV1;
pub(crate) use super::TimezoneNamesGenericLongV1 as MzGenericLongV1;
pub(crate) use super::TimezoneNamesGenericShortV1 as MzGenericShortV1;
pub(crate) use super::TimezoneNamesLocationsOverrideV1 as LocationsOverrideV1;
pub(crate) use super::TimezoneNamesLocationsRootV1 as LocationsRootV1;
pub(crate) use super::TimezoneNamesSpecificLongV1 as MzSpecificLongV1;
pub(crate) use super::TimezoneNamesSpecificShortV1 as MzSpecificShortV1;
pub(crate) use super::TimezoneNamesStandardLongV1 as MzStandardLongV1;
pub(crate) use icu_time::provider::TimezonePeriods as MzPeriod;
pub(crate) use icu_time::provider::TimezonePeriodsV1 as MzPeriodV1;
}
icu_provider::data_marker!(
TimezoneNamesEssentialsV1,
TimeZoneEssentials<'static>
);
icu_provider::data_marker!(
TimezoneNamesLocationsOverrideV1,
Locations<'static>
);
icu_provider::data_marker!(
TimezoneNamesLocationsRootV1,
Locations<'static>
);
icu_provider::data_marker!(
TimezoneNamesCitiesOverrideV1,
ExemplarCities<'static>
);
icu_provider::data_marker!(
TimezoneNamesCitiesRootV1,
ExemplarCities<'static>
);
icu_provider::data_marker!(
TimezoneNamesGenericLongV1,
MetazoneGenericNames<'static>,
has_checksum = true
);
icu_provider::data_marker!(
TimezoneNamesGenericShortV1,
MetazoneGenericNames<'static>,
has_checksum = true
);
icu_provider::data_marker!(
TimezoneNamesStandardLongV1,
MetazoneGenericNames<'static>,
has_checksum = true
);
icu_provider::data_marker!(
TimezoneNamesSpecificLongV1,
MetazoneSpecificNames<'static>,
has_checksum = true
);
icu_provider::data_marker!(
TimezoneNamesSpecificShortV1,
MetazoneSpecificNames<'static>,
has_checksum = true,
);
#[derive(PartialEq, Debug, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::time_zones))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[yoke(prove_covariance_manually)]
pub struct TimeZoneEssentials<'data> {
#[cfg_attr(feature = "serde", serde(borrow,))]
pub offset_separator: Cow<'data, str>,
#[cfg_attr(
feature = "serde",
serde(
borrow,
deserialize_with = "icu_pattern::deserialize_borrowed_cow::<icu_pattern::SinglePlaceholder, _>"
)
)]
pub offset_pattern: Cow<'data, SinglePlaceholderPattern>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub offset_zero: Cow<'data, str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub offset_unknown: Cow<'data, str>,
}
icu_provider::data_struct!(
TimeZoneEssentials<'_>,
#[cfg(feature = "datagen")]
);
#[derive(PartialEq, Debug, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::time_zones))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[yoke(prove_covariance_manually)]
pub struct Locations<'data> {
#[cfg_attr(feature = "serde", serde(borrow))]
pub locations: ZeroMap<'data, TimeZone, str>,
#[cfg_attr(
feature = "serde",
serde(
borrow,
deserialize_with = "icu_pattern::deserialize_borrowed_cow::<icu_pattern::SinglePlaceholder, _>"
)
)]
pub pattern_generic: Cow<'data, SinglePlaceholderPattern>,
#[cfg_attr(
feature = "serde",
serde(
borrow,
deserialize_with = "icu_pattern::deserialize_borrowed_cow::<icu_pattern::SinglePlaceholder, _>"
)
)]
pub pattern_standard: Cow<'data, SinglePlaceholderPattern>,
#[cfg_attr(
feature = "serde",
serde(
borrow,
deserialize_with = "icu_pattern::deserialize_borrowed_cow::<icu_pattern::SinglePlaceholder, _>"
)
)]
pub pattern_daylight: Cow<'data, SinglePlaceholderPattern>,
#[cfg_attr(
feature = "serde",
serde(
borrow,
deserialize_with = "icu_pattern::deserialize_borrowed_cow::<icu_pattern::DoublePlaceholder, _>"
)
)]
pub pattern_partial_location: Cow<'data, DoublePlaceholderPattern>,
}
icu_provider::data_struct!(
Locations<'_>,
#[cfg(feature = "datagen")]
);
#[derive(PartialEq, Debug, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::time_zones))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[yoke(prove_covariance_manually)]
pub struct ExemplarCities<'data> {
#[cfg_attr(feature = "serde", serde(borrow))]
pub exemplars: ZeroMap<'data, TimeZone, str>,
}
icu_provider::data_struct!(
ExemplarCities<'_>,
#[cfg(feature = "datagen")]
);
#[derive(PartialEq, Debug, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::time_zones))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[yoke(prove_covariance_manually)]
pub struct MetazoneGenericNames<'data> {
#[cfg_attr(feature = "serde", serde(borrow))]
pub defaults: ZeroMap<'data, MetazoneId, str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub overrides: ZeroMap<'data, TimeZone, str>,
}
icu_provider::data_struct!(
MetazoneGenericNames<'_>,
#[cfg(feature = "datagen")]
);
#[derive(PartialEq, Debug, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::time_zones))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[yoke(prove_covariance_manually)]
pub struct MetazoneSpecificNames<'data> {
#[cfg_attr(feature = "serde", serde(borrow))]
pub defaults: ZeroMap<'data, (MetazoneId, TimeZoneVariant), str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub overrides: ZeroMap<'data, (TimeZone, TimeZoneVariant), str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub use_standard: ZeroVec<'data, MetazoneId>,
}
icu_provider::data_struct!(
MetazoneSpecificNames<'_>,
#[cfg(feature = "datagen")]
);
#[cfg(feature = "serde")]
pub(crate) mod legacy {
use super::*;
use icu_time::zone::ZoneNameTimestamp;
use zerovec::ule::NichedOption;
use zerovec::ZeroMap2d;
icu_provider::data_marker!(
TimezoneMetazonePeriodsV1,
MetazonePeriod<'static>,
is_singleton = true,
has_checksum = true
);
#[derive(PartialEq, Debug, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[yoke(prove_covariance_manually)]
#[allow(dead_code, reason = "We construct this struct through serde impls")]
pub struct MetazonePeriod<'data> {
#[cfg_attr(feature = "serde", serde(borrow))]
pub list: ZeroMap2d<'data, TimeZone, ZoneNameTimestamp, NichedOption<MetazoneId, 1>>,
}
icu_provider::data_struct!(
MetazonePeriod<'_>,
#[cfg(feature = "datagen")]
);
#[inline(never)] pub(crate) fn metazone_timezone_compat(
provider: &impl BufferProvider,
req: DataRequest<'_>,
) -> Result<DataResponse<icu_time::provider::TimezonePeriodsV1>, DataError> {
use alloc::vec::Vec;
use icu_time::provider::Timestamp24;
use icu_time::provider::TimezonePeriods;
use zerotrie::ZeroTrieSimpleAscii;
use zerovec::ule::vartuple::VarTuple;
use zerovec::ule::AsULE;
use zerovec::vecs::VarZeroVecOwned;
let DataResponse::<TimezoneMetazonePeriodsV1> {
payload: old_payload,
metadata,
} = provider.as_deserializing().load(req)?;
let index = ZeroTrieSimpleAscii::<Vec<u8>>::from_iter(
old_payload
.get()
.list
.iter0()
.enumerate()
.map(|(i, v)| (v.key0().as_str(), i)),
)
.convert_store();
let mut list = VarZeroVecOwned::new();
for ps in old_payload.get().list.iter0() {
let mut cursor = ps.into_iter1_copied();
let Some((_, mz)) = cursor.next() else {
continue; };
let rest = cursor
.map(move |(&t, mz)| (Timestamp24(ZoneNameTimestamp::from_unaligned(t)), 0, mz))
.collect::<ZeroVec<_>>();
let rest = VarTuple {
sized: (0, mz),
variable: rest.as_slice(),
};
list.push(&rest);
}
Ok(DataResponse {
payload: DataPayload::from_owned(TimezonePeriods {
index,
list: list.into(),
offsets: ZeroVec::from(alloc::vec![Default::default()]),
}),
metadata,
})
}
#[test]
fn test_metazone_timezone_compat() {
let converted = metazone_timezone_compat(
&icu_provider_blob::BlobDataProvider::try_new_from_static_blob(
include_bytes!("../../tests/data/metazone_periods_old.postcard"),
)
.unwrap(),
Default::default(),
)
.unwrap()
.payload;
let tz = TimeZone::from_iana_id("Antarctica/Casey");
for t in [
ZoneNameTimestamp::from_epoch_seconds(0),
ZoneNameTimestamp::from_epoch_seconds(1255802400),
ZoneNameTimestamp::from_epoch_seconds(1267714800),
ZoneNameTimestamp::from_epoch_seconds(1319738400),
ZoneNameTimestamp::from_epoch_seconds(1329843600),
ZoneNameTimestamp::from_epoch_seconds(1477065600),
ZoneNameTimestamp::from_epoch_seconds(1520701200),
ZoneNameTimestamp::from_epoch_seconds(1538856000),
ZoneNameTimestamp::from_epoch_seconds(1552752000),
ZoneNameTimestamp::from_epoch_seconds(1570129200),
ZoneNameTimestamp::from_epoch_seconds(1583596800),
ZoneNameTimestamp::from_epoch_seconds(1615640400),
ZoneNameTimestamp::from_epoch_seconds(1647090000),
ZoneNameTimestamp::from_epoch_seconds(1678291200),
] {
assert_eq!(
converted
.get()
.get(tz, t)
.unwrap()
.1
.map(|mz| match mz.id.get() {
22 => 21,
31 => 30,
_ => unreachable!(),
}),
icu_time::provider::Baked::SINGLETON_TIMEZONE_PERIODS_V1
.get(tz, t)
.unwrap()
.1
.map(|mz| mz.id.get()),
"{t:?}",
);
}
}
}