Skip to main content

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