lazy_template/enclosed/
simple_escape.rs1use super::{ComponentParserInput, ParserConfig};
2use crate::Parse;
3use derive_more::{Display, Error};
4use split_char_from_str::SplitCharFromStr;
5
6pub type ParserInput<'a> = ComponentParserInput<'a>;
7
8#[derive(Debug, Clone, Copy)]
9pub struct SimpleEscapeParser;
10pub type Parser = SimpleEscapeParser;
11
12pub type SimpleEscape = char;
13pub type ParseOutput = SimpleEscape;
14
15#[derive(Debug, Display, Error, Clone, Copy)]
16pub enum ParseError {
17 #[display("Unsupported escape code {_0:?}")]
18 UnsupportedEscapeCode(#[error(not(source))] char),
19 #[display("Unexpected end of input")]
20 UnexpectedEndOfInput,
21}
22
23impl<'a> Parse<'a, ParserInput<'a>> for Parser {
24 type Output = ParseOutput;
25 type Error = Option<ParseError>;
26
27 fn parse(&self, input: ParserInput<'a>) -> Result<(Self::Output, &'a str), Self::Error> {
28 let (head, tail) = input.text.split_first_char().ok_or(None)?;
29
30 if head != '\\' {
31 return Err(None);
32 }
33
34 let (escape_code, rest) = tail
35 .split_first_char()
36 .ok_or(ParseError::UnexpectedEndOfInput)
37 .map_err(Some)?;
38
39 let char = escape_bracket(escape_code, input.config)
40 .or_else(|| make_special_character(escape_code))
41 .ok_or(ParseError::UnsupportedEscapeCode(escape_code))
42 .map_err(Some)?;
43
44 Ok((char, rest))
45 }
46}
47
48fn escape_bracket(escape_code: char, config: ParserConfig) -> Option<char> {
49 (escape_code == config.open_bracket || escape_code == config.close_bracket)
50 .then_some(escape_code)
51}
52
53fn make_special_character(escape_code: char) -> Option<char> {
54 Some(match escape_code {
55 '\\' => '\\',
56 '0' => '\0',
57 'b' => '\x08',
58 'e' => '\x1b',
59 'n' => '\n',
60 'r' => '\r',
61 't' => '\t',
62 _ => return None,
63 })
64}