Skip to main content

time_macros/format_description/
mod.rs

1//! Parser for format descriptions.
2
3use crate::FormatDescriptionVersion;
4
5mod ast;
6mod format_item;
7mod lexer;
8pub(crate) mod public;
9
10pub(crate) fn parse_with_version(
11    version: FormatDescriptionVersion,
12    s: &[u8],
13    proc_span: proc_macro::Span,
14) -> Result<public::OwnedFormatItem, crate::Error> {
15    let mut lexed = lexer::lex(version, s, proc_span);
16    let ast = ast::parse(version, &mut lexed);
17    let format_items = format_item::parse(ast)
18        .map(|res| res.and_then(|item| (version, item).try_into()))
19        .collect::<Result<_, _>>()?;
20
21    let mut fd = public::OwnedFormatItem {
22        version,
23        inner: public::OwnedFormatItemInner::Compound(format_items),
24    };
25    fd.optimize();
26
27    let top_level_item = if let public::OwnedFormatItemInner::Compound(items) = &mut fd.inner
28        && items.len() == 1
29        && let Some(item) = items.pop()
30    {
31        public::OwnedFormatItem {
32            version,
33            inner: item,
34        }
35    } else {
36        fd
37    };
38
39    Ok(top_level_item)
40}
41
42#[derive(Debug, Clone, Copy)]
43struct Location {
44    byte: u32,
45    proc_span: proc_macro::Span,
46}
47
48impl Location {
49    fn to(self, end: Self) -> Span {
50        Span { start: self, end }
51    }
52
53    #[must_use = "this does not modify the original value"]
54    fn offset(&self, offset: u32) -> Self {
55        Self {
56            byte: self.byte + offset,
57            proc_span: self.proc_span,
58        }
59    }
60
61    fn error(self, message: &'static str) -> Error {
62        Error {
63            message,
64            _span: unused(Span {
65                start: self,
66                end: self,
67            }),
68            proc_span: self.proc_span,
69        }
70    }
71}
72
73#[derive(Debug, Clone, Copy)]
74struct Span {
75    start: Location,
76    end: Location,
77}
78
79impl Span {
80    fn dummy() -> Self {
81        Self {
82            start: Location {
83                byte: u32::MAX,
84                proc_span: proc_macro::Span::call_site(),
85            },
86            end: Location {
87                byte: u32::MAX,
88                proc_span: proc_macro::Span::call_site(),
89            },
90        }
91    }
92
93    #[must_use = "this does not modify the original value"]
94    const fn shrink_to_start(&self) -> Self {
95        Self {
96            start: self.start,
97            end: self.start,
98        }
99    }
100
101    #[must_use = "this does not modify the original value"]
102    const fn shrink_to_end(&self) -> Self {
103        Self {
104            start: self.end,
105            end: self.end,
106        }
107    }
108
109    fn error(self, message: &'static str) -> Error {
110        Error {
111            message,
112            _span: unused(self),
113            proc_span: self.start.proc_span,
114        }
115    }
116}
117
118#[derive(Debug, Clone, Copy)]
119struct Spanned<T> {
120    value: T,
121    span: Span,
122}
123
124impl<T> core::ops::Deref for Spanned<T> {
125    type Target = T;
126
127    fn deref(&self) -> &Self::Target {
128        &self.value
129    }
130}
131
132impl<T> Spanned<T> {
133    #[inline]
134    fn map<F, U>(self, f: F) -> Spanned<U>
135    where
136        F: FnOnce(T) -> U,
137    {
138        Spanned {
139            value: f(self.value),
140            span: self.span,
141        }
142    }
143}
144
145trait OptionExt<T> {
146    fn transpose(self) -> Spanned<Option<T>>;
147}
148
149impl<T> OptionExt<T> for Option<Spanned<T>> {
150    #[inline]
151    fn transpose(self) -> Spanned<Option<T>> {
152        match self {
153            Some(spanned) => Spanned {
154                value: Some(spanned.value),
155                span: spanned.span,
156            },
157            None => Spanned {
158                value: None,
159                span: Span::dummy(),
160            },
161        }
162    }
163}
164
165trait SpannedValue: Sized {
166    fn spanned(self, span: Span) -> Spanned<Self>;
167}
168
169impl<T> SpannedValue for T {
170    fn spanned(self, span: Span) -> Spanned<Self> {
171        Spanned { value: self, span }
172    }
173}
174
175#[derive(Debug)]
176struct Error {
177    message: &'static str,
178    _span: Unused<Span>,
179    proc_span: proc_macro::Span,
180}
181
182impl From<Error> for crate::Error {
183    fn from(error: Error) -> Self {
184        Self::Custom {
185            message: error.message.into(),
186            span_start: Some(error.proc_span),
187            span_end: Some(error.proc_span),
188        }
189    }
190}
191
192struct Unused<T>(core::marker::PhantomData<T>);
193
194impl<T> core::fmt::Debug for Unused<T> {
195    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196        f.debug_tuple("Unused").finish()
197    }
198}
199
200fn unused<T>(_: T) -> Unused<T> {
201    Unused(core::marker::PhantomData)
202}