1use 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
92macro_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 #[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 #[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 #[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)] 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
227pub(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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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 {
#[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)
}
}
#[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
616macro_rules! target_ty {
618 ($name:ident $type:ty) => {
619 $type
620 };
621 ($name:ident) => {
622 $crate::format_description::modifier::$name
623 };
624}
625
626macro_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
640macro_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 #[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#[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 {
#[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 #[expect(deprecated)]
844 enum YearRange {
845 Standard = "standard",
846 #[default]
847 Extended = "extended",
848 }
849}
850
851#[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}