Skip to content

Commit d090e94

Browse files
Refactor try_unescape in macro-support (#3292)
* Add unit test for fix_unescape * Refactor try_unescape in macro-support
1 parent 0f6621a commit d090e94

File tree

2 files changed

+32
-36
lines changed

2 files changed

+32
-36
lines changed

.github/workflows/main.yml

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ jobs:
121121
- run: cargo test -p wasm-bindgen-cli-support
122122
- run: cargo test -p wasm-bindgen-cli
123123
- run: cargo test -p wasm-bindgen-externref-xform
124+
- run: cargo test -p wasm-bindgen-macro-support
124125
- run: cargo test -p wasm-bindgen-multi-value-xform
125126
- run: cargo test -p wasm-bindgen-wasm-interpreter
126127
- run: cargo test -p wasm-bindgen-futures

crates/macro-support/src/parser.rs

+31-36
Original file line numberDiff line numberDiff line change
@@ -1545,25 +1545,13 @@ fn extract_doc_comments(attrs: &[syn::Attribute]) -> Vec<String> {
15451545
}
15461546

15471547
// Unescapes a quoted string. char::escape_debug() was used to escape the text.
1548-
fn try_unescape(s: &str) -> Option<String> {
1549-
if s.is_empty() {
1550-
return Some(String::new());
1551-
}
1548+
fn try_unescape(mut s: &str) -> Option<String> {
1549+
s = s.strip_prefix('"').unwrap_or(s);
1550+
s = s.strip_suffix('"').unwrap_or(s);
15521551
let mut result = String::with_capacity(s.len());
15531552
let mut chars = s.chars();
1554-
for i in 0.. {
1555-
let c = match chars.next() {
1556-
Some(c) => c,
1557-
None => {
1558-
if result.ends_with('"') {
1559-
result.pop();
1560-
}
1561-
return Some(result);
1562-
}
1563-
};
1564-
if i == 0 && c == '"' {
1565-
// ignore it
1566-
} else if c == '\\' {
1553+
while let Some(c) = chars.next() {
1554+
if c == '\\' {
15671555
let c = chars.next()?;
15681556
match c {
15691557
't' => result.push('\t'),
@@ -1586,30 +1574,17 @@ fn try_unescape(s: &str) -> Option<String> {
15861574
result.push(c);
15871575
}
15881576
}
1589-
None
1577+
Some(result)
15901578
}
15911579

15921580
fn unescape_unicode(chars: &mut Chars) -> Option<(char, char)> {
15931581
let mut value = 0;
1594-
for i in 0..7 {
1595-
let c = chars.next()?;
1596-
let num = if c >= '0' && c <= '9' {
1597-
c as u32 - '0' as u32
1598-
} else if c >= 'a' && c <= 'f' {
1599-
c as u32 - 'a' as u32 + 10
1600-
} else if c >= 'A' && c <= 'F' {
1601-
c as u32 - 'A' as u32 + 10
1602-
} else {
1603-
if i == 0 {
1604-
return None;
1605-
}
1606-
let decoded = char::from_u32(value)?;
1607-
return Some((decoded, c));
1608-
};
1609-
if i >= 6 {
1610-
return None;
1582+
for (i, c) in chars.enumerate() {
1583+
match (i, c.to_digit(16)) {
1584+
(0..=5, Some(num)) => value = (value << 4) | num,
1585+
(1.., None) => return Some((char::from_u32(value)?, c)),
1586+
_ => break,
16111587
}
1612-
value = (value << 4) | num;
16131588
}
16141589
None
16151590
}
@@ -1713,3 +1688,23 @@ pub fn link_to(opts: BindgenAttrs) -> Result<ast::LinkToModule, Diagnostic> {
17131688
program.linked_modules.push(module);
17141689
Ok(ast::LinkToModule(program))
17151690
}
1691+
1692+
#[cfg(test)]
1693+
mod tests {
1694+
#[test]
1695+
fn test_try_unescape() {
1696+
use super::try_unescape;
1697+
assert_eq!(try_unescape("hello").unwrap(), "hello");
1698+
assert_eq!(try_unescape("\"hello").unwrap(), "hello");
1699+
assert_eq!(try_unescape("hello\"").unwrap(), "hello");
1700+
assert_eq!(try_unescape("\"hello\"").unwrap(), "hello");
1701+
assert_eq!(try_unescape("hello\\\\").unwrap(), "hello\\");
1702+
assert_eq!(try_unescape("hello\\n").unwrap(), "hello\n");
1703+
assert_eq!(try_unescape("hello\\u"), None);
1704+
assert_eq!(try_unescape("hello\\u{"), None);
1705+
assert_eq!(try_unescape("hello\\u{}"), None);
1706+
assert_eq!(try_unescape("hello\\u{0}").unwrap(), "hello\0");
1707+
assert_eq!(try_unescape("hello\\u{000000}").unwrap(), "hello\0");
1708+
assert_eq!(try_unescape("hello\\u{0000000}"), None);
1709+
}
1710+
}

0 commit comments

Comments
 (0)