lazy_template/enclosed/
simple_escape.rs1use super::{ComponentParserInput, ParserConfig};
2use crate::Parse;
3use derive_more::{Display, Error};
4use split_first_char::split_first_char;
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) = split_first_char(input.text).ok_or(None)?;
29
30 if head != '\\' {
31 return Err(None);
32 }
33
34 let (escape_code, rest) =
35 split_first_char(tail).ok_or(Some(ParseError::UnexpectedEndOfInput))?;
36
37 let char = escape_bracket(escape_code, input.config)
38 .or_else(|| make_special_character(escape_code))
39 .ok_or(ParseError::UnsupportedEscapeCode(escape_code))
40 .map_err(Some)?;
41
42 Ok((char, rest))
43 }
44}
45
46fn escape_bracket(escape_code: char, config: ParserConfig) -> Option<char> {
47 (escape_code == config.open_bracket || escape_code == config.close_bracket)
48 .then_some(escape_code)
49}
50
51fn make_special_character(escape_code: char) -> Option<char> {
52 Some(match escape_code {
53 '\\' => '\\',
54 '0' => '\0',
55 'b' => '\x08',
56 'e' => '\x1b',
57 'n' => '\n',
58 'r' => '\r',
59 't' => '\t',
60 _ => return None,
61 })
62}