use crate::raw::neo::RawOptions;
use crate::scaffold::GetField;
use crate::{fields, fieldsets, Length};
use icu_provider::prelude::*;
#[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 {
Z(fieldsets::Z),
O(fieldsets::O),
V(fieldsets::V),
L(fieldsets::L),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ZoneStyle {
Z,
O,
V,
L,
}
#[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()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum CompositeFieldSet {
Date(DateFieldSet),
CalendarPeriod(CalendarPeriodFieldSet),
Time(TimeFieldSet),
Zone(ZoneFieldSet),
DateTime(DateAndTimeFieldSet),
DateZone(DateFieldSet, ZoneStyle),
TimeZone(TimeFieldSet, ZoneStyle),
DateTimeZone(DateAndTimeFieldSet, ZoneStyle),
}
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) -> (fields::TimeZone, fields::FieldLength) {
match self {
$(
Self::$variant(variant) => variant.to_field(),
)+
}
}
}
};
(@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,
})
}
#[cfg(all(feature = "serde", feature = "experimental"))]
pub(crate) fn from_date_field_set_with_raw_options(date_field_set: DateFieldSet, options: RawOptions) -> Self {
match date_field_set {
$(
DateFieldSet::$d_variant(_) => Self::$variant(fieldsets::$variant::from_raw_options(options)),
)+
}
}
}
};
}
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<fields::Hour>,
) -> &'static DataMarkerAttributes {
use fields::Hour::*;
match hour_cycle {
None => Self::ATTR_T,
Some(H11 | H12) => Self::ATTR_T12,
Some(H23 | H24) => Self::ATTR_T24,
}
}
}
impl_attrs! {
@zone,
ZoneFieldSet,
[
Z,
O,
V,
L,
]
}
impl ZoneFieldSet {
pub(crate) fn from_time_zone_style_and_length(style: ZoneStyle, length: Length) -> Self {
match style {
ZoneStyle::Z => Self::Z(fieldsets::Z::with_length(length)),
ZoneStyle::O => Self::O(fieldsets::O::with_length(length)),
ZoneStyle::V => Self::V(fieldsets::V::with_length(length)),
ZoneStyle::L => Self::L(fieldsets::L::with_length(length)),
}
}
}
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,
}
}
}