time_macros/format_description/
mod.rs

1//! Parser for format descriptions.
2
3macro_rules! version {
4    ($range:expr) => {
5        $range.contains(&VERSION)
6    };
7}
8
9mod ast;
10mod format_item;
11mod lexer;
12mod public;
13
14pub(crate) fn parse_with_version(
15    version: Option<crate::FormatDescriptionVersion>,
16    s: &[u8],
17    proc_span: proc_macro::Span,
18) -> Result<Vec<public::OwnedFormatItem>, crate::Error> {
19    match version {
20        Some(crate::FormatDescriptionVersion::V1) | None => parse::<1>(s, proc_span),
21        Some(crate::FormatDescriptionVersion::V2) => parse::<2>(s, proc_span),
22    }
23}
24
25fn parse<const VERSION: u8>(
26    s: &[u8],
27    proc_span: proc_macro::Span,
28) -> Result<Vec<public::OwnedFormatItem>, crate::Error> {
29    let mut lexed = lexer::lex::<VERSION>(s, proc_span);
30    let ast = ast::parse::<_, VERSION>(&mut lexed);
31    let format_items = format_item::parse(ast);
32    Ok(format_items
33        .map(|res| res.map(Into::into))
34        .collect::<Result<_, _>>()?)
35}
36
37#[derive(Clone, Copy)]
38struct Location {
39    byte: u32,
40    proc_span: proc_macro::Span,
41}
42
43impl Location {
44    fn to(self, end: Self) -> Span {
45        Span { start: self, end }
46    }
47
48    #[must_use = "this does not modify the original value"]
49    fn offset(&self, offset: u32) -> Self {
50        Self {
51            byte: self.byte + offset,
52            proc_span: self.proc_span,
53        }
54    }
55
56    fn error(self, message: &'static str) -> Error {
57        Error {
58            message,
59            _span: unused(Span {
60                start: self,
61                end: self,
62            }),
63            proc_span: self.proc_span,
64        }
65    }
66}
67
68#[derive(Clone, Copy)]
69struct Span {
70    start: Location,
71    end: Location,
72}
73
74impl Span {
75    #[must_use = "this does not modify the original value"]
76    const fn shrink_to_start(&self) -> Self {
77        Self {
78            start: self.start,
79            end: self.start,
80        }
81    }
82
83    #[must_use = "this does not modify the original value"]
84    const fn shrink_to_end(&self) -> Self {
85        Self {
86            start: self.end,
87            end: self.end,
88        }
89    }
90
91    #[must_use = "this does not modify the original value"]
92    const fn shrink_to_before(&self, pos: u32) -> Self {
93        Self {
94            start: self.start,
95            end: Location {
96                byte: self.start.byte + pos - 1,
97                proc_span: self.start.proc_span,
98            },
99        }
100    }
101
102    #[must_use = "this does not modify the original value"]
103    fn shrink_to_after(&self, pos: u32) -> Self {
104        Self {
105            start: Location {
106                byte: self.start.byte + pos + 1,
107                proc_span: self.start.proc_span,
108            },
109            end: self.end,
110        }
111    }
112
113    fn error(self, message: &'static str) -> Error {
114        Error {
115            message,
116            _span: unused(self),
117            proc_span: self.start.proc_span,
118        }
119    }
120}
121
122#[derive(Clone, Copy)]
123struct Spanned<T> {
124    value: T,
125    span: Span,
126}
127
128impl<T> core::ops::Deref for Spanned<T> {
129    type Target = T;
130
131    fn deref(&self) -> &Self::Target {
132        &self.value
133    }
134}
135
136trait SpannedValue: Sized {
137    fn spanned(self, span: Span) -> Spanned<Self>;
138}
139
140impl<T> SpannedValue for T {
141    fn spanned(self, span: Span) -> Spanned<Self> {
142        Spanned { value: self, span }
143    }
144}
145
146struct Error {
147    message: &'static str,
148    _span: Unused<Span>,
149    proc_span: proc_macro::Span,
150}
151
152impl From<Error> for crate::Error {
153    fn from(error: Error) -> Self {
154        Self::Custom {
155            message: error.message.into(),
156            span_start: Some(error.proc_span),
157            span_end: Some(error.proc_span),
158        }
159    }
160}
161
162struct Unused<T>(core::marker::PhantomData<T>);
163
164fn unused<T>(_: T) -> Unused<T> {
165    Unused(core::marker::PhantomData)
166}