Skip to main content

time/format_description/parse/
format_item.rs

1//! Typed, validated representation of a parsed format description.
2
3use alloc::borrow::ToOwned as _;
4use core::num::NonZero;
5use core::str::{self, FromStr};
6
7use super::lexer_ast::Modifier;
8use super::{Error, OptionExt as _, Span, Spanned, SpannedValue as _, unused};
9use crate::error::InvalidFormatDescription;
10use crate::format_description::__private::FormatDescriptionV3Inner;
11use crate::hint;
12use crate::internal_macros::{bug, try_likely_ok};
13
14macro_rules! parse_modifiers {
15    ($version:expr, $modifiers:expr, struct { $($field:ident : $modifier:ident),* $(,)? }) => {
16        'block: {
17            struct Parsed {
18                $($field: Option<Spanned<<$modifier as ModifierValue>::Type>>),*
19            }
20
21            let mut parsed = Parsed {
22                $($field: None),*
23            };
24
25            for modifier in $modifiers {
26                $(if ident_eq::<VERSION>(&modifier.key, stringify!($field)) {
27                    hint::cold_path();
28                    if version!(3..) && parsed.$field.is_some() {
29                        break 'block Err(Error {
30                            _inner: unused(modifier.key_span().error("duplicate modifier key")),
31                            public: InvalidFormatDescription::DuplicateModifier {
32                                name: stringify!($field),
33                                index: modifier.key.location.byte as usize,
34                            }
35                        });
36                    }
37                    match <$modifier>::from_modifier_value::<VERSION>(
38                        || modifier.value_span(),
39                        modifier.value,
40                    ) {
41                        Ok(value) => {
42                            parsed.$field = Some(
43                                <<$modifier as ModifierValue>::Type>::from(value)
44                                    .spanned(modifier.value_span())
45                            )
46                        },
47                        Err(err) => {
48                            hint::cold_path();
49                            break 'block Err(err)
50                        },
51                    }
52                    continue;
53                })*
54
55                hint::cold_path();
56                break 'block Err(Error {
57                    _inner: unused(modifier.key_span().error("invalid modifier key")),
58                    public: InvalidFormatDescription::InvalidModifier {
59                        value: (*modifier.key).to_owned(),
60                        index: modifier.key.location.byte as usize,
61                    }
62                });
63            }
64
65            Ok(parsed)
66        }
67    };
68}
69
70#[inline]
71pub(super) fn ident_eq<const VERSION: u8>(provided: &str, expected: &str) -> bool {
72    const {
        if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                    1..=3 => true,
                    _ => false,
                } {
            {
                ::core::panicking::panic_fmt(format_args!("invalid version provided"));
            }
        };
    };assert_version!();
73    if const {

        #[allow(non_exhaustive_omitted_patterns)]
        match VERSION { 3.. => true, _ => false, }
    }version!(3..) {
74        provided == expected
75    } else {
76        provided.len() == expected.len()
77            && core::iter::zip(provided.bytes(), expected.bytes())
78                .all(|(p, e)| p.to_ascii_lowercase() == e)
79    }
80}
81
82pub(super) fn parse_optional_format_modifier<const VERSION: u8>(
83    modifiers: &[Modifier<'_>],
84) -> Result<Spanned<bool>, Error> {
85    let modifiers = 'block:
    {
    struct Parsed {
        format: Option<Spanned<<OptionalFormat as ModifierValue>::Type>>,
    }
    let mut parsed = Parsed { format: None };
    for modifier in modifiers {
        if ident_eq::<VERSION>(&modifier.key, "format") {
            hint::cold_path();
            if const {

                            #[allow(non_exhaustive_omitted_patterns)]
                            match VERSION { 3.. => true, _ => false, }
                        } && parsed.format.is_some() {
                break 'block
                    Err(Error {
                            _inner: unused(modifier.key_span().error("duplicate modifier key")),
                            public: InvalidFormatDescription::DuplicateModifier {
                                name: "format",
                                index: modifier.key.location.byte as usize,
                            },
                        });
            }
            match <OptionalFormat>::from_modifier_value::<VERSION>(||
                        modifier.value_span(), modifier.value) {
                Ok(value) => {
                    parsed.format =
                        Some(<<OptionalFormat as
                                        ModifierValue>::Type>::from(value).spanned(modifier.value_span()))
                }
                Err(err) => { hint::cold_path(); break 'block Err(err) }
            }
            continue;
        }
        hint::cold_path();
        break 'block
            Err(Error {
                    _inner: unused(modifier.key_span().error("invalid modifier key")),
                    public: InvalidFormatDescription::InvalidModifier {
                        value: (*modifier.key).to_owned(),
                        index: modifier.key.location.byte as usize,
                    },
                });
    }
    Ok(parsed)
}parse_modifiers!(VERSION, modifiers, struct {
86        format: OptionalFormat,
87    })?;
88
89    Ok(modifiers.format.transpose().map(|val| val.unwrap_or(true)))
90}
91
92/// Declare the `Component` struct.
93macro_rules! component_definition {
94    (@if_required required then { $($then:tt)* } $(else { $($else:tt)* })?) => { $($then)* };
95    (@if_required then { $($then:tt)* } $(else { $($else:tt)* })?) => { $($($else)*)? };
96    (@if_from_str from_str then { $($then:tt)* } $(else { $($else:tt)* })?) => { $($then)* };
97    (@if_from_str then { $($then:tt)* } $(else { $($else:tt)* })?) => { $($($else)*)? };
98    (@if_year "year" $($then:tt)*) => { $($then)* };
99    (@if_year $lit:tt $($then:tt)*) => {};
100
101    ($vis:vis enum $name:ident {$(
102        $variant:ident = $parse_variant:tt {$(
103            $(#[$required:tt])?
104            $field:ident = $parse_field:literal:
105            Option<$(#[$from_str:tt])? $field_type:ty>
106        ),* $(,)?}
107    ),* $(,)?}) => {
108        $vis enum $name {
109            $($variant($variant),)*
110        }
111
112        $($vis struct $variant {
113            $($field: Spanned<Option<$field_type>>),*
114        })*
115
116        $(impl $variant {
117            /// Parse the component from the AST, given its modifiers.
118            #[inline]
119            fn with_modifiers<const VERSION: u8>(
120                modifiers: &[Modifier<'_>],
121                _component_span: Span,
122            ) -> Result<Self, Error>
123            {
124                assert_version!();
125
126                // rustc will complain if the modifier is empty.
127                #[allow(unused_mut)]
128                let mut this = Self {
129                    $($field: None.spanned(Span::DUMMY)),*
130                };
131
132                for modifier in modifiers {
133                    $(if ident_eq::<VERSION>(&modifier.key, $parse_field) {
134                        if version!(3..) && this.$field.is_some() {
135                            hint::cold_path();
136                            return Err(Error {
137                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
138                                public: InvalidFormatDescription::DuplicateModifier {
139                                    name: stringify!($field),
140                                    index: modifier.key.location.byte as usize,
141                                }
142                            });
143                        }
144                        this.$field = Some(
145                            component_definition!(@if_from_str $($from_str)?
146                                then {
147                                    parse_from_modifier_value::<$field_type>(
148                                        || modifier.value_span(),
149                                        modifier.value,
150                                    )?
151                                } else {
152                                    <$field_type>::from_modifier_value::<VERSION>(
153                                        || modifier.value_span(),
154                                        modifier.value,
155                                    )?
156                                }
157                            )
158                        ).spanned(modifier.key_value_span());
159                        continue;
160                    })*
161
162                    hint::cold_path();
163                    return Err(Error {
164                        _inner: unused(modifier.key_span().error("invalid modifier key")),
165                        public: InvalidFormatDescription::InvalidModifier {
166                            value: (*modifier.key).to_owned(),
167                            index: modifier.key.location.byte as usize,
168                        }
169                    });
170                }
171
172                $(component_definition! { @if_required $($required)? then {
173                    if this.$field.is_none() {
174                        hint::cold_path();
175                        return Err(Error {
176                            _inner: unused(_component_span.error("missing required modifier")),
177                            public:
178                                InvalidFormatDescription::MissingRequiredModifier {
179                                    name: $parse_field,
180                                    index: _component_span.start.byte as usize,
181                                }
182                        });
183                    }
184                }})*
185
186                Ok(this)
187            }
188        })*
189
190        /// Parse a component from the AST, given its name and modifiers.
191        #[inline]
192        pub(super) fn component_from_ast<const VERSION: u8>(
193            name: &Spanned<&str>,
194            modifiers: &[Modifier<'_>],
195        ) -> Result<AstComponent, Error> {
196            assert_version!();
197
198            $(if ident_eq::<VERSION>(&name, $parse_variant) {
199                #[allow(unused_mut)] // only used for some variants
200                let mut component = AstComponent::$variant(
201                    try_likely_ok!($variant::with_modifiers::<VERSION>(&modifiers, name.span))
202                );
203                component_definition!(@if_year $parse_variant
204                    #[cfg(feature = "large-dates")]
205                    if version!(3..)
206                        && let AstComponent::Year(y) = &mut component
207                        && y.range.value.is_none()
208                    {
209                        y.range = Some(YearRange::Standard).spanned(Span::DUMMY);
210                    }
211                );
212                return Ok(component);
213            })*
214
215            hint::cold_path();
216            Err(Error {
217                _inner: unused(name.span.error("invalid component")),
218                public: InvalidFormatDescription::InvalidComponentName {
219                    name: (**name).to_owned(),
220                    index: name.span.start.byte as usize,
221                },
222            })
223        }
224    }
225}
226
227// Keep in alphabetical order.
228pub(super) enum AstComponent {
    Day(Day),
    End(End),
    Hour(Hour),
    Ignore(Ignore),
    Minute(Minute),
    Month(Month),
    OffsetHour(OffsetHour),
    OffsetMinute(OffsetMinute),
    OffsetSecond(OffsetSecond),
    Ordinal(Ordinal),
    Period(Period),
    Second(Second),
    Subsecond(Subsecond),
    UnixTimestamp(UnixTimestamp),
    Weekday(Weekday),
    WeekNumber(WeekNumber),
    Year(Year),
}
pub(super) struct Day {
    padding: Spanned<Option<Padding>>,
}
pub(super) struct End {
    trailing_input: Spanned<Option<TrailingInput>>,
}
pub(super) struct Hour {
    padding: Spanned<Option<Padding>>,
    base: Spanned<Option<HourBase>>,
}
pub(super) struct Ignore {
    count: Spanned<Option<NonZero<u16>>>,
}
pub(super) struct Minute {
    padding: Spanned<Option<Padding>>,
}
pub(super) struct Month {
    padding: Spanned<Option<Padding>>,
    repr: Spanned<Option<MonthRepr>>,
    case_sensitive: Spanned<Option<MonthCaseSensitive>>,
}
pub(super) struct OffsetHour {
    sign_behavior: Spanned<Option<SignBehavior>>,
    padding: Spanned<Option<Padding>>,
}
pub(super) struct OffsetMinute {
    padding: Spanned<Option<Padding>>,
}
pub(super) struct OffsetSecond {
    padding: Spanned<Option<Padding>>,
}
pub(super) struct Ordinal {
    padding: Spanned<Option<Padding>>,
}
pub(super) struct Period {
    case: Spanned<Option<PeriodCase>>,
    case_sensitive: Spanned<Option<PeriodCaseSensitive>>,
}
pub(super) struct Second {
    padding: Spanned<Option<Padding>>,
}
pub(super) struct Subsecond {
    digits: Spanned<Option<SubsecondDigits>>,
}
pub(super) struct UnixTimestamp {
    precision: Spanned<Option<UnixTimestampPrecision>>,
    sign_behavior: Spanned<Option<SignBehavior>>,
}
pub(super) struct Weekday {
    repr: Spanned<Option<WeekdayRepr>>,
    one_indexed: Spanned<Option<WeekdayOneIndexed>>,
    case_sensitive: Spanned<Option<WeekdayCaseSensitive>>,
}
pub(super) struct WeekNumber {
    padding: Spanned<Option<Padding>>,
    repr: Spanned<Option<WeekNumberRepr>>,
}
pub(super) struct Year {
    padding: Spanned<Option<Padding>>,
    repr: Spanned<Option<YearRepr>>,
    range: Spanned<Option<YearRange>>,
    base: Spanned<Option<YearBase>>,
    sign_behavior: Spanned<Option<SignBehavior>>,
}
impl Day {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this = Self { padding: None.spanned(Span::DUMMY) };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl End {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this = Self { trailing_input: None.spanned(Span::DUMMY) };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "trailing_input") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.trailing_input.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "trailing_input",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.trailing_input =
                    Some(<TrailingInput>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Hour {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this =
            Self {
                padding: None.spanned(Span::DUMMY),
                base: None.spanned(Span::DUMMY),
            };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "repr") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.base.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "base",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.base =
                    Some(<HourBase>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Ignore {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this = Self { count: None.spanned(Span::DUMMY) };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "count") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.count.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "count",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.count =
                    Some(parse_from_modifier_value::<NonZero<u16>>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        if this.count.is_none() {
            hint::cold_path();
            return Err(Error {
                        _inner: unused(_component_span.error("missing required modifier")),
                        public: InvalidFormatDescription::MissingRequiredModifier {
                            name: "count",
                            index: _component_span.start.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Minute {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this = Self { padding: None.spanned(Span::DUMMY) };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Month {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this =
            Self {
                padding: None.spanned(Span::DUMMY),
                repr: None.spanned(Span::DUMMY),
                case_sensitive: None.spanned(Span::DUMMY),
            };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "repr") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.repr.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "repr",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.repr =
                    Some(<MonthRepr>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "case_sensitive") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.case_sensitive.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "case_sensitive",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.case_sensitive =
                    Some(<MonthCaseSensitive>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl OffsetHour {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this =
            Self {
                sign_behavior: None.spanned(Span::DUMMY),
                padding: None.spanned(Span::DUMMY),
            };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "sign") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.sign_behavior.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "sign_behavior",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.sign_behavior =
                    Some(<SignBehavior>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl OffsetMinute {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this = Self { padding: None.spanned(Span::DUMMY) };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl OffsetSecond {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this = Self { padding: None.spanned(Span::DUMMY) };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Ordinal {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this = Self { padding: None.spanned(Span::DUMMY) };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Period {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this =
            Self {
                case: None.spanned(Span::DUMMY),
                case_sensitive: None.spanned(Span::DUMMY),
            };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "case") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.case.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "case",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.case =
                    Some(<PeriodCase>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "case_sensitive") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.case_sensitive.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "case_sensitive",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.case_sensitive =
                    Some(<PeriodCaseSensitive>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Second {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this = Self { padding: None.spanned(Span::DUMMY) };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Subsecond {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this = Self { digits: None.spanned(Span::DUMMY) };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "digits") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.digits.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "digits",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.digits =
                    Some(<SubsecondDigits>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl UnixTimestamp {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this =
            Self {
                precision: None.spanned(Span::DUMMY),
                sign_behavior: None.spanned(Span::DUMMY),
            };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "precision") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.precision.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "precision",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.precision =
                    Some(<UnixTimestampPrecision>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "sign") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.sign_behavior.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "sign_behavior",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.sign_behavior =
                    Some(<SignBehavior>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Weekday {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this =
            Self {
                repr: None.spanned(Span::DUMMY),
                one_indexed: None.spanned(Span::DUMMY),
                case_sensitive: None.spanned(Span::DUMMY),
            };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "repr") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.repr.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "repr",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.repr =
                    Some(<WeekdayRepr>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "one_indexed") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.one_indexed.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "one_indexed",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.one_indexed =
                    Some(<WeekdayOneIndexed>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "case_sensitive") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.case_sensitive.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "case_sensitive",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.case_sensitive =
                    Some(<WeekdayCaseSensitive>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl WeekNumber {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this =
            Self {
                padding: None.spanned(Span::DUMMY),
                repr: None.spanned(Span::DUMMY),
            };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "repr") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.repr.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "repr",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.repr =
                    Some(<WeekNumberRepr>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
impl Year {
    /// Parse the component from the AST, given its modifiers.
    #[inline]
    fn with_modifiers<const VERSION :
        u8>(modifiers: &[Modifier<'_>], _component_span: Span)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        #[allow(unused_mut)]
        let mut this =
            Self {
                padding: None.spanned(Span::DUMMY),
                repr: None.spanned(Span::DUMMY),
                range: None.spanned(Span::DUMMY),
                base: None.spanned(Span::DUMMY),
                sign_behavior: None.spanned(Span::DUMMY),
            };
        for modifier in modifiers {
            if ident_eq::<VERSION>(&modifier.key, "padding") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.padding.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "padding",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.padding =
                    Some(<Padding>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "repr") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.repr.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "repr",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.repr =
                    Some(<YearRepr>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "range") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.range.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "range",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.range =
                    Some(<YearRange>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "base") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.base.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "base",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.base =
                    Some(<YearBase>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            if ident_eq::<VERSION>(&modifier.key, "sign") {
                if const {

                                #[allow(non_exhaustive_omitted_patterns)]
                                match VERSION { 3.. => true, _ => false, }
                            } && this.sign_behavior.is_some() {
                    hint::cold_path();
                    return Err(Error {
                                _inner: unused(modifier.key_span().error("duplicate modifier key")),
                                public: InvalidFormatDescription::DuplicateModifier {
                                    name: "sign_behavior",
                                    index: modifier.key.location.byte as usize,
                                },
                            });
                }
                this.sign_behavior =
                    Some(<SignBehavior>::from_modifier_value::<VERSION>(||
                                        modifier.value_span(),
                                    modifier.value)?).spanned(modifier.key_value_span());
                continue;
            }
            hint::cold_path();
            return Err(Error {
                        _inner: unused(modifier.key_span().error("invalid modifier key")),
                        public: InvalidFormatDescription::InvalidModifier {
                            value: (*modifier.key).to_owned(),
                            index: modifier.key.location.byte as usize,
                        },
                    });
        }
        Ok(this)
    }
}
/// Parse a component from the AST, given its name and modifiers.
#[inline]
pub(super) fn component_from_ast<const VERSION :
    u8>(name: &Spanned<&str>, modifiers: &[Modifier<'_>])
    -> Result<AstComponent, Error> {
    const {
            if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                        1..=3 => true,
                        _ => false,
                    } {
                {
                    ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                }
            };
        };
    if ident_eq::<VERSION>(&name, "day") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Day(match Day::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "end") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::End(match End::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "hour") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Hour(match Hour::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "ignore") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Ignore(match Ignore::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "minute") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Minute(match Minute::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "month") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Month(match Month::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "offset_hour") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::OffsetHour(match OffsetHour::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "offset_minute") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::OffsetMinute(match OffsetMinute::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "offset_second") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::OffsetSecond(match OffsetSecond::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "ordinal") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Ordinal(match Ordinal::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "period") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Period(match Period::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "second") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Second(match Second::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "subsecond") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Subsecond(match Subsecond::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "unix_timestamp") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::UnixTimestamp(match UnixTimestamp::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "weekday") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Weekday(match Weekday::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "week_number") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::WeekNumber(match WeekNumber::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    if ident_eq::<VERSION>(&name, "year") {
        #[allow(unused_mut)]
        let mut component =
            AstComponent::Year(match Year::with_modifiers::<VERSION>(&modifiers,
                        name.span) {
                    Ok(value) => value,
                    Err(error) => {
                        crate::hint::cold_path();
                        return Err(error.into());
                    }
                });
        ;
        return Ok(component);
    }
    hint::cold_path();
    Err(Error {
            _inner: unused(name.span.error("invalid component")),
            public: InvalidFormatDescription::InvalidComponentName {
                name: (**name).to_owned(),
                index: name.span.start.byte as usize,
            },
        })
}component_definition! {
229    pub(super) enum AstComponent {
230        Day = "day" {
231            padding = "padding": Option<Padding>,
232        },
233        End = "end" {
234            trailing_input = "trailing_input": Option<TrailingInput>,
235        },
236        Hour = "hour" {
237            padding = "padding": Option<Padding>,
238            base = "repr": Option<HourBase>,
239        },
240        Ignore = "ignore" {
241            #[required]
242            count = "count": Option<#[from_str] NonZero<u16>>,
243        },
244        Minute = "minute" {
245            padding = "padding": Option<Padding>,
246        },
247        Month = "month" {
248            padding = "padding": Option<Padding>,
249            repr = "repr": Option<MonthRepr>,
250            case_sensitive = "case_sensitive": Option<MonthCaseSensitive>,
251        },
252        OffsetHour = "offset_hour" {
253            sign_behavior = "sign": Option<SignBehavior>,
254            padding = "padding": Option<Padding>,
255        },
256        OffsetMinute = "offset_minute" {
257            padding = "padding": Option<Padding>,
258        },
259        OffsetSecond = "offset_second" {
260            padding = "padding": Option<Padding>,
261        },
262        Ordinal = "ordinal" {
263            padding = "padding": Option<Padding>,
264        },
265        Period = "period" {
266            case = "case": Option<PeriodCase>,
267            case_sensitive = "case_sensitive": Option<PeriodCaseSensitive>,
268        },
269        Second = "second" {
270            padding = "padding": Option<Padding>,
271        },
272        Subsecond = "subsecond" {
273            digits = "digits": Option<SubsecondDigits>,
274        },
275        UnixTimestamp = "unix_timestamp" {
276            precision = "precision": Option<UnixTimestampPrecision>,
277            sign_behavior = "sign": Option<SignBehavior>,
278        },
279        Weekday = "weekday" {
280            repr = "repr": Option<WeekdayRepr>,
281            one_indexed = "one_indexed": Option<WeekdayOneIndexed>,
282            case_sensitive = "case_sensitive": Option<WeekdayCaseSensitive>,
283        },
284        WeekNumber = "week_number" {
285            padding = "padding": Option<Padding>,
286            repr = "repr": Option<WeekNumberRepr>,
287        },
288        Year = "year" {
289            padding = "padding": Option<Padding>,
290            repr = "repr": Option<YearRepr>,
291            range = "range": Option<YearRange>,
292            base = "base": Option<YearBase>,
293            sign_behavior = "sign": Option<SignBehavior>,
294        },
295    }
296}
297
298macro_rules! impl_from_ast_component_for {
299    ($([$reject_nonsensical:literal] $ty:ty),+ $(,)?) => {$(
300        impl TryFrom<AstComponent> for $ty {
301            type Error = Error;
302
303            #[inline]
304            fn try_from(component: AstComponent) -> Result<Self, Self::Error> {
305                macro_rules! reject_modifier {
306                    ($modifier:ident, $modifier_str:literal, $context:literal) => {
307                        if $reject_nonsensical && $modifier.value.is_some() {
308                            hint::cold_path();
309                            return Err(Error {
310                                _inner: unused($modifier.span.error(concat!(
311                                    "the '",
312                                    $modifier_str,
313                                    "' modifier is not valid ",
314                                    $context
315                                ))),
316                                public: InvalidFormatDescription::InvalidModifierCombination {
317                                    modifier: $modifier_str,
318                                    context: $context,
319                                    index: $modifier.span.start.byte as usize,
320                                },
321                            });
322                        }
323                    };
324                }
325
326                use crate::format_description::modifier;
327                Ok(match component {
328                    AstComponent::Day(Day { padding }) => Self::Day(modifier::Day {
329                        padding: padding.unwrap_or_default().into(),
330                    }),
331                    AstComponent::End(End { trailing_input }) => Self::End(modifier::End {
332                        trailing_input: trailing_input.unwrap_or_default().into(),
333                    }),
334                    AstComponent::Hour(Hour { padding, base }) => match base.unwrap_or_default() {
335                        HourBase::Twelve => Self::Hour12(modifier::Hour12 {
336                            padding: padding.unwrap_or_default().into(),
337                        }),
338                        HourBase::TwentyFour => Self::Hour24(modifier::Hour24 {
339                            padding: padding.unwrap_or_default().into(),
340                        }),
341                    },
342                    AstComponent::Ignore(Ignore { count }) => Self::Ignore(modifier::Ignore {
343                        count: match *count {
344                            Some(value) => value,
345                            None => bug!("required modifier was not set"),
346                        },
347                    }),
348                    AstComponent::Minute(Minute { padding }) => Self::Minute(modifier::Minute {
349                        padding: padding.unwrap_or_default().into(),
350                    }),
351                    AstComponent::Month(Month {
352                        padding,
353                        repr,
354                        case_sensitive,
355                    }) => match repr.unwrap_or_default() {
356                        MonthRepr::Numerical => {
357                            reject_modifier!(
358                                case_sensitive,
359                                "case_sensitive",
360                                "for numerical month"
361                            );
362                            Self::MonthNumerical(modifier::MonthNumerical {
363                                padding: padding.unwrap_or_default().into(),
364                            })
365                        },
366                        MonthRepr::Long => {
367                            reject_modifier!(padding, "padding", "for long month");
368                            Self::MonthLong(modifier::MonthLong {
369                                case_sensitive: case_sensitive.unwrap_or_default().into(),
370                            })
371                        },
372                        MonthRepr::Short => {
373                            reject_modifier!(padding, "padding", "for short month");
374                            Self::MonthShort(modifier::MonthShort {
375                                case_sensitive: case_sensitive.unwrap_or_default().into(),
376                            })
377                        },
378                    },
379                    AstComponent::OffsetHour(OffsetHour {
380                        sign_behavior,
381                        padding,
382                    }) => Self::OffsetHour(modifier::OffsetHour {
383                        sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
384                        padding: padding.unwrap_or_default().into(),
385                    }),
386                    AstComponent::OffsetMinute(OffsetMinute { padding }) => {
387                        Self::OffsetMinute(modifier::OffsetMinute {
388                            padding: padding.unwrap_or_default().into(),
389                        })
390                    }
391                    AstComponent::OffsetSecond(OffsetSecond { padding }) => {
392                        Self::OffsetSecond(modifier::OffsetSecond {
393                            padding: padding.unwrap_or_default().into(),
394                        })
395                    }
396                    AstComponent::Ordinal(Ordinal { padding }) => Self::Ordinal(modifier::Ordinal {
397                        padding: padding.unwrap_or_default().into(),
398                    }),
399                    AstComponent::Period(Period {
400                        case,
401                        case_sensitive,
402                    }) => Self::Period(modifier::Period {
403                        is_uppercase: case.unwrap_or_default().into(),
404                        case_sensitive: case_sensitive.unwrap_or_default().into(),
405                    }),
406                    AstComponent::Second(Second { padding }) => Self::Second(modifier::Second {
407                        padding: padding.unwrap_or_default().into(),
408                    }),
409                    AstComponent::Subsecond(Subsecond { digits }) => {
410                        Self::Subsecond(modifier::Subsecond {
411                            digits: digits.unwrap_or_default().into(),
412                        })
413                    },
414                    AstComponent::UnixTimestamp(UnixTimestamp {
415                        precision,
416                        sign_behavior,
417                    }) => match precision.unwrap_or_default() {
418                        UnixTimestampPrecision::Second => {
419                            Self::UnixTimestampSecond(modifier::UnixTimestampSecond {
420                                sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
421                            })
422                        }
423                        UnixTimestampPrecision::Millisecond => {
424                            Self::UnixTimestampMillisecond(modifier::UnixTimestampMillisecond {
425                                sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
426                            })
427                        }
428                        UnixTimestampPrecision::Microsecond => {
429                            Self::UnixTimestampMicrosecond(modifier::UnixTimestampMicrosecond {
430                                sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
431                            })
432                        }
433                        UnixTimestampPrecision::Nanosecond => {
434                            Self::UnixTimestampNanosecond(modifier::UnixTimestampNanosecond {
435                                sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
436                            })
437                        }
438                    },
439                    AstComponent::Weekday(Weekday {
440                        repr,
441                        one_indexed,
442                        case_sensitive,
443                    }) => match repr.unwrap_or_default() {
444                        WeekdayRepr::Short => {
445                            reject_modifier!(one_indexed, "one_indexed", "for short weekday");
446                            Self::WeekdayShort(modifier::WeekdayShort {
447                                case_sensitive: case_sensitive.unwrap_or_default().into(),
448                            })
449                        },
450                        WeekdayRepr::Long => {
451                            reject_modifier!(one_indexed, "one_indexed", "for long weekday");
452                            Self::WeekdayLong(modifier::WeekdayLong {
453                                case_sensitive: case_sensitive.unwrap_or_default().into(),
454                            })
455                        },
456                        WeekdayRepr::Sunday => {
457                            reject_modifier!(
458                                case_sensitive,
459                                "case_sensitive",
460                                "for numerical weekday"
461                            );
462                            Self::WeekdaySunday(modifier::WeekdaySunday {
463                                one_indexed: one_indexed.unwrap_or_default().into(),
464                            })
465                        },
466                        WeekdayRepr::Monday => {
467                            reject_modifier!(
468                                case_sensitive,
469                                "case_sensitive",
470                                "for numerical weekday"
471                            );
472                            Self::WeekdayMonday(modifier::WeekdayMonday {
473                                one_indexed: one_indexed.unwrap_or_default().into(),
474                            })
475                        },
476                    },
477                    AstComponent::WeekNumber(WeekNumber { padding, repr }) => {
478                        match repr.unwrap_or_default() {
479                            WeekNumberRepr::Iso => {
480                                Self::WeekNumberIso(modifier::WeekNumberIso {
481                                    padding: padding.unwrap_or_default().into(),
482                                })
483                            },
484                            WeekNumberRepr::Sunday => {
485                                Self::WeekNumberSunday(modifier::WeekNumberSunday {
486                                    padding: padding.unwrap_or_default().into(),
487                                })
488                            },
489                            WeekNumberRepr::Monday => {
490                                Self::WeekNumberMonday(modifier::WeekNumberMonday {
491                                    padding: padding.unwrap_or_default().into(),
492                                })
493                            },
494                        }
495                    }
496                    AstComponent::Year(Year {
497                        padding,
498                        repr,
499                        range,
500                        base,
501                        sign_behavior,
502                    }) => {
503                        #[cfg(not(feature = "large-dates"))]
504                        reject_modifier!(
505                            range,
506                            "range",
507                            "when the `large-dates` feature is not enabled"
508                        );
509
510                        match (
511                            base.unwrap_or_default(),
512                            repr.unwrap_or_default(),
513                            range.unwrap_or_default(),
514                        ) {
515                            #[cfg(feature = "large-dates")]
516                            (YearBase::Calendar, YearRepr::Full, YearRange::Extended) => {
517                                Self::CalendarYearFullExtendedRange(
518                                    modifier::CalendarYearFullExtendedRange {
519                                        padding: padding.unwrap_or_default().into(),
520                                        sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
521                                    },
522                                )
523                            }
524                            (YearBase::Calendar, YearRepr::Full, _) => {
525                                Self::CalendarYearFullStandardRange(
526                                    modifier::CalendarYearFullStandardRange {
527                                        padding: padding.unwrap_or_default().into(),
528                                        sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
529                                    },
530                                )
531                            }
532                            #[cfg(feature = "large-dates")]
533                            (YearBase::Calendar, YearRepr::Century, YearRange::Extended) => {
534                                Self::CalendarYearCenturyExtendedRange(
535                                    modifier::CalendarYearCenturyExtendedRange {
536                                        padding: padding.unwrap_or_default().into(),
537                                        sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
538                                    },
539                                )
540                            }
541                            (YearBase::Calendar, YearRepr::Century, _) => {
542                                Self::CalendarYearCenturyStandardRange(
543                                    modifier::CalendarYearCenturyStandardRange {
544                                        padding: padding.unwrap_or_default().into(),
545                                        sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
546                                    },
547                                )
548                            }
549                            #[cfg(feature = "large-dates")]
550                            (YearBase::IsoWeek, YearRepr::Full, YearRange::Extended) => {
551                                Self::IsoYearFullExtendedRange(modifier::IsoYearFullExtendedRange {
552                                    padding: padding.unwrap_or_default().into(),
553                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
554                                })
555                            }
556                            (YearBase::IsoWeek, YearRepr::Full, _) => {
557                                Self::IsoYearFullStandardRange(modifier::IsoYearFullStandardRange {
558                                    padding: padding.unwrap_or_default().into(),
559                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
560                                })
561                            }
562                            #[cfg(feature = "large-dates")]
563                            (YearBase::IsoWeek, YearRepr::Century, YearRange::Extended) => {
564                                Self::IsoYearCenturyExtendedRange(
565                                    modifier::IsoYearCenturyExtendedRange {
566                                        padding: padding.unwrap_or_default().into(),
567                                        sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
568                                    },
569                                )
570                            }
571                            (YearBase::IsoWeek, YearRepr::Century, _) => {
572                                Self::IsoYearCenturyStandardRange(
573                                    modifier::IsoYearCenturyStandardRange {
574                                        padding: padding.unwrap_or_default().into(),
575                                        sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
576                                    },
577                                )
578                            }
579                            (YearBase::Calendar, YearRepr::LastTwo, _) => {
580                                #[cfg(feature = "large-dates")]
581                                reject_modifier!(range, "range", "when `repr:last_two` is used");
582                                reject_modifier!(
583                                    sign_behavior,
584                                    "sign",
585                                    "when `repr:last_two` is used"
586                                );
587                                Self::CalendarYearLastTwo(modifier::CalendarYearLastTwo {
588                                    padding: padding.unwrap_or_default().into(),
589                                })
590                            }
591                            (YearBase::IsoWeek, YearRepr::LastTwo, _) => {
592                                #[cfg(feature = "large-dates")]
593                                reject_modifier!(range, "range", "when `repr:last_two` is used");
594                                reject_modifier!(
595                                    sign_behavior,
596                                    "sign",
597                                    "when `repr:last_two` is used"
598                                );
599                                Self::IsoYearLastTwo(modifier::IsoYearLastTwo {
600                                    padding: padding.unwrap_or_default().into(),
601                                })
602                            }
603                        }
604                    }
605                })
606            }
607        })+
608    }
609}
610
611impl TryFrom<AstComponent> for FormatDescriptionV3Inner<'_> {
    type Error = Error;
    #[inline]
    fn try_from(component: AstComponent) -> Result<Self, Self::Error> {
        macro_rules! reject_modifier {
            ($modifier : ident, $modifier_str : literal, $context : literal)
            =>
            {
                if true && $modifier.value.is_some()
                {
                    hint :: cold_path(); return
                    Err(Error
                    {
                        _inner :
                        unused($modifier.span.error(concat!
                        ("the '", $modifier_str, "' modifier is not valid ",
                        $context))), public : InvalidFormatDescription ::
                        InvalidModifierCombination
                        {
                            modifier : $modifier_str, context : $context, index :
                            $modifier.span.start.byte as usize,
                        },
                    });
                }
            };
        }
        use crate::format_description::modifier;
        Ok(match component {
                AstComponent::Day(Day { padding }) =>
                    Self::Day(modifier::Day {
                            padding: padding.unwrap_or_default().into(),
                        }),
                AstComponent::End(End { trailing_input }) =>
                    Self::End(modifier::End {
                            trailing_input: trailing_input.unwrap_or_default().into(),
                        }),
                AstComponent::Hour(Hour { padding, base }) =>
                    match base.unwrap_or_default() {
                        HourBase::Twelve =>
                            Self::Hour12(modifier::Hour12 {
                                    padding: padding.unwrap_or_default().into(),
                                }),
                        HourBase::TwentyFour =>
                            Self::Hour24(modifier::Hour24 {
                                    padding: padding.unwrap_or_default().into(),
                                }),
                    },
                AstComponent::Ignore(Ignore { count }) =>
                    Self::Ignore(modifier::Ignore {
                            count: match *count {
                                Some(value) => value,
                                None => {
                                    crate::hint::cold_path();
                                    {
                                        ::core::panicking::panic_fmt(format_args!("internal error: required modifier was not set"));
                                    }
                                }
                            },
                        }),
                AstComponent::Minute(Minute { padding }) =>
                    Self::Minute(modifier::Minute {
                            padding: padding.unwrap_or_default().into(),
                        }),
                AstComponent::Month(Month { padding, repr, case_sensitive })
                    =>
                    match repr.unwrap_or_default() {
                        MonthRepr::Numerical => {
                            if true && case_sensitive.value.is_some() {
                                hint::cold_path();
                                return Err(Error {
                                            _inner: unused(case_sensitive.span.error("the \'case_sensitive\' modifier is not valid for numerical month")),
                                            public: InvalidFormatDescription::InvalidModifierCombination {
                                                modifier: "case_sensitive",
                                                context: "for numerical month",
                                                index: case_sensitive.span.start.byte as usize,
                                            },
                                        });
                            };
                            Self::MonthNumerical(modifier::MonthNumerical {
                                    padding: padding.unwrap_or_default().into(),
                                })
                        }
                        MonthRepr::Long => {
                            if true && padding.value.is_some() {
                                hint::cold_path();
                                return Err(Error {
                                            _inner: unused(padding.span.error("the \'padding\' modifier is not valid for long month")),
                                            public: InvalidFormatDescription::InvalidModifierCombination {
                                                modifier: "padding",
                                                context: "for long month",
                                                index: padding.span.start.byte as usize,
                                            },
                                        });
                            };
                            Self::MonthLong(modifier::MonthLong {
                                    case_sensitive: case_sensitive.unwrap_or_default().into(),
                                })
                        }
                        MonthRepr::Short => {
                            if true && padding.value.is_some() {
                                hint::cold_path();
                                return Err(Error {
                                            _inner: unused(padding.span.error("the \'padding\' modifier is not valid for short month")),
                                            public: InvalidFormatDescription::InvalidModifierCombination {
                                                modifier: "padding",
                                                context: "for short month",
                                                index: padding.span.start.byte as usize,
                                            },
                                        });
                            };
                            Self::MonthShort(modifier::MonthShort {
                                    case_sensitive: case_sensitive.unwrap_or_default().into(),
                                })
                        }
                    },
                AstComponent::OffsetHour(OffsetHour { sign_behavior, padding
                    }) =>
                    Self::OffsetHour(modifier::OffsetHour {
                            sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
                            padding: padding.unwrap_or_default().into(),
                        }),
                AstComponent::OffsetMinute(OffsetMinute { padding }) => {
                    Self::OffsetMinute(modifier::OffsetMinute {
                            padding: padding.unwrap_or_default().into(),
                        })
                }
                AstComponent::OffsetSecond(OffsetSecond { padding }) => {
                    Self::OffsetSecond(modifier::OffsetSecond {
                            padding: padding.unwrap_or_default().into(),
                        })
                }
                AstComponent::Ordinal(Ordinal { padding }) =>
                    Self::Ordinal(modifier::Ordinal {
                            padding: padding.unwrap_or_default().into(),
                        }),
                AstComponent::Period(Period { case, case_sensitive }) =>
                    Self::Period(modifier::Period {
                            is_uppercase: case.unwrap_or_default().into(),
                            case_sensitive: case_sensitive.unwrap_or_default().into(),
                        }),
                AstComponent::Second(Second { padding }) =>
                    Self::Second(modifier::Second {
                            padding: padding.unwrap_or_default().into(),
                        }),
                AstComponent::Subsecond(Subsecond { digits }) => {
                    Self::Subsecond(modifier::Subsecond {
                            digits: digits.unwrap_or_default().into(),
                        })
                }
                AstComponent::UnixTimestamp(UnixTimestamp {
                    precision, sign_behavior }) =>
                    match precision.unwrap_or_default() {
                        UnixTimestampPrecision::Second => {
                            Self::UnixTimestampSecond(modifier::UnixTimestampSecond {
                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
                                })
                        }
                        UnixTimestampPrecision::Millisecond => {
                            Self::UnixTimestampMillisecond(modifier::UnixTimestampMillisecond {
                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
                                })
                        }
                        UnixTimestampPrecision::Microsecond => {
                            Self::UnixTimestampMicrosecond(modifier::UnixTimestampMicrosecond {
                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
                                })
                        }
                        UnixTimestampPrecision::Nanosecond => {
                            Self::UnixTimestampNanosecond(modifier::UnixTimestampNanosecond {
                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
                                })
                        }
                    },
                AstComponent::Weekday(Weekday {
                    repr, one_indexed, case_sensitive }) =>
                    match repr.unwrap_or_default() {
                        WeekdayRepr::Short => {
                            if true && one_indexed.value.is_some() {
                                hint::cold_path();
                                return Err(Error {
                                            _inner: unused(one_indexed.span.error("the \'one_indexed\' modifier is not valid for short weekday")),
                                            public: InvalidFormatDescription::InvalidModifierCombination {
                                                modifier: "one_indexed",
                                                context: "for short weekday",
                                                index: one_indexed.span.start.byte as usize,
                                            },
                                        });
                            };
                            Self::WeekdayShort(modifier::WeekdayShort {
                                    case_sensitive: case_sensitive.unwrap_or_default().into(),
                                })
                        }
                        WeekdayRepr::Long => {
                            if true && one_indexed.value.is_some() {
                                hint::cold_path();
                                return Err(Error {
                                            _inner: unused(one_indexed.span.error("the \'one_indexed\' modifier is not valid for long weekday")),
                                            public: InvalidFormatDescription::InvalidModifierCombination {
                                                modifier: "one_indexed",
                                                context: "for long weekday",
                                                index: one_indexed.span.start.byte as usize,
                                            },
                                        });
                            };
                            Self::WeekdayLong(modifier::WeekdayLong {
                                    case_sensitive: case_sensitive.unwrap_or_default().into(),
                                })
                        }
                        WeekdayRepr::Sunday => {
                            if true && case_sensitive.value.is_some() {
                                hint::cold_path();
                                return Err(Error {
                                            _inner: unused(case_sensitive.span.error("the \'case_sensitive\' modifier is not valid for numerical weekday")),
                                            public: InvalidFormatDescription::InvalidModifierCombination {
                                                modifier: "case_sensitive",
                                                context: "for numerical weekday",
                                                index: case_sensitive.span.start.byte as usize,
                                            },
                                        });
                            };
                            Self::WeekdaySunday(modifier::WeekdaySunday {
                                    one_indexed: one_indexed.unwrap_or_default().into(),
                                })
                        }
                        WeekdayRepr::Monday => {
                            if true && case_sensitive.value.is_some() {
                                hint::cold_path();
                                return Err(Error {
                                            _inner: unused(case_sensitive.span.error("the \'case_sensitive\' modifier is not valid for numerical weekday")),
                                            public: InvalidFormatDescription::InvalidModifierCombination {
                                                modifier: "case_sensitive",
                                                context: "for numerical weekday",
                                                index: case_sensitive.span.start.byte as usize,
                                            },
                                        });
                            };
                            Self::WeekdayMonday(modifier::WeekdayMonday {
                                    one_indexed: one_indexed.unwrap_or_default().into(),
                                })
                        }
                    },
                AstComponent::WeekNumber(WeekNumber { padding, repr }) => {
                    match repr.unwrap_or_default() {
                        WeekNumberRepr::Iso => {
                            Self::WeekNumberIso(modifier::WeekNumberIso {
                                    padding: padding.unwrap_or_default().into(),
                                })
                        }
                        WeekNumberRepr::Sunday => {
                            Self::WeekNumberSunday(modifier::WeekNumberSunday {
                                    padding: padding.unwrap_or_default().into(),
                                })
                        }
                        WeekNumberRepr::Monday => {
                            Self::WeekNumberMonday(modifier::WeekNumberMonday {
                                    padding: padding.unwrap_or_default().into(),
                                })
                        }
                    }
                }
                AstComponent::Year(Year {
                    padding, repr, range, base, sign_behavior }) => {
                    if true && range.value.is_some() {
                        hint::cold_path();
                        return Err(Error {
                                    _inner: unused(range.span.error("the \'range\' modifier is not valid when the `large-dates` feature is not enabled")),
                                    public: InvalidFormatDescription::InvalidModifierCombination {
                                        modifier: "range",
                                        context: "when the `large-dates` feature is not enabled",
                                        index: range.span.start.byte as usize,
                                    },
                                });
                    };
                    match (base.unwrap_or_default(), repr.unwrap_or_default(),
                            range.unwrap_or_default()) {
                        (YearBase::Calendar, YearRepr::Full, _) => {
                            Self::CalendarYearFullStandardRange(modifier::CalendarYearFullStandardRange {
                                    padding: padding.unwrap_or_default().into(),
                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
                                })
                        }
                        (YearBase::Calendar, YearRepr::Century, _) => {
                            Self::CalendarYearCenturyStandardRange(modifier::CalendarYearCenturyStandardRange {
                                    padding: padding.unwrap_or_default().into(),
                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
                                })
                        }
                        (YearBase::IsoWeek, YearRepr::Full, _) => {
                            Self::IsoYearFullStandardRange(modifier::IsoYearFullStandardRange {
                                    padding: padding.unwrap_or_default().into(),
                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
                                })
                        }
                        (YearBase::IsoWeek, YearRepr::Century, _) => {
                            Self::IsoYearCenturyStandardRange(modifier::IsoYearCenturyStandardRange {
                                    padding: padding.unwrap_or_default().into(),
                                    sign_is_mandatory: sign_behavior.unwrap_or_default().into(),
                                })
                        }
                        (YearBase::Calendar, YearRepr::LastTwo, _) => {
                            if true && sign_behavior.value.is_some() {
                                hint::cold_path();
                                return Err(Error {
                                            _inner: unused(sign_behavior.span.error("the \'sign\' modifier is not valid when `repr:last_two` is used")),
                                            public: InvalidFormatDescription::InvalidModifierCombination {
                                                modifier: "sign",
                                                context: "when `repr:last_two` is used",
                                                index: sign_behavior.span.start.byte as usize,
                                            },
                                        });
                            };
                            Self::CalendarYearLastTwo(modifier::CalendarYearLastTwo {
                                    padding: padding.unwrap_or_default().into(),
                                })
                        }
                        (YearBase::IsoWeek, YearRepr::LastTwo, _) => {
                            if true && sign_behavior.value.is_some() {
                                hint::cold_path();
                                return Err(Error {
                                            _inner: unused(sign_behavior.span.error("the \'sign\' modifier is not valid when `repr:last_two` is used")),
                                            public: InvalidFormatDescription::InvalidModifierCombination {
                                                modifier: "sign",
                                                context: "when `repr:last_two` is used",
                                                index: sign_behavior.span.start.byte as usize,
                                            },
                                        });
                            };
                            Self::IsoYearLastTwo(modifier::IsoYearLastTwo {
                                    padding: padding.unwrap_or_default().into(),
                                })
                        }
                    }
                }
            })
    }
}impl_from_ast_component_for!(
612    [false] crate::format_description::Component,
613    [true] FormatDescriptionV3Inner<'_>,
614);
615
616/// Get the target type for a given enum.
617macro_rules! target_ty {
618    ($name:ident $type:ty) => {
619        $type
620    };
621    ($name:ident) => {
622        $crate::format_description::modifier::$name
623    };
624}
625
626/// Get the target value for a given enum.
627macro_rules! target_value {
628    ($name:ident $variant:ident $value:expr) => {
629        $value
630    };
631    ($name:ident $variant:ident) => {
632        $crate::format_description::modifier::$name::$variant
633    };
634}
635
636trait ModifierValue {
637    type Type;
638}
639
640/// Declare the various modifiers.
641///
642/// For the general case, ordinary syntax can be used. Note that you _must_ declare a default
643/// variant. The only significant change is that the string representation of the variant must be
644/// provided after the variant name. For example, `Numerical = b"numerical"` declares a variant
645/// named `Numerical` with the string representation `b"numerical"`. This is the value that will be
646/// used when parsing the modifier. The value is not case sensitive.
647///
648/// If the type in the public API does not have the same name as the type in the internal
649/// representation, then the former must be specified in parenthesis after the internal name. For
650/// example, `HourBase(bool)` has an internal name "HourBase", but is represented as a boolean in
651/// the public API.
652///
653/// By default, the internal variant name is assumed to be the same as the public variant name. If
654/// this is not the case, the qualified path to the variant must be specified in parenthesis after
655/// the internal variant name. For example, `Twelve(true)` has an internal variant name "Twelve",
656/// but is represented as `true` in the public API.
657macro_rules! modifier {
658    ($(
659        $(#[expect($expect_inner:meta)])?
660        enum $name:ident $(($target_ty:ty))? {
661            $(
662                $(#[$attr:meta])?
663                $variant:ident $(($target_value:expr))? = $parse_variant:literal
664            ),* $(,)?
665        }
666    )+) => {$(
667        #[derive(Default, Clone, Copy)]
668        enum $name {
669            $($(#[$attr])? $variant),*
670        }
671
672        impl $name {
673            /// Parse the modifier from its string representation.
674            #[inline]
675            fn from_modifier_value<const VERSION: u8>(
676                value_span: impl FnOnce() -> Span,
677                value: &str,
678            ) -> Result<Self, Error>
679            {
680                assert_version!();
681
682                $(if ident_eq::<VERSION>(&value, $parse_variant) {
683                    return Ok(Self::$variant);
684                })*
685
686                hint::cold_path();
687                let span = value_span();
688                Err(Error {
689                    _inner: unused(span.error("invalid modifier value")),
690                    public: InvalidFormatDescription::InvalidModifier {
691                        value: value.to_owned(),
692                        index: span.start.byte as usize,
693                    },
694                })
695            }
696        }
697
698        $(#[expect($expect_inner)])?
699        impl ModifierValue for $name {
700            type Type = target_ty!($name $($target_ty)?);
701        }
702
703        $(#[expect($expect_inner)])?
704        impl From<$name> for target_ty!($name $($target_ty)?) {
705            #[inline]
706            fn from(modifier: $name) -> Self {
707                match modifier {
708                    $($name::$variant => target_value!($name $variant $($target_value)?)),*
709                }
710            }
711        }
712    )+};
713}
714
715// Keep in alphabetical order.
716#[automatically_derived]
impl ::core::default::Default for YearRange {
    #[inline]
    fn default() -> YearRange { Self::Extended }
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for YearRange { }
#[automatically_derived]
impl ::core::clone::Clone for YearRange {
    #[inline]
    fn clone(&self) -> YearRange { *self }
}
#[automatically_derived]
impl ::core::marker::Copy for YearRange { }
impl YearRange {
    /// Parse the modifier from its string representation.
    #[inline]
    fn from_modifier_value<const VERSION :
        u8>(value_span: impl FnOnce() -> Span, value: &str)
        -> Result<Self, Error> {
        const {
                if !#[allow(non_exhaustive_omitted_patterns)] match VERSION {
                            1..=3 => true,
                            _ => false,
                        } {
                    {
                        ::core::panicking::panic_fmt(format_args!("invalid version provided"));
                    }
                };
            };
        if ident_eq::<VERSION>(&value, "standard") {
            return Ok(Self::Standard);
        }
        if ident_eq::<VERSION>(&value, "extended") {
            return Ok(Self::Extended);
        }
        hint::cold_path();
        let span = value_span();
        Err(Error {
                _inner: unused(span.error("invalid modifier value")),
                public: InvalidFormatDescription::InvalidModifier {
                    value: value.to_owned(),
                    index: span.start.byte as usize,
                },
            })
    }
}
#[expect(deprecated)]
impl ModifierValue for YearRange {
    type Type = crate::format_description::modifier::YearRange;
}
#[expect(deprecated)]
impl From<YearRange> for crate::format_description::modifier::YearRange {
    #[inline]
    fn from(modifier: YearRange) -> Self {
        match modifier {
            YearRange::Standard =>
                crate::format_description::modifier::YearRange::Standard,
            YearRange::Extended =>
                crate::format_description::modifier::YearRange::Extended,
        }
    }
}modifier! {
717    enum HourBase(bool) {
718        Twelve(true) = "12",
719        #[default]
720        TwentyFour(false) = "24",
721    }
722
723    enum MonthCaseSensitive(bool) {
724        False(false) = "false",
725        #[default]
726        True(true) = "true",
727    }
728
729    #[expect(deprecated)]
730    enum MonthRepr {
731        #[default]
732        Numerical = "numerical",
733        Long = "long",
734        Short = "short",
735    }
736
737    enum OptionalFormat(bool) {
738        False(false) = "false",
739        #[default]
740        True(true) = "true",
741    }
742
743    enum Padding {
744        Space = "space",
745        #[default]
746        Zero = "zero",
747        None = "none",
748    }
749
750    enum PeriodCase(bool) {
751        Lower(false) = "lower",
752        #[default]
753        Upper(true) = "upper",
754    }
755
756    enum PeriodCaseSensitive(bool) {
757        False(false) = "false",
758        #[default]
759        True(true) = "true",
760    }
761
762    enum SignBehavior(bool) {
763        #[default]
764        Automatic(false) = "automatic",
765        Mandatory(true) = "mandatory",
766    }
767
768    enum SubsecondDigits {
769        One = "1",
770        Two = "2",
771        Three = "3",
772        Four = "4",
773        Five = "5",
774        Six = "6",
775        Seven = "7",
776        Eight = "8",
777        Nine = "9",
778        #[default]
779        OneOrMore = "1+",
780    }
781
782    enum TrailingInput {
783        #[default]
784        Prohibit = "prohibit",
785        Discard = "discard",
786    }
787
788    #[expect(deprecated)]
789    enum UnixTimestampPrecision {
790        #[default]
791        Second = "second",
792        Millisecond = "millisecond",
793        Microsecond = "microsecond",
794        Nanosecond = "nanosecond",
795    }
796
797    #[expect(deprecated)]
798    enum WeekNumberRepr {
799        #[default]
800        Iso = "iso",
801        Sunday = "sunday",
802        Monday = "monday",
803    }
804
805    enum WeekdayCaseSensitive(bool) {
806        False(false) = "false",
807        #[default]
808        True(true) = "true",
809    }
810
811    enum WeekdayOneIndexed(bool) {
812        False(false) = "false",
813        #[default]
814        True(true) = "true",
815    }
816
817    #[expect(deprecated)]
818    enum WeekdayRepr {
819        Short = "short",
820        #[default]
821        Long = "long",
822        Sunday = "sunday",
823        Monday = "monday",
824    }
825
826    enum YearBase(bool) {
827        #[default]
828        Calendar(false) = "calendar",
829        IsoWeek(true) = "iso_week",
830    }
831
832    #[expect(deprecated)]
833    enum YearRepr {
834        #[default]
835        Full = "full",
836        Century = "century",
837        LastTwo = "last_two",
838    }
839
840    // For v1 and v2 format descriptions, the default is `extended`. For v3 format descriptions,
841    // the default is `standard`. For backwards compatibility, the default here needs to stay
842    // `extended`.
843    #[expect(deprecated)]
844    enum YearRange {
845        Standard = "standard",
846        #[default]
847        Extended = "extended",
848    }
849}
850
851/// Parse a modifier value using `FromStr`. Requires the modifier value to be valid UTF-8.
852#[inline]
853fn parse_from_modifier_value<T>(value_span: impl FnOnce() -> Span, value: &str) -> Result<T, Error>
854where
855    T: FromStr,
856{
857    value.parse::<T>().map_err(|_| {
858        hint::cold_path();
859        let span = value_span();
860        Error {
861            _inner: unused(span.error("invalid modifier value")),
862            public: InvalidFormatDescription::InvalidModifier {
863                value: value.to_owned(),
864                index: span.start.byte as usize,
865            },
866        }
867    })
868}