Convert this string into space separated by whitespace characters

I am trying to convert this string to vec or string representation similar to this.

"Text\n\0" ====> \"Text\" 0x0A 0x00
"Test1\t\x7FTest2" ====> \"Test1\" 0x09 0x7F \"Test2\"

What could be possible solution for this?

I have tried this, here is rust playground link

fn main() {
    // let test = "Text\n\0";

    let str1 = "Test1\t\x7FTest2";
    let mut res = vec![];

    for c in str1.chars() {
        res.push("\"");
        if c == '\t' {        
            res.push("\" 0x09");
        } else if c == '\x7F' {
            res.push("\" 0x7F");
        } else {
            res.push(c);
        }
    }

    println!("{}", res.join(" "));
    assert_eq!(res.join(" "), "\"Test1\" 0x09 0x7F \"Test2\"".to_string());
}

How about something like this:

fn main() {
    let str1 = "Test1\t\x7FTest2";
    let mut res = vec![];
    let mut temp_string = String::new();

    for c in str1.chars() {
        if c == '\t' {
            if !temp_string.is_empty() {
                res.push(format!(r#""{temp_string}""#));
                temp_string.clear();
            }
            res.push("0x09".to_owned());
        } else if c == '\x7F' {
            if !temp_string.is_empty() {
                res.push(format!(r#""{temp_string}""#));
                temp_string.clear();
            }
            res.push("0x7F".to_owned());
        } else {
            temp_string.push(c);
        }
    }

    if !temp_string.is_empty() {
        res.push(format!(r#""{temp_string}""#));
    }

    println!("{}", res.join(" "));
    assert_eq!(res.join(" "), "\"Test1\" 0x09 0x7F \"Test2\"".to_string());
}

Playground.

1 Like

Here’s one approach (playground):

pub fn encode(s: &str) -> Vec<String> {
    let mut result = vec![];
    for chunk in s.split_inclusive(should_escape) {
        // The last char of `chunk` may need escaping.
        let (i, c) = chunk.char_indices().last().unwrap();
        if should_escape(c) {
            if i > 0 {
                result.push(quote(&chunk[..i]));
            }
            result.push(escape(c));
        } else {
            result.push(quote(chunk));
        }
    }
    result
}

fn should_escape(c: char) -> bool {
    c.is_ascii_whitespace() || c.is_ascii_control()
}

fn escape(c: char) -> String {
    format!("0x{:02X}", c as u8)
}

fn quote(s: &str) -> String {
    format!("\"{s}\"")
}

Note that you can modify the should_escape function to easily change which characters get escaped.

Nice. If you pass &mut Vec<u8> to quote, you can use write! and avoid allocating a string.