use crate::fields::{self, Field, FieldLength};
use crate::pattern::PatternLoadError;
use crate::provider::neo::*;
use crate::provider::time_zones::tz;
use core::fmt;
use icu_provider::prelude::*;
use yoke::Yokeable;
use super::UnstableSealed;
#[allow(missing_docs)]
pub trait DateTimeNamesMarker: UnstableSealed {
type YearNames: NamesContainer<YearNamesV1Marker, FieldLength>;
type MonthNames: NamesContainer<MonthNamesV1Marker, (fields::Month, FieldLength)>;
type WeekdayNames: NamesContainer<WeekdayNamesV1Marker, (fields::Weekday, FieldLength)>;
type DayPeriodNames: NamesContainer<DayPeriodNamesV1Marker, FieldLength>;
type ZoneEssentials: NamesContainer<tz::EssentialsV1Marker, ()>;
type ZoneLocations: NamesContainer<tz::LocationsV1Marker, ()>;
type ZoneGenericLong: NamesContainer<tz::MzGenericLongV1Marker, ()>;
type ZoneGenericShort: NamesContainer<tz::MzGenericShortV1Marker, ()>;
type ZoneSpecificLong: NamesContainer<tz::MzSpecificLongV1Marker, ()>;
type ZoneSpecificShort: NamesContainer<tz::MzSpecificShortV1Marker, ()>;
type MetazoneLookup: NamesContainer<tz::MzPeriodV1Marker, ()>;
}
#[allow(missing_docs)]
pub trait NamesContainer<M: DynamicDataMarker, Variables>: UnstableSealed
where
Variables: PartialEq + Copy + fmt::Debug,
{
type Container: MaybePayload<M, Variables> + fmt::Debug;
}
impl<M: DynamicDataMarker, Variables> NamesContainer<M, Variables> for ()
where
Variables: PartialEq + Copy + fmt::Debug,
{
type Container = ();
}
macro_rules! impl_holder_trait {
($marker:path) => {
impl UnstableSealed for $marker {}
impl<Variables> NamesContainer<$marker, Variables> for $marker
where
Variables: PartialEq + Copy + fmt::Debug,
{
type Container = DataPayloadWithVariables<$marker, Variables>;
}
};
}
impl_holder_trait!(YearNamesV1Marker);
impl_holder_trait!(MonthNamesV1Marker);
impl_holder_trait!(WeekdayNamesV1Marker);
impl_holder_trait!(DayPeriodNamesV1Marker);
impl_holder_trait!(tz::EssentialsV1Marker);
impl_holder_trait!(tz::LocationsV1Marker);
impl_holder_trait!(tz::MzGenericLongV1Marker);
impl_holder_trait!(tz::MzGenericShortV1Marker);
impl_holder_trait!(tz::MzSpecificLongV1Marker);
impl_holder_trait!(tz::MzSpecificShortV1Marker);
impl_holder_trait!(tz::MzPeriodV1Marker);
#[allow(missing_docs)]
#[derive(Debug)]
#[non_exhaustive]
pub enum MaybePayloadError {
TypeTooSpecific,
ConflictingField,
}
impl MaybePayloadError {
pub(crate) fn into_load_error(self, field: Field) -> PatternLoadError {
match self {
Self::TypeTooSpecific => PatternLoadError::TypeTooSpecific(field),
Self::ConflictingField => PatternLoadError::ConflictingField(field),
}
}
}
#[allow(missing_docs)]
pub trait MaybePayload<M: DynamicDataMarker, Variables>: UnstableSealed {
fn new_empty() -> Self;
fn load_put<P>(
&mut self,
provider: &P,
req: DataRequest,
variables: Variables,
) -> Result<Result<(), DataError>, MaybePayloadError>
where
P: BoundDataProvider<M> + ?Sized,
Self: Sized;
fn get(&self) -> DataPayloadWithVariablesBorrowed<M, Variables>;
}
pub struct DataPayloadWithVariables<M: DynamicDataMarker, Variables> {
inner: OptionalNames<Variables, DataPayload<M>>,
}
impl<M: DynamicDataMarker, Variables> UnstableSealed for DataPayloadWithVariables<M, Variables> {}
impl<M: DynamicDataMarker, Variables> fmt::Debug for DataPayloadWithVariables<M, Variables>
where
Variables: fmt::Debug,
DataPayload<M>: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<M: DynamicDataMarker, Variables> From<()> for DataPayloadWithVariables<M, Variables> {
#[inline]
fn from(_: ()) -> Self {
Self {
inner: OptionalNames::None,
}
}
}
#[allow(missing_docs)]
pub struct DataPayloadWithVariablesBorrowed<'data, M: DynamicDataMarker, Variables> {
pub(crate) inner: OptionalNames<Variables, &'data <M::DataStruct as Yokeable<'data>>::Output>,
}
impl<'data, M: DynamicDataMarker, Variables> fmt::Debug
for DataPayloadWithVariablesBorrowed<'data, M, Variables>
where
<M::DataStruct as Yokeable<'data>>::Output: fmt::Debug,
Variables: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(core::any::type_name::<Self>())
.field("inner", &self.inner)
.finish()
}
}
impl<M: DynamicDataMarker, Variables> MaybePayload<M, Variables>
for DataPayloadWithVariables<M, Variables>
where
Variables: PartialEq + Copy,
{
#[inline]
fn new_empty() -> Self {
Self {
inner: OptionalNames::None,
}
}
fn load_put<P>(
&mut self,
provider: &P,
req: DataRequest,
variables: Variables,
) -> Result<Result<(), DataError>, MaybePayloadError>
where
P: BoundDataProvider<M> + ?Sized,
Self: Sized,
{
let arg_variables = variables;
match &self.inner {
OptionalNames::SingleLength { variables, .. } if arg_variables == *variables => {
return Ok(Ok(()));
}
OptionalNames::SingleLength { .. } => {
return Err(MaybePayloadError::ConflictingField);
}
OptionalNames::None => (),
};
match provider.load_bound(req) {
Ok(response) => {
self.inner = OptionalNames::SingleLength {
payload: response.payload,
variables: arg_variables,
};
Ok(Ok(()))
}
Err(e) => Ok(Err(e)),
}
}
#[inline]
fn get(&self) -> DataPayloadWithVariablesBorrowed<M, Variables> {
DataPayloadWithVariablesBorrowed {
inner: self.inner.as_borrowed(),
}
}
}
impl<M: DynamicDataMarker, Variables> MaybePayload<M, Variables> for () {
#[inline]
fn new_empty() -> Self {}
#[inline]
fn load_put<P>(
&mut self,
_: &P,
_: DataRequest,
_: Variables,
) -> Result<Result<(), DataError>, MaybePayloadError>
where
P: BoundDataProvider<M> + ?Sized,
Self: Sized,
{
Err(MaybePayloadError::TypeTooSpecific)
}
#[allow(clippy::needless_lifetimes)] #[inline]
fn get(&self) -> DataPayloadWithVariablesBorrowed<M, Variables> {
DataPayloadWithVariablesBorrowed {
inner: OptionalNames::None,
}
}
}
#[derive(Debug, Copy, Clone)]
pub(crate) enum OptionalNames<Variables, Payload> {
None,
SingleLength {
variables: Variables,
payload: Payload,
},
}
impl<Variables, Payload> OptionalNames<Variables, Payload>
where
Variables: Copy + PartialEq,
Payload: Copy,
{
pub(crate) fn get_with_variables(&self, arg_variables: Variables) -> Option<Payload> {
match self {
Self::None => None,
Self::SingleLength { variables, payload } if arg_variables == *variables => {
Some(*payload)
}
_ => None,
}
}
}
impl<Payload> OptionalNames<(), Payload>
where
Payload: Copy,
{
pub(crate) fn get_option(&self) -> Option<Payload> {
match self {
Self::SingleLength {
variables: (),
payload,
} => Some(*payload),
_ => None,
}
}
}
impl<M: DynamicDataMarker, Variables> OptionalNames<Variables, DataPayload<M>>
where
Variables: Copy,
{
#[allow(clippy::needless_lifetimes)] #[inline]
pub(crate) fn as_borrowed<'a>(
&'a self,
) -> OptionalNames<Variables, &'a <M::DataStruct as Yokeable<'a>>::Output> {
match self {
Self::None => OptionalNames::None,
Self::SingleLength { variables, payload } => OptionalNames::SingleLength {
variables: *variables,
payload: payload.get(),
},
}
}
}
#[allow(missing_docs)]
pub trait DateTimeNamesFrom<M: DateTimeNamesMarker>: DateTimeNamesMarker {
fn map_year_names(
other: <M::YearNames as NamesContainer<YearNamesV1Marker, FieldLength>>::Container,
) -> <Self::YearNames as NamesContainer<YearNamesV1Marker, FieldLength>>::Container;
fn map_month_names(other: <M::MonthNames as NamesContainer<MonthNamesV1Marker, (fields::Month, FieldLength)>>::Container) -> <Self::MonthNames as NamesContainer<MonthNamesV1Marker, (fields::Month, FieldLength)>>::Container;
fn map_weekday_names(
other: <M::WeekdayNames as NamesContainer<
WeekdayNamesV1Marker,
(fields::Weekday, FieldLength),
>>::Container,
) -> <Self::WeekdayNames as NamesContainer<
WeekdayNamesV1Marker,
(fields::Weekday, FieldLength),
>>::Container;
fn map_day_period_names(
other: <M::DayPeriodNames as NamesContainer<DayPeriodNamesV1Marker, FieldLength>>::Container,
) -> <Self::DayPeriodNames as NamesContainer<DayPeriodNamesV1Marker, FieldLength>>::Container;
fn map_zone_essentials(
other: <M::ZoneEssentials as NamesContainer<tz::EssentialsV1Marker, ()>>::Container,
) -> <Self::ZoneEssentials as NamesContainer<tz::EssentialsV1Marker, ()>>::Container;
fn map_zone_locations(
other: <M::ZoneLocations as NamesContainer<tz::LocationsV1Marker, ()>>::Container,
) -> <Self::ZoneLocations as NamesContainer<tz::LocationsV1Marker, ()>>::Container;
fn map_zone_generic_long(
other: <M::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1Marker, ()>>::Container,
) -> <Self::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1Marker, ()>>::Container;
fn map_zone_generic_short(
other: <M::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1Marker, ()>>::Container,
) -> <Self::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1Marker, ()>>::Container;
fn map_zone_specific_long(
other: <M::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1Marker, ()>>::Container,
) -> <Self::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1Marker, ()>>::Container;
fn map_zone_specific_short(
other: <M::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1Marker, ()>>::Container,
) -> <Self::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1Marker, ()>>::Container;
fn map_metazone_lookup(
other: <M::MetazoneLookup as NamesContainer<tz::MzPeriodV1Marker, ()>>::Container,
) -> <Self::MetazoneLookup as NamesContainer<tz::MzPeriodV1Marker, ()>>::Container;
}
impl<M: DateTimeNamesMarker, T: DateTimeNamesMarker> DateTimeNamesFrom<M> for T
where
<Self::YearNames as NamesContainer<YearNamesV1Marker, FieldLength>>::Container: From<<M::YearNames as NamesContainer<YearNamesV1Marker, FieldLength>>::Container>,
<Self::MonthNames as NamesContainer<MonthNamesV1Marker, (fields::Month, FieldLength)>>::Container: From<<M::MonthNames as NamesContainer<MonthNamesV1Marker, (fields::Month, FieldLength)>>::Container>,
<Self::WeekdayNames as NamesContainer<WeekdayNamesV1Marker, (fields::Weekday, FieldLength)>>::Container: From<<M::WeekdayNames as NamesContainer<WeekdayNamesV1Marker, (fields::Weekday, FieldLength)>>::Container>,
<Self::DayPeriodNames as NamesContainer<DayPeriodNamesV1Marker, FieldLength>>::Container: From<<M::DayPeriodNames as NamesContainer<DayPeriodNamesV1Marker, FieldLength>>::Container>,
<Self::ZoneEssentials as NamesContainer<tz::EssentialsV1Marker, ()>>::Container: From<<M::ZoneEssentials as NamesContainer<tz::EssentialsV1Marker, ()>>::Container>,
<Self::ZoneLocations as NamesContainer<tz::LocationsV1Marker, ()>>::Container: From<<M::ZoneLocations as NamesContainer<tz::LocationsV1Marker, ()>>::Container>,
<Self::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1Marker, ()>>::Container: From<<M::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1Marker, ()>>::Container>,
<Self::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1Marker, ()>>::Container: From<<M::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1Marker, ()>>::Container>,
<Self::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1Marker, ()>>::Container: From<<M::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1Marker, ()>>::Container>,
<Self::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1Marker, ()>>::Container: From<<M::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1Marker, ()>>::Container>,
<Self::MetazoneLookup as NamesContainer<tz::MzPeriodV1Marker, ()>>::Container: From<<M::MetazoneLookup as NamesContainer<tz::MzPeriodV1Marker, ()>>::Container>,
{
#[inline]
fn map_year_names(other: <M::YearNames as NamesContainer<YearNamesV1Marker, FieldLength>>::Container) -> <Self::YearNames as NamesContainer<YearNamesV1Marker, FieldLength>>::Container {
other.into()
}
#[inline]
fn map_month_names(other: <M::MonthNames as NamesContainer<MonthNamesV1Marker, (fields::Month, FieldLength)>>::Container) -> <Self::MonthNames as NamesContainer<MonthNamesV1Marker, (fields::Month, FieldLength)>>::Container {
other.into()
}
#[inline]
fn map_weekday_names(other: <M::WeekdayNames as NamesContainer<WeekdayNamesV1Marker, (fields::Weekday, FieldLength)>>::Container) -> <Self::WeekdayNames as NamesContainer<WeekdayNamesV1Marker, (fields::Weekday, FieldLength)>>::Container {
other.into()
}
#[inline]
fn map_day_period_names(other: <M::DayPeriodNames as NamesContainer<DayPeriodNamesV1Marker, FieldLength>>::Container) -> <Self::DayPeriodNames as NamesContainer<DayPeriodNamesV1Marker, FieldLength>>::Container {
other.into()
}
#[inline]
fn map_zone_essentials(other: <M::ZoneEssentials as NamesContainer<tz::EssentialsV1Marker, ()>>::Container) -> <Self::ZoneEssentials as NamesContainer<tz::EssentialsV1Marker, ()>>::Container {
other.into()
}
#[inline]
fn map_zone_locations(other: <M::ZoneLocations as NamesContainer<tz::LocationsV1Marker, ()>>::Container) -> <Self::ZoneLocations as NamesContainer<tz::LocationsV1Marker, ()>>::Container {
other.into()
}
#[inline]
fn map_zone_generic_long(other: <M::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1Marker, ()>>::Container) -> <Self::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1Marker, ()>>::Container {
other.into()
}
#[inline]
fn map_zone_generic_short(other: <M::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1Marker, ()>>::Container) -> <Self::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1Marker, ()>>::Container {
other.into()
}
#[inline]
fn map_zone_specific_long(other: <M::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1Marker, ()>>::Container) -> <Self::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1Marker, ()>>::Container {
other.into()
}
#[inline]
fn map_zone_specific_short(other: <M::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1Marker, ()>>::Container) -> <Self::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1Marker, ()>>::Container {
other.into()
}
#[inline]
fn map_metazone_lookup(other: <M::MetazoneLookup as NamesContainer<tz::MzPeriodV1Marker, ()>>::Container) -> <Self::MetazoneLookup as NamesContainer<tz::MzPeriodV1Marker, ()>>::Container {
other.into()
}
}