lexer/
unescaped.rs

1//! Utilities for unescaping strings
2
3use std::{char, str::Chars};
4
5/// Escapes the given char.
6///
7/// # Example
8/// ```
9/// use lexer::unescaped::escape_char;
10/// assert_eq!(Some('\n'), escape_char('n'));
11/// /* \g is NOT a valid escape character */
12/// assert_eq!(None, escape_char('g'));
13/// ```
14pub const fn escape_char(c: char) -> Option<char> {
15    let c = match c {
16        'n' => '\n',
17        'r' => '\r',
18        't' => '\t',
19        '\\' => '\\',
20        '\'' => '\'',
21        '"' => '\"',
22        _ => return None,
23    };
24    Some(c)
25}
26
27/// Iterator that takes a string and outputs it's characters,
28/// unescaping them if necessary.
29///
30/// This means, if the string contains the characters '\\' 'n',
31/// this iterator would return a single character '\n'
32pub struct Unescaped<'src> {
33    chars: Chars<'src>,
34}
35
36impl Iterator for Unescaped<'_> {
37    type Item = char;
38
39    fn next(&mut self) -> Option<Self::Item> {
40        let c = self.chars.next()?;
41        if c == '\\' {
42            escape_char(self.chars.next()?)
43        } else {
44            Some(c)
45        }
46    }
47}
48
49impl<'src> From<&'src str> for Unescaped<'src> {
50    fn from(value: &'src str) -> Self {
51        Self {
52            chars: value.chars(),
53        }
54    }
55}