time/format_description/parse/
mod.rs1use alloc::boxed::Box;
4use alloc::vec::Vec;
5
6pub use self::strftime::{parse_strftime_borrowed, parse_strftime_owned};
7use crate::{error, format_description};
8
9macro_rules! version {
11    ($range:expr) => {
12        $range.contains(&VERSION)
13    };
14}
15
16macro_rules! validate_version {
18    ($version:ident) => {
19        const {
20            assert!($version >= 1 && $version <= 2);
21        }
22    };
23}
24
25mod ast;
26mod format_item;
27mod lexer;
28mod strftime;
29
30#[inline]
39pub fn parse(
40    s: &str,
41) -> Result<Vec<format_description::BorrowedFormatItem<'_>>, error::InvalidFormatDescription> {
42    parse_borrowed::<1>(s)
43}
44
45#[inline]
51pub fn parse_borrowed<const VERSION: usize>(
52    s: &str,
53) -> Result<Vec<format_description::BorrowedFormatItem<'_>>, error::InvalidFormatDescription> {
54    validate_version!(VERSION);
55    let mut lexed = lexer::lex::<VERSION>(s.as_bytes());
56    let ast = ast::parse::<_, VERSION>(&mut lexed);
57    let format_items = format_item::parse(ast);
58    Ok(format_items
59        .map(|res| res.and_then(TryInto::try_into))
60        .collect::<Result<_, _>>()?)
61}
62
63#[inline]
74pub fn parse_owned<const VERSION: usize>(
75    s: &str,
76) -> Result<format_description::OwnedFormatItem, error::InvalidFormatDescription> {
77    validate_version!(VERSION);
78    let mut lexed = lexer::lex::<VERSION>(s.as_bytes());
79    let ast = ast::parse::<_, VERSION>(&mut lexed);
80    let format_items = format_item::parse(ast);
81    let items = format_items.collect::<Result<Box<_>, _>>()?;
82    Ok(items.into())
83}
84
85#[inline]
87fn attach_location<'item>(
88    iter: impl Iterator<Item = &'item u8>,
89) -> impl Iterator<Item = (&'item u8, Location)> {
90    let mut byte_pos = 0;
91
92    iter.map(move |byte| {
93        let location = Location { byte: byte_pos };
94        byte_pos += 1;
95        (byte, location)
96    })
97}
98
99#[derive(Clone, Copy)]
101struct Location {
102    byte: u32,
104}
105
106impl Location {
107    #[inline]
109    const fn to(self, end: Self) -> Span {
110        Span { start: self, end }
111    }
112
113    #[inline]
115    const fn to_self(self) -> Span {
116        Span {
117            start: self,
118            end: self,
119        }
120    }
121
122    #[must_use = "this does not modify the original value"]
126    #[inline]
127    const fn offset(&self, offset: u32) -> Self {
128        Self {
129            byte: self.byte + offset,
130        }
131    }
132
133    #[inline]
135    const fn error(self, message: &'static str) -> ErrorInner {
136        ErrorInner {
137            _message: message,
138            _span: Span {
139                start: self,
140                end: self,
141            },
142        }
143    }
144}
145
146#[derive(Clone, Copy)]
148struct Span {
149    start: Location,
150    end: Location,
151}
152
153impl Span {
154    #[must_use = "this does not modify the original value"]
156    #[inline]
157    const fn shrink_to_start(&self) -> Self {
158        Self {
159            start: self.start,
160            end: self.start,
161        }
162    }
163
164    #[must_use = "this does not modify the original value"]
166    const fn shrink_to_end(&self) -> Self {
167        Self {
168            start: self.end,
169            end: self.end,
170        }
171    }
172
173    #[must_use = "this does not modify the original value"]
175    #[inline]
176    const fn shrink_to_before(&self, pos: u32) -> Self {
177        Self {
178            start: self.start,
179            end: Location {
180                byte: self.start.byte + pos - 1,
181            },
182        }
183    }
184
185    #[must_use = "this does not modify the original value"]
187    #[inline]
188    const fn shrink_to_after(&self, pos: u32) -> Self {
189        Self {
190            start: Location {
191                byte: self.start.byte + pos + 1,
192            },
193            end: self.end,
194        }
195    }
196
197    #[inline]
199    const fn error(self, message: &'static str) -> ErrorInner {
200        ErrorInner {
201            _message: message,
202            _span: self,
203        }
204    }
205}
206
207#[derive(Clone, Copy)]
209struct Spanned<T> {
210    value: T,
212    span: Span,
214}
215
216impl<T> core::ops::Deref for Spanned<T> {
217    type Target = T;
218
219    #[inline]
220    fn deref(&self) -> &Self::Target {
221        &self.value
222    }
223}
224
225trait SpannedValue: Sized {
227    fn spanned(self, span: Span) -> Spanned<Self>;
229}
230
231impl<T> SpannedValue for T {
232    #[inline]
233    fn spanned(self, span: Span) -> Spanned<Self> {
234        Spanned { value: self, span }
235    }
236}
237
238struct ErrorInner {
240    _message: &'static str,
242    _span: Span,
244}
245
246struct Error {
248    _inner: Unused<ErrorInner>,
250    public: error::InvalidFormatDescription,
252}
253
254impl From<Error> for error::InvalidFormatDescription {
255    #[inline]
256    fn from(error: Error) -> Self {
257        error.public
258    }
259}
260
261struct Unused<T>(core::marker::PhantomData<T>);
267
268#[inline]
270fn unused<T>(_: T) -> Unused<T> {
271    Unused(core::marker::PhantomData)
272}