time_macros/format_description/public/
modifier.rs

1use std::num::NonZero;
2
3use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
4
5use crate::to_tokens::{ToTokenStream, ToTokenTree};
6
7macro_rules! to_tokens {
8    (
9        $(#[$struct_attr:meta])*
10        $struct_vis:vis struct $struct_name:ident {$(
11            $(#[$field_attr:meta])*
12            $field_vis:vis $field_name:ident : $field_ty:ty = $default:pat
13        ),* $(,)?}
14    ) => {
15        $(#[$struct_attr])*
16        $struct_vis struct $struct_name {$(
17            $(#[$field_attr])*
18            $field_vis $field_name: $field_ty
19        ),*}
20
21        impl ToTokenTree for $struct_name {
22            fn into_token_tree(self) -> TokenTree {
23                let Self {$($field_name),*} = self;
24
25                #[allow(clippy::redundant_pattern_matching)]
26                if matches!(($(&$field_name,)*), ($($default,)*)) {
27                    return TokenTree::Group(Group::new(
28                        Delimiter::None,
29                        quote_! { $struct_name::default() }
30                    ));
31                }
32
33                let mut tokens = quote_! {
34                    let mut value = $struct_name::default();
35                };
36                $(
37                    #[allow(clippy::redundant_pattern_matching)]
38                    if !matches!($field_name, $default) {
39                        quote_append!(tokens value.$field_name =);
40                        $field_name.append_to(&mut tokens);
41                        quote_append!(tokens ;);
42                    }
43                )*
44                quote_append!(tokens value);
45
46                TokenTree::Group(Group::new(
47                    Delimiter::Brace,
48                    tokens,
49                ))
50            }
51        }
52    };
53
54    (
55        $(#[$enum_attr:meta])*
56        $enum_vis:vis enum $enum_name:ident {$(
57            $(#[$variant_attr:meta])*
58            $variant_name:ident
59        ),+ $(,)?}
60    ) => {
61        $(#[$enum_attr])*
62        $enum_vis enum $enum_name {$(
63            $(#[$variant_attr])*
64            $variant_name
65        ),+}
66
67        impl ToTokenStream for $enum_name {
68            fn append_to(self, ts: &mut TokenStream) {
69                quote_append! { ts
70                    $enum_name::
71                };
72                let name = match self {
73                    $(Self::$variant_name => stringify!($variant_name)),+
74                };
75                ts.extend([TokenTree::Ident(Ident::new(name, Span::mixed_site()))]);
76            }
77        }
78    }
79}
80
81to_tokens! {
82    pub(crate) struct Day {
83        pub(crate) padding: Padding = Padding::Zero,
84    }
85}
86
87to_tokens! {
88    pub(crate) enum MonthRepr {
89        Numerical,
90        Long,
91        Short,
92    }
93}
94
95to_tokens! {
96    pub(crate) struct Month {
97        pub(crate) padding: Padding = Padding::Zero,
98        pub(crate) repr: MonthRepr = MonthRepr::Numerical,
99        pub(crate) case_sensitive: bool = true,
100    }
101}
102
103to_tokens! {
104    pub(crate) struct Ordinal {
105        pub(crate) padding: Padding = Padding::Zero,
106    }
107}
108
109to_tokens! {
110    pub(crate) enum WeekdayRepr {
111        Short,
112        Long,
113        Sunday,
114        Monday,
115    }
116}
117
118to_tokens! {
119    pub(crate) struct Weekday {
120        pub(crate) repr: WeekdayRepr = WeekdayRepr::Long,
121        pub(crate) one_indexed: bool = true,
122        pub(crate) case_sensitive: bool = true,
123    }
124}
125
126to_tokens! {
127    pub(crate) enum WeekNumberRepr {
128        Iso,
129        Sunday,
130        Monday,
131    }
132}
133
134to_tokens! {
135    pub(crate) struct WeekNumber {
136        pub(crate) padding: Padding = Padding::Zero,
137        pub(crate) repr: WeekNumberRepr = WeekNumberRepr::Iso,
138    }
139}
140
141to_tokens! {
142    pub(crate) enum YearRepr {
143        Full,
144        Century,
145        LastTwo,
146    }
147}
148
149to_tokens! {
150    pub(crate) enum YearRange {
151        Standard,
152        Extended,
153    }
154}
155
156to_tokens! {
157    pub(crate) struct Year {
158        pub(crate) padding: Padding = Padding::Zero,
159        pub(crate) repr: YearRepr = YearRepr::Full,
160        pub(crate) range: YearRange = YearRange::Extended,
161        pub(crate) iso_week_based: bool = false,
162        pub(crate) sign_is_mandatory: bool = false,
163    }
164}
165
166to_tokens! {
167    pub(crate) struct Hour {
168        pub(crate) padding: Padding = Padding::Zero,
169        pub(crate) is_12_hour_clock: bool = false,
170    }
171}
172
173to_tokens! {
174    pub(crate) struct Minute {
175        pub(crate) padding: Padding = Padding::Zero,
176    }
177}
178
179to_tokens! {
180    pub(crate) struct Period {
181        pub(crate) is_uppercase: bool = true,
182        pub(crate) case_sensitive: bool = true,
183    }
184}
185
186to_tokens! {
187    pub(crate) struct Second {
188        pub(crate) padding: Padding = Padding::Zero,
189    }
190}
191
192to_tokens! {
193    pub(crate) enum SubsecondDigits {
194        One,
195        Two,
196        Three,
197        Four,
198        Five,
199        Six,
200        Seven,
201        Eight,
202        Nine,
203        OneOrMore,
204    }
205}
206
207to_tokens! {
208    pub(crate) struct Subsecond {
209        pub(crate) digits: SubsecondDigits = SubsecondDigits::OneOrMore,
210    }
211}
212
213to_tokens! {
214    pub(crate) struct OffsetHour {
215        pub(crate) sign_is_mandatory: bool = false,
216        pub(crate) padding: Padding = Padding::Zero,
217    }
218}
219
220to_tokens! {
221    pub(crate) struct OffsetMinute {
222        pub(crate) padding: Padding = Padding::Zero,
223    }
224}
225
226to_tokens! {
227    pub(crate) struct OffsetSecond {
228        pub(crate) padding: Padding = Padding::Zero,
229    }
230}
231
232to_tokens! {
233    pub(crate) enum Padding {
234        Space,
235        Zero,
236        None,
237    }
238}
239
240pub(crate) struct Ignore {
241    pub(crate) count: NonZero<u16>,
242}
243
244impl ToTokenTree for Ignore {
245    fn into_token_tree(self) -> TokenTree {
246        quote_group! {{
247            Ignore::count(#(self.count))
248        }}
249    }
250}
251
252to_tokens! {
253    pub(crate) enum UnixTimestampPrecision {
254        Second,
255        Millisecond,
256        Microsecond,
257        Nanosecond,
258    }
259}
260
261to_tokens! {
262    pub(crate) struct UnixTimestamp {
263        pub(crate) precision: UnixTimestampPrecision = UnixTimestampPrecision::Second,
264        pub(crate) sign_is_mandatory: bool = false,
265    }
266}
267
268to_tokens! {
269    pub(crate) struct End {}
270}