1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
unsafe fn change_borders(text: &mut str) {
    let bts = text.as_bytes_mut();
    bts[0] = b'\'';
    bts[bts.len() - 1] = b'\'';
}

pub fn escape(src: &str) -> String {
    let mut formatted = format!("{:?}", src).replace('\'', "\\d");
    unsafe { change_borders(&mut formatted) }
    formatted
}

// Tab is escaped as \t.
// Carriage return is escaped as \r.
// Line feed is escaped as \n.
// Single quote is escaped as \'.
// Double quote is escaped as \".
// Backslash is escaped as \\.
pub fn deescape(src: String) -> String {
    let mut result = String::new();
    let mut chars = src.chars();
    while let Some(symbol) = chars.next() {
        if symbol != '\\' {
            result.push(symbol);
            continue;
        }
        let next = match chars.next() {
            Some(val) => val,
            _ => break,
        };
        let val = match next {
            't' => '\t',
            'r' => '\r',
            'n' => '\n',
            'd' => '\'',
            '"' => '"',
            '0' => '\0',
            '\\' => '\\',
            _ => panic!("unexpected escaped sequence"),
        };
        result.push(val)
    }
    result
}