Как «интерпретировать» экранированные символы в строке? - PullRequest
2 голосов
/ 25 октября 2019

Я хочу обработать строку, содержащую обратную косую черту, за которой следует экранируемый символ, как если бы они были одним символом.

let raw = r#"\""#;
let cooked = raw.process_escape_character_magic();

Прямо сейчас, raw имеет 2 символа: \ и ",Но на самом деле я хочу cooked, который имеет только один символ: ".

Как мне получить cooked?

Я думал об использовании регулярных выражений, но я чувствую,как, вероятно, должен быть лучший способ.

1 Ответ

2 голосов
/ 25 октября 2019

Мне нравится использовать итераторы в Rust, и я думаю, что это идеальный вариант использования:

#[derive(Debug, PartialEq)]
enum MyError {
    EscapeAtEndOfString,
    InvalidEscapedChar(char),
}

struct InterpretEscapedString<'a> {
    s: std::str::Chars<'a>,
}

impl<'a> Iterator for InterpretEscapedString<'a> {
    type Item = Result<char, MyError>;

    fn next(&mut self) -> Option<Self::Item> {
        self.s.next().map(|c| match c {
            '\\' => match self.s.next() {
                None => Err(MyError::EscapeAtEndOfString),
                Some('n') => Ok('\n'),
                Some('\\') => Ok('\\'),
                // etc.
                Some(c) => Err(MyError::InvalidEscapedChar(c)),
            },
            c => Ok(c),
        })
    }
}

fn interpret_escaped_string(s: &str) -> Result<String, MyError> {
    (InterpretEscapedString { s: s.chars() }).collect()
}

fn main() {
    assert_eq!(interpret_escaped_string(r#""#), Ok("".into()));
    assert_eq!(interpret_escaped_string(r#"a"#), Ok("a".into()));
    assert_eq!(interpret_escaped_string(r#"\"#), Err(MyError::EscapeAtEndOfString));
    assert_eq!(interpret_escaped_string(r#"\\"#), Ok("\\".into()));
    assert_eq!(interpret_escaped_string(r#"a\n"#), Ok("a\n".into()));
    assert_eq!(interpret_escaped_string(r#"a\."#), Err(MyError::InvalidEscapedChar('.')));
}

Более полная реализация такого модуля на игровой площадке .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...