6

I want to process a string containing a backslash followed by an escapable character as if they were one character.

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

Right now, raw has 2 characters: \ and ". But what I actually want is cooked, which only has one character: ".

How do I get cooked?

I was thinking about using regex, but I feel like there should probably be a better way.

2
  • Should every backslash + some character in the string be replaced with that character, or do different escape sequences mean different things? (Or, if you’d like to answer something that addresses a lot of potential questions at once: where did you get the string/which format is it in?) Commented Oct 25, 2019 at 2:03
  • @Ry- Same meaning as in Rust's own strings, i.e. "\n" gives a newline character, etc. Commented Oct 25, 2019 at 2:21

1 Answer 1

4

I like using iterators in Rust, and I think that's a perfect usecase:

#[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('.')));
}

More complete implementation of such a module in the playground.

Sign up to request clarification or add additional context in comments.

2 Comments

No way to get all escaped characters? i.e. \", \`, \t, \n`, etc.? Or do we have to manually put them in the match statement? Close enough either way I suppose, but still leaves a bad taste in my mouth.
@kkeey There's no reason that would be in the std lib. That's an information internal to the compiler.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.