Skip to content

Commit 319bb80

Browse files
Merge pull request RustPython#843 from jgirardet/parsenew
support bytes creation from hex and ascii
2 parents ae7058f + eb2d0b0 commit 319bb80

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

parser/src/lexer.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ where
542542
let tok = if is_bytes {
543543
if string_content.is_ascii() {
544544
Tok::Bytes {
545-
value: string_content.as_bytes().to_vec(),
545+
value: lex_byte(string_content)?,
546546
}
547547
} else {
548548
return Err(LexicalError::StringError);
@@ -1133,6 +1133,54 @@ where
11331133
}
11341134
}
11351135

1136+
fn lex_byte(s: String) -> Result<Vec<u8>, LexicalError> {
1137+
let mut res = vec![];
1138+
let mut escape = false; //flag if previous was \
1139+
let mut hex_on = false; // hex mode on or off
1140+
let mut hex_value = String::new();
1141+
1142+
for c in s.chars() {
1143+
if hex_on {
1144+
if c.is_ascii_hexdigit() {
1145+
if hex_value.is_empty() {
1146+
hex_value.push(c);
1147+
continue;
1148+
} else {
1149+
hex_value.push(c);
1150+
res.push(u8::from_str_radix(&hex_value, 16).unwrap());
1151+
hex_on = false;
1152+
hex_value.clear();
1153+
}
1154+
} else {
1155+
return Err(LexicalError::StringError);
1156+
}
1157+
} else {
1158+
match (c, escape) {
1159+
('\\', true) => res.push(b'\\'),
1160+
('\\', false) => {
1161+
escape = true;
1162+
continue;
1163+
}
1164+
('x', true) => hex_on = true,
1165+
('x', false) => res.push(b'x'),
1166+
('t', true) => res.push(b'\t'),
1167+
('t', false) => res.push(b't'),
1168+
('n', true) => res.push(b'\n'),
1169+
('n', false) => res.push(b'n'),
1170+
('r', true) => res.push(b'\r'),
1171+
('r', false) => res.push(b'r'),
1172+
(x, true) => {
1173+
res.push(b'\\');
1174+
res.push(x as u8);
1175+
}
1176+
(x, false) => res.push(x as u8),
1177+
}
1178+
escape = false;
1179+
}
1180+
}
1181+
Ok(res)
1182+
}
1183+
11361184
#[cfg(test)]
11371185
mod tests {
11381186
use super::{make_tokenizer, NewlineHandler, Tok};
@@ -1520,4 +1568,28 @@ mod tests {
15201568
test_string_continuation_mac_eol: MAC_EOL,
15211569
test_string_continuation_unix_eol: UNIX_EOL,
15221570
}
1571+
1572+
#[test]
1573+
fn test_byte() {
1574+
// single quote
1575+
let all = r##"b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'"##;
1576+
let source = String::from(all);
1577+
let tokens = lex_source(&source);
1578+
let res = (0..=255).collect::<Vec<u8>>();
1579+
assert_eq!(tokens, vec![Tok::Bytes { value: res }]);
1580+
1581+
// double quote
1582+
let all = r##"b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff""##;
1583+
let source = String::from(all);
1584+
let tokens = lex_source(&source);
1585+
let res = (0..=255).collect::<Vec<u8>>();
1586+
assert_eq!(tokens, vec![Tok::Bytes { value: res }]);
1587+
1588+
// backslash doesnt escape
1589+
let all = r##"b"omkmok\Xaa""##;
1590+
let source = String::from(all);
1591+
let tokens = lex_source(&source);
1592+
let res = vec![111, 109, 107, 109, 111, 107, 92, 88, 97, 97];
1593+
assert_eq!(tokens, vec![Tok::Bytes { value: res }]);
1594+
}
15231595
}

tests/snippets/bytes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
with assertRaises(TypeError):
1111
bytes("bla")
1212

13+
assert b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" == bytes(range(0,256))
14+
assert b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' == bytes(range(0,256))
15+
assert b"omkmok\Xaa" == bytes([111, 109, 107, 109, 111, 107, 92, 88, 97, 97])
16+
1317

1418
a = b"abcd"
1519
b = b"ab"

0 commit comments

Comments
 (0)