use crate::fieldsets::{builder, Combo};
use crate::raw::neo::RawOptions;
use crate::scaffold::GetField;
use crate::{fieldsets, provider};
use icu_provider::prelude::*;
#[cfg(doc)]
use crate::input::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum DateFieldSet {
D(fieldsets::D),
MD(fieldsets::MD),
YMD(fieldsets::YMD),
DE(fieldsets::DE),
MDE(fieldsets::MDE),
YMDE(fieldsets::YMDE),
E(fieldsets::E),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum CalendarPeriodFieldSet {
M(fieldsets::M),
YM(fieldsets::YM),
Y(fieldsets::Y),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum TimeFieldSet {
T(fieldsets::T),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ZoneFieldSet {
SpecificLong(fieldsets::zone::SpecificLong),
SpecificShort(fieldsets::zone::SpecificShort),
LocalizedOffsetLong(fieldsets::zone::LocalizedOffsetLong),
LocalizedOffsetShort(fieldsets::zone::LocalizedOffsetShort),
GenericLong(fieldsets::zone::GenericLong),
GenericShort(fieldsets::zone::GenericShort),
Location(fieldsets::zone::Location),
ExemplarCity(fieldsets::zone::ExemplarCity),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum DateAndTimeFieldSet {
DT(fieldsets::DT),
MDT(fieldsets::MDT),
YMDT(fieldsets::YMDT),
DET(fieldsets::DET),
MDET(fieldsets::MDET),
YMDET(fieldsets::YMDET),
ET(fieldsets::ET),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum CompositeDateTimeFieldSet {
Date(DateFieldSet),
CalendarPeriod(CalendarPeriodFieldSet),
Time(TimeFieldSet),
DateTime(DateAndTimeFieldSet),
}
impl CompositeDateTimeFieldSet {
pub fn try_from_composite_field_set(field_set: CompositeFieldSet) -> Option<Self> {
match field_set {
CompositeFieldSet::Date(v) => Some(Self::Date(v)),
CompositeFieldSet::CalendarPeriod(v) => Some(Self::CalendarPeriod(v)),
CompositeFieldSet::Time(v) => Some(Self::Time(v)),
CompositeFieldSet::Zone(_) => None,
CompositeFieldSet::DateTime(v) => Some(Self::DateTime(v)),
CompositeFieldSet::DateZone(_) => None,
CompositeFieldSet::TimeZone(_) => None,
CompositeFieldSet::DateTimeZone(_) => None,
}
}
pub fn to_composite_field_set(self) -> CompositeFieldSet {
match self {
Self::Date(v) => CompositeFieldSet::Date(v),
Self::CalendarPeriod(v) => CompositeFieldSet::CalendarPeriod(v),
Self::Time(v) => CompositeFieldSet::Time(v),
Self::DateTime(v) => CompositeFieldSet::DateTime(v),
}
}
}
impl GetField<CompositeFieldSet> for CompositeDateTimeFieldSet {
fn get_field(&self) -> CompositeFieldSet {
self.to_composite_field_set()
}
}
pub type ZonedDateFieldSet = Combo<DateFieldSet, ZoneFieldSet>;
pub type ZonedTimeFieldSet = Combo<TimeFieldSet, ZoneFieldSet>;
pub type ZonedDateAndTimeFieldSet = Combo<DateAndTimeFieldSet, ZoneFieldSet>;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum CompositeFieldSet {
Date(DateFieldSet),
CalendarPeriod(CalendarPeriodFieldSet),
Time(TimeFieldSet),
Zone(ZoneFieldSet),
DateTime(DateAndTimeFieldSet),
DateZone(ZonedDateFieldSet),
TimeZone(ZonedTimeFieldSet),
DateTimeZone(ZonedDateAndTimeFieldSet),
}
macro_rules! first {
($first:literal, $($remainder:literal,)*) => {
$first
};
}
macro_rules! impl_attrs {
(@attrs, $type:path, [$(($attr_var:ident, $str_var:ident, $value:literal),)+]) => {
impl $type {
$(
const $attr_var: &'static DataMarkerAttributes = DataMarkerAttributes::from_str_or_panic($value);
)+
#[doc = concat!("use icu::datetime::fieldsets::enums::", stringify!($type), " as FS;")]
#[doc = concat!(" &DataMarkerAttributes::from_str_or_panic(\"", first!($($value,)*), "\")")]
pub const ALL_DATA_MARKER_ATTRIBUTES: &'static [&'static DataMarkerAttributes] = &[
$(
Self::$attr_var,
)+
];
}
};
(@id_str, $type:path, [$(($variant:ident, $attr_var:ident)),+,]) => {
impl $type {
pub(crate) const fn id_str(self) -> &'static DataMarkerAttributes {
match self {
$(
Self::$variant(_) => Self::$attr_var,
)+
}
}
}
};
(@to_raw_options, $type:path, [$($variant:ident),+,]) => {
impl $type {
pub(crate) fn to_raw_options(self) -> RawOptions {
match self {
$(
Self::$variant(variant) => variant.to_raw_options(),
)+
}
}
}
};
(@composite, $type:path, $variant:ident) => {
impl $type {
#[inline]
pub(crate) fn to_enum(self) -> $type {
self
}
}
impl GetField<CompositeFieldSet> for $type {
#[inline]
fn get_field(&self) -> CompositeFieldSet {
CompositeFieldSet::$variant(self.to_enum())
}
}
};
(@date, $type:path, [$(($variant:ident, $attr_var:ident, $str_var:ident, $value:literal)),+,]) => {
impl_attrs! { @attrs, $type, [$(($attr_var, $str_var, $value)),+,] }
impl_attrs! { @id_str, $type, [$(($variant, $attr_var)),+,] }
impl_attrs! { @to_raw_options, $type, [$($variant),+,] }
impl_attrs! { @composite, $type, Date }
};
(@calendar_period, $type:path, [$(($variant:ident, $attr_var:ident, $str_var:ident, $value:literal)),+,]) => {
impl_attrs! { @attrs, $type, [$(($attr_var, $str_var, $value)),+,] }
impl_attrs! { @to_raw_options, $type, [$($variant),+,] }
impl_attrs! { @composite, $type, CalendarPeriod }
impl_attrs! { @id_str, $type, [$(($variant, $attr_var)),+,] }
};
(@time, $type:path, [$(($attr_var:ident, $str_var:ident, $value:literal)),+,]) => {
impl_attrs! { @attrs, $type, [$(($attr_var, $str_var, $value)),+,] }
impl_attrs! { @to_raw_options, $type, [T,] }
impl_attrs! { @composite, $type, Time }
};
(@zone, $type:path, [$($variant:ident),+,]) => {
impl_attrs! { @composite, $type, Zone }
impl $type {
pub(crate) fn to_field(self) -> (provider::fields::TimeZone, provider::fields::FieldLength) {
match self {
$(
Self::$variant(variant) => variant.to_field(),
)+
}
}
pub(crate) fn to_zone_style(self) -> builder::ZoneStyle {
match self {
$(
Self::$variant(_) => builder::ZoneStyle::$variant,
)+
}
}
}
};
(@datetime, $type:path, [$(($d_variant:ident, $variant:ident)),+,]) => {
impl_attrs! { @to_raw_options, $type, [$($variant),+,] }
impl_attrs! { @composite, $type, DateTime }
impl $type {
pub(crate) fn to_date_field_set(self) -> DateFieldSet {
match self {
$(
Self::$variant(variant) => DateFieldSet::$d_variant(variant.to_date_field_set()),
)+
}
}
pub(crate) fn to_time_field_set(self) -> TimeFieldSet {
let (length, time_precision, alignment) = match self {
$(
Self::$variant(variant) => (variant.length, variant.time_precision, variant.alignment),
)+
};
TimeFieldSet::T(fieldsets::T {
length,
time_precision,
alignment,
})
}
}
};
}
impl_attrs! {
@date,
DateFieldSet,
[
(D, ATTR_D, STR_D, "d"),
(MD, ATTR_MD, STR_MD, "m0d"),
(YMD, ATTR_YMD, STR_YMD, "ym0d"),
(DE, ATTR_DE, STR_DE, "de"),
(MDE, ATTR_MDE, STR_MDE, "m0de"),
(YMDE, ATTR_YMDE, STR_YMDE, "ym0de"),
(E, ATTR_E, STR_E, "e"),
]
}
impl_attrs! {
@calendar_period,
CalendarPeriodFieldSet,
[
(M, ATTR_M, STR_M, "m0"),
(YM, ATTR_YM, STR_YM, "ym0"),
(Y, ATTR_Y, STR_Y, "y"),
]
}
impl_attrs! {
@time,
TimeFieldSet,
[
(ATTR_T, STR_T, "j"),
(ATTR_T12, STR_T12, "h"),
(ATTR_T24, STR_T24, "h0"),
]
}
impl TimeFieldSet {
pub(crate) const fn id_str_for_hour_cycle(
self,
hour_cycle: Option<provider::fields::Hour>,
) -> &'static DataMarkerAttributes {
use provider::fields::Hour::*;
match hour_cycle {
None => Self::ATTR_T,
Some(H11 | H12) => Self::ATTR_T12,
Some(H23) => Self::ATTR_T24,
}
}
}
impl_attrs! {
@zone,
ZoneFieldSet,
[
SpecificLong,
SpecificShort,
LocalizedOffsetLong,
LocalizedOffsetShort,
GenericLong,
GenericShort,
Location,
ExemplarCity,
]
}
impl_attrs! {
@attrs,
DateAndTimeFieldSet,
[
(ATTR_ET, STR_ET, "ej"),
]
}
impl_attrs! {
@datetime,
DateAndTimeFieldSet,
[
(D, DT),
(MD, MDT),
(YMD, YMDT),
(DE, DET),
(MDE, MDET),
(YMDE, YMDET),
(E, ET),
]
}
impl DateAndTimeFieldSet {
pub(crate) const fn id_str(self) -> Option<&'static DataMarkerAttributes> {
match self {
DateAndTimeFieldSet::ET(_) => Some(Self::ATTR_ET),
_ => None,
}
}
}