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}