runtime_format/
parse.rs

1use crate::ToFormatParser;
2
3#[derive(Debug, Clone, Copy)]
4/// An enum representing the parsed portion of a format string
5#[non_exhaustive]
6pub enum ParseSegment<'a> {
7    /// A string literal to be included as is
8    Literal(&'a str),
9    /// A keyed value, that should be looked up using [`FormatKey`](crate::FormatKey)
10    Key(&'a str),
11}
12
13impl Default for ParseSegment<'_> {
14    fn default() -> Self {
15        Self::Literal("")
16    }
17}
18
19/// An [`Iterator`] of [`ParseSegment`]s. Returned by of [`str::to_parser`](ToFormatParser).
20pub struct FromStr<'a> {
21    pub(crate) s: &'a str,
22    pub(crate) is_key: bool,
23}
24
25impl<'a> Iterator for FromStr<'a> {
26    type Item = ParseSegment<'a>;
27
28    fn next(&mut self) -> Option<Self::Item> {
29        if self.s.is_empty() {
30            None
31        } else if self.is_key {
32            match self.s.strip_prefix('{') {
33                // escaped
34                Some(rest) => match rest.split_once('{') {
35                    None => {
36                        self.is_key = false;
37                        Some(ParseSegment::Literal(core::mem::take(&mut self.s)))
38                    }
39                    Some((prefix, rest)) => {
40                        let x = &self.s[..prefix.len() + 1];
41                        self.s = rest;
42                        Some(ParseSegment::Literal(x))
43                    }
44                },
45                None => match self.s.split_once('}') {
46                    Some((key, rest)) => {
47                        self.is_key = false;
48                        self.s = rest;
49                        Some(ParseSegment::Key(key))
50                    }
51                    None => None,
52                },
53            }
54        } else {
55            match self.s.split_once('{') {
56                None => Some(ParseSegment::Literal(core::mem::take(&mut self.s))),
57                Some((prefix, rest)) => {
58                    self.is_key = true;
59                    self.s = rest;
60                    Some(ParseSegment::Literal(prefix))
61                }
62            }
63        }
64    }
65}
66
67impl<'a> ToFormatParser<'a> for str {
68    type Parser = FromStr<'a>;
69
70    fn to_parser(&'a self) -> Self::Parser {
71        FromStr {
72            s: self,
73            is_key: false,
74        }
75    }
76
77    fn unparsed(iter: Self::Parser) -> &'a str {
78        iter.s
79    }
80}