prism_parser/grammar/
escaped_string.rs

1use serde::{Deserialize, Serialize};
2use std::borrow::Cow;
3use std::fmt::{Display, Formatter};
4use std::str::{Chars, FromStr};
5
6#[derive(Debug, Copy, Clone, Hash, Serialize, Deserialize, Eq, PartialEq)]
7pub struct EscapedString<'grm>(&'grm str);
8
9impl<'grm> EscapedString<'grm> {
10    pub fn from_escaped(s: &'grm str) -> Self {
11        Self(s)
12    }
13
14    pub fn to_cow(&self) -> Cow<'grm, str> {
15        if self.0.contains('\\') {
16            Cow::Owned(self.chars().collect())
17        } else {
18            Cow::Borrowed(self.0)
19        }
20    }
21
22    pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
23        EscapedStringIter(self.0.chars())
24    }
25
26    pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
27        self.0.parse()
28    }
29}
30
31impl Display for EscapedString<'_> {
32    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
33        write!(f, "{}", self.0)
34    }
35}
36
37struct EscapedStringIter<'grm>(Chars<'grm>);
38
39impl<'grm> Iterator for EscapedStringIter<'grm> {
40    type Item = char;
41
42    fn next(&mut self) -> Option<Self::Item> {
43        Some(match self.0.next()? {
44            '\\' => match self.0.next()? {
45                'n' => '\n',
46                'r' => '\r',
47                '\\' => '\\',
48                '"' => '"',
49                '\'' => '\'',
50                _ => panic!("Invalid escape sequence"),
51            },
52            c => c,
53        })
54    }
55}