Skip to main content

time_macros/format_description/public/
mod.rs

1mod component;
2pub(super) mod modifier;
3
4use proc_macro::TokenStream;
5
6pub(crate) use self::component::Component;
7use crate::FormatDescriptionVersion;
8use crate::to_tokens::ToTokenStream;
9
10#[derive(Clone)]
11pub(crate) struct OwnedFormatItem {
12    pub(crate) version: FormatDescriptionVersion,
13    pub(crate) inner: OwnedFormatItemInner,
14}
15
16#[derive(Clone)]
17pub(crate) enum OwnedFormatItemInner {
18    Literal(Box<[u8]>),
19    StringLiteral(Box<str>),
20    Component(Component),
21    Compound(Box<[Self]>),
22    Optional { format: bool, item: Box<Self> },
23    First(Box<[Self]>),
24}
25
26impl ToTokenStream for OwnedFormatItem {
27    fn append_to(self, ts: &mut TokenStream) {
28        match self.version {
29            FormatDescriptionVersion::V1 | FormatDescriptionVersion::V2 => match self.inner {
30                OwnedFormatItemInner::Literal(bytes) => quote_append! { ts
31                    BorrowedFormatItem::Literal(#(Literal::byte_string(bytes.as_ref())))
32                },
33                OwnedFormatItemInner::StringLiteral(string) => quote_append! { ts
34                    BorrowedFormatItem::StringLiteral(#(string.as_ref()))
35                },
36                OwnedFormatItemInner::Component(component) => quote_append! { ts
37                    BorrowedFormatItem::Component { 0: #S(component) }
38                },
39                OwnedFormatItemInner::Compound(items) => {
40                    let items = items
41                        .into_vec()
42                        .into_iter()
43                        .map(|item| {
44                            quote_! { #S(Self { version: self.version, inner: item }), }
45                        })
46                        .collect::<TokenStream>();
47                    quote_append! { ts
48                        BorrowedFormatItem::Compound { 0: &[#S(items)] }
49                    }
50                }
51                OwnedFormatItemInner::Optional { format, item } => {
52                    if !format {
53                        bug!("v1 and v2 format descriptions must format optional items")
54                    }
55                    quote_append! { ts
56                        BorrowedFormatItem::Optional {
57                            0: &#S(Self { version: self.version, inner: *item })
58                        }
59                    }
60                }
61                OwnedFormatItemInner::First(items) => {
62                    let items = items
63                        .into_vec()
64                        .into_iter()
65                        .map(|item| {
66                            quote_! { #S(Self { version: self.version, inner: item }), }
67                        })
68                        .collect::<TokenStream>();
69                    quote_append! { ts
70                        BorrowedFormatItem::First { 0: &[#S(items)] }
71                    }
72                }
73            },
74            FormatDescriptionVersion::V3 => match self.inner {
75                OwnedFormatItemInner::Literal(_) => {
76                    bug!("v3 format descriptions should never have non-UTF8 literals")
77                }
78                OwnedFormatItemInner::StringLiteral(string) => quote_append! { ts
79                    FormatDescriptionV3Inner::BorrowedLiteral(#(string.as_ref()))
80                },
81                OwnedFormatItemInner::Component(component) => {
82                    quote_append! { ts
83                        FormatDescriptionV3Inner::Component(#S(component))
84                    }
85                }
86                OwnedFormatItemInner::Compound(items) => {
87                    let items = items
88                        .into_iter()
89                        .map(|item| {
90                            quote_! { #S(Self { version: self.version, inner: item }), }
91                        })
92                        .collect::<TokenStream>();
93                    quote_append! { ts
94                        FormatDescriptionV3Inner::BorrowedCompound(const { &[#S(items)] })
95                    }
96                }
97                OwnedFormatItemInner::Optional { format, item } => {
98                    quote_append! { ts
99                        FormatDescriptionV3Inner::BorrowedOptional {
100                            format: #S(format),
101                            item: &#S(Self { version: self.version, inner: *item })
102                        }
103                    }
104                }
105                OwnedFormatItemInner::First(items) => {
106                    let items = items
107                        .into_iter()
108                        .map(|item| {
109                            quote_! { #S(Self { version: self.version, inner: item }), }
110                        })
111                        .collect::<TokenStream>();
112                    quote_append! { ts
113                        FormatDescriptionV3Inner::BorrowedFirst(const { &[#S(items)] })
114                    }
115                }
116            },
117        }
118    }
119}