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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::borrow::Cow;
pub fn escape_quoted(unescaped: &str) -> Cow<str> {
let mut escaped = Cow::Borrowed(unescaped);
if escaped.contains('\\') {
escaped = Cow::Owned(escaped.replace('\\', "\\\\"));
}
if escaped.contains('\"') {
escaped = Cow::Owned(escaped.replace('"', "\\\""));
}
escaped
}
pub fn unescape_quoted(escaped: &str) -> Cow<str> {
let mut unescaped = Cow::Borrowed(escaped);
if unescaped.contains("\\\\") {
unescaped = Cow::Owned(unescaped.replace("\\\\", "\\"));
}
if unescaped.contains("\\\"") {
unescaped = Cow::Owned(unescaped.replace("\\\"", "\""));
}
unescaped
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_escape_quoted() {
let tests = [
("", ""),
("\\", "\\\\"),
("\"", "\\\""),
("alice", "alice"),
("\\alice\\", "\\\\alice\\\\"),
("alice\"", "alice\\\""),
(r#"\alice\ ""#, r#"\\alice\\ \""#),
];
for (test, expected) in tests {
let got = escape_quoted(test);
assert_eq!(expected, got);
}
}
#[test]
fn test_unescape_quoted() {
let tests = [
("", ""),
("\\\\", "\\"),
("\\\"", "\""),
("alice", "alice"),
("\\\\alice\\\\", "\\alice\\"),
("alice\\\"", "alice\""),
(r#"\\alice\\ \""#, r#"\alice\ ""#),
];
for (test, expected) in tests {
let got = unescape_quoted(test);
assert_eq!(expected, got);
}
}
#[test]
fn test_that_unescape_is_inverse_of_escape() {
let input = "\\\"\\¹²³abc_*:;059^$%§!\"";
assert_eq!(input, unescape_quoted(escape_quoted(input).as_ref()));
}
}