]> git.proxmox.com Git - rustc.git/blob - vendor/time-macros/src/format_description/parse.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / vendor / time-macros / src / format_description / parse.rs
1 use proc_macro::Span;
2
3 use crate::format_description::component::{Component, NakedComponent};
4 use crate::format_description::error::InvalidFormatDescription;
5 use crate::format_description::{helper, modifier, FormatItem};
6 use crate::Error;
7
8 struct ParsedItem<'a> {
9 item: FormatItem<'a>,
10 remaining: &'a [u8],
11 }
12
13 fn parse_component(mut s: &[u8], index: &mut usize) -> Result<Component, InvalidFormatDescription> {
14 s = helper::consume_whitespace(s, index);
15
16 let component_index = *index;
17 let whitespace_loc = s
18 .iter()
19 .position(u8::is_ascii_whitespace)
20 .unwrap_or(s.len());
21 *index += whitespace_loc;
22 let component_name = &s[..whitespace_loc];
23 s = &s[whitespace_loc..];
24 s = helper::consume_whitespace(s, index);
25
26 Ok(NakedComponent::parse(component_name, component_index)?
27 .attach_modifiers(modifier::Modifiers::parse(component_name, s, index)?))
28 }
29
30 fn parse_literal<'a>(s: &'a [u8], index: &mut usize) -> ParsedItem<'a> {
31 let loc = s.iter().position(|&c| c == b'[').unwrap_or(s.len());
32 *index += loc;
33 ParsedItem {
34 item: FormatItem::Literal(&s[..loc]),
35 remaining: &s[loc..],
36 }
37 }
38
39 fn parse_item<'a>(
40 s: &'a [u8],
41 index: &mut usize,
42 ) -> Result<ParsedItem<'a>, InvalidFormatDescription> {
43 if let [b'[', b'[', remaining @ ..] = s {
44 *index += 2;
45 return Ok(ParsedItem {
46 item: FormatItem::Literal(b"["),
47 remaining,
48 });
49 };
50
51 if s.starts_with(b"[") {
52 if let Some(bracket_index) = s.iter().position(|&c| c == b']') {
53 *index += 1; // opening bracket
54 let ret_val = ParsedItem {
55 item: FormatItem::Component(parse_component(&s[1..bracket_index], index)?),
56 remaining: &s[bracket_index + 1..],
57 };
58 *index += 1; // closing bracket
59 Ok(ret_val)
60 } else {
61 Err(InvalidFormatDescription::UnclosedOpeningBracket { index: *index })
62 }
63 } else {
64 Ok(parse_literal(s, index))
65 }
66 }
67
68 pub(crate) fn parse(mut s: &[u8], span: Span) -> Result<Vec<FormatItem<'_>>, Error> {
69 let mut compound = Vec::new();
70 let mut loc = 0;
71
72 while !s.is_empty() {
73 let ParsedItem { item, remaining } =
74 parse_item(s, &mut loc).map_err(|error| Error::InvalidFormatDescription {
75 error,
76 span_start: Some(span),
77 span_end: Some(span),
78 })?;
79 s = remaining;
80 compound.push(item);
81 }
82
83 Ok(compound)
84 }