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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use crate::TextError;
use std::intrinsics::transmute;
pub fn unescape(text: impl AsRef<str>) -> Result<String, TextError> {
let text = text.as_ref();
let mut out = String::with_capacity(text.len());
let mut chars = text.chars().enumerate();
while let Some((index, c)) = chars.next() {
if c != '\\' {
out.push(c);
continue;
}
if let Some(next) = chars.next() {
match escape_chars(next.1) {
Some(c) => out.push(c),
None => {
let t = Box::from(format!("\\{}", next.1).as_ref());
return Err(TextError::UnescapeError(index, t));
}
}
}
}
Ok(out)
}
pub unsafe fn unescape_unchecked(text: impl AsRef<str>) -> String {
let text = text.as_ref();
let mut out = String::with_capacity(text.len());
let mut chars = text.chars();
while let Some(c) = chars.next() {
if c != '\\' {
out.push(c);
continue;
}
if let Some(next) = chars.next() {
match escape_chars(next) {
Some(c) => out.push(c),
None => out.push(next),
}
}
}
return out;
}
fn escape_chars(c: char) -> Option<char> {
match c {
'b' => Some('\u{0008}'),
'f' => Some('\u{000C}'),
'n' => Some('\n'),
'r' => Some('\r'),
't' => Some('\t'),
'\'' => Some('\''),
'\"' => Some('\"'),
'\\' => Some('\\'),
_ => None,
}
}
#[allow(unused_variables)]
pub fn unescape_utf8(text: impl AsRef<str>) {
unimplemented!()
}
#[allow(unused_variables)]
pub fn unescape_only(text: impl AsRef<str>, c: char) {
unimplemented!()
}
pub fn unescape_hex_chars(text: impl AsRef<str>) -> Option<String> {
unsafe { unescape_unicode_char(text.as_ref(), 16) }
}
pub fn unescape_dec_chars(text: impl AsRef<str>) -> Option<String> {
unsafe { unescape_unicode_char(text.as_ref(), 10) }
}
unsafe fn unescape_unicode_char(text: &str, radix: u32) -> Option<String> {
let mut out = String::with_capacity(text.len());
for c in text.split_whitespace() {
match u32::from_str_radix(c, radix) {
Ok(o) => out.push(transmute::<u32, char>(o)),
Err(_) => return None,
}
}
Some(out)
}