Skip to content

Commit f254d4c

Browse files
committed
Rewrite libcore's UTF-8 validation for performance
1 parent 9dee4e4 commit f254d4c

File tree

3 files changed

+594
-132
lines changed

3 files changed

+594
-132
lines changed

library/alloc/tests/str.rs

Lines changed: 268 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::assert_matches::assert_matches;
22
use std::borrow::Cow;
33
use std::cmp::Ordering::{Equal, Greater, Less};
4-
use std::str::{from_utf8, from_utf8_unchecked};
4+
use std::str::{from_utf8, from_utf8_unchecked, Utf8Error};
55

66
#[test]
77
fn test_le() {
@@ -983,6 +983,250 @@ fn from_utf8_error() {
983983
test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
984984
}
985985

986+
const fn utf8_error_eq(e: &Utf8Error, valid: usize, err_len: Option<usize>) -> bool {
987+
e.valid_up_to() == valid
988+
&& match (err_len, e.error_len()) {
989+
(Some(a), Some(b)) => a == b,
990+
(None, None) => true,
991+
_ => false,
992+
}
993+
}
994+
995+
#[test]
996+
fn from_utf8_error_offset() {
997+
const N: usize = if cfg!(miri) { 8 } else { 64 };
998+
999+
#[track_caller]
1000+
fn check(input: &[u8], valid: usize, err_len: Option<usize>) {
1001+
let mut buf = Vec::with_capacity(input.len() + N * N * N * 4);
1002+
for i in 0..N {
1003+
for j in 0..N {
1004+
buf.clear();
1005+
buf.extend(core::iter::repeat(b'a').take(i));
1006+
buf.extend(core::iter::repeat(*b"\xE6\x88\x91").take(i).flat_map(|n| n));
1007+
let bump = buf.len();
1008+
buf.extend_from_slice(input);
1009+
1010+
assert!(
1011+
utf8_error_eq(&from_utf8(&buf).unwrap_err(), bump + valid, err_len),
1012+
"offset ({i}, {j}, _): on {input:?} ({buf:?})"
1013+
);
1014+
for k in 0..N {
1015+
if k != 0 {
1016+
buf.extend(*b"\xD0\xB6")
1017+
}
1018+
let error = from_utf8(&buf).unwrap_err();
1019+
let real_err = from_utf8(&buf).unwrap_err();
1020+
assert_eq!(
1021+
error, real_err,
1022+
"(vs ref) offset ({i}, {j}, {k}): on {input:?} ({buf:?})"
1023+
);
1024+
}
1025+
}
1026+
}
1027+
}
1028+
check(b"A\xC3\xA9 \xFF ", 4, Some(1));
1029+
check(b"A\xC3\xA9 \x80 ", 4, Some(1));
1030+
check(b"A\xC3\xA9 \xC1 ", 4, Some(1));
1031+
check(b"A\xC3\xA9 \xC1", 4, Some(1));
1032+
check(b"A\xC3\xA9 \xC2", 4, None);
1033+
check(b"A\xC3\xA9 \xC2 ", 4, Some(1));
1034+
check(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
1035+
check(b"A\xC3\xA9 \xE0", 4, None);
1036+
check(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
1037+
check(b"A\xC3\xA9 \xE0\xA0", 4, None);
1038+
check(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
1039+
check(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
1040+
check(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
1041+
check(b"A\xC3\xA9 \xF1", 4, None);
1042+
check(b"A\xC3\xA9 \xF1\x80", 4, None);
1043+
check(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
1044+
check(b"A\xC3\xA9 \xF1 ", 4, Some(1));
1045+
check(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
1046+
check(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
1047+
check(b"\xc3\x28", 0, Some(1));
1048+
check(b"\xa0\xa1", 0, Some(1));
1049+
check(b"\xe2\x28\xa1", 0, Some(1));
1050+
check(b"\xe2\x82\x28", 0, Some(2));
1051+
check(b"\xf0\x28\x8c\xbc", 0, Some(1));
1052+
check(b"\xf0\x90\x28\xbc", 0, Some(2));
1053+
check(b"\xf0\x28\x8c\x28", 0, Some(1));
1054+
check(b"\xc0\x9f", 0, Some(1));
1055+
check(b"\xf5\xff\xff\xff", 0, Some(1));
1056+
check(b"\xed\xa0\x81", 0, Some(1));
1057+
check(b"\xf8\x90\x80\x80\x80", 0, Some(1));
1058+
check(b"123456789012345\xed", 15, None);
1059+
check(b"123456789012345\xf1", 15, None);
1060+
check(b"123456789012345\xc2", 15, None);
1061+
check(b"\xC2\x7F", 0, Some(1));
1062+
check(b"\xce", 0, None);
1063+
check(b"\xce\xba\xe1", 2, None);
1064+
check(b"\xce\xba\xe1\xbd", 2, None);
1065+
check(b"\xce\xba\xe1\xbd\xb9\xcf", 5, None);
1066+
check(b"\xce\xba\xe1\xbd\xb9\xcf\x83\xce", 7, None);
1067+
check(b"\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce", 9, None);
1068+
check(b"\xdf", 0, None);
1069+
check(b"\xef\xbf", 0, None);
1070+
check(b"\x80", 0, Some(1));
1071+
check(b"\x91\x85\x95\x9e", 0, Some(1));
1072+
check(b"\x6c\x02\x8e\x18", 2, Some(1));
1073+
check(b"\xFF", 0, Some(1));
1074+
check(b"a\xFF", 1, Some(1));
1075+
check(b"\xCE\xB2\xFF", 2, Some(1));
1076+
check(b"\xE2\x98\x83\xFF", 3, Some(1));
1077+
check(b"\xF0\x9D\x9D\xB1\xFF", 4, Some(1));
1078+
check(b"\xCE\xF0", 0, Some(1));
1079+
check(b"\xE2\x98\xF0", 0, Some(2));
1080+
check(b"\xF0\x9D\x9D\xF0", 0, Some(3));
1081+
check(b"\xF0\x82\x82\xAC", 0, Some(1));
1082+
check(b"a\xF0\x82\x82\xAC", 1, Some(1));
1083+
check(b"\xE2\x98\x83\xF0\x82\x82\xAC", 3, Some(1));
1084+
check(b"\xED\xA0\x80", 0, Some(1));
1085+
check(b"\xE2\x98\x83\xED\xA0\x80", 3, Some(1));
1086+
check(b"\xE2\x98\x83\xCE\xE2\x98\x83", 3, Some(1));
1087+
check(b"\xCEa", 0, Some(1));
1088+
check(b"a\xCEa", 1, Some(1));
1089+
check(b"\xE2\x98\x83\xE2\x98\xE2\x98\x83", 3, Some(2));
1090+
// check(b"\xF0\x9D\x9Ca", 3, Some(2));
1091+
check(b"\xE2\x98a", 0, Some(2));
1092+
check(b"a\xE2\x98a", 1, Some(2));
1093+
check(b"\xF0\x9D\x9Ca", 0, Some(3));
1094+
check(b"a\xF0\x9D\x9Ca", 1, Some(3));
1095+
check(b"\xF0\x9D\x9C\xB1\xF0\x9D\x9C\xE2\x98\x83", 4, Some(3));
1096+
check(b"foobar\xF1\x80\x80quux", 6, Some(3));
1097+
check(b"\xCE", 0, None);
1098+
check(b"a\xCE", 1, None);
1099+
check(b"\xE2\x98\x83\xCE", 3, None);
1100+
check(b"\xE2\x98", 0, None);
1101+
check(b"a\xE2\x98", 1, None);
1102+
check(b"\xE2\x98\x83\xE2\x98", 3, None);
1103+
check(b"\xF0\x9D\x9C", 0, None);
1104+
check(b"a\xF0\x9D\x9C", 1, None);
1105+
check(b"\xF0\x9D\x9C\xB1\xF0\x9D\x9C", 4, None);
1106+
check(b"\xe2\x98\x83\xce\xb2\xe3\x83\x84\xFF", 8, Some(1));
1107+
}
1108+
1109+
#[test]
1110+
fn utf8_error_cases_const() {
1111+
macro_rules! expect_utf8_error {
1112+
($bytes:expr, $valid:expr, $elen:expr $(,)?) => {{
1113+
assert!(utf8_error_eq(&from_utf8($bytes).unwrap_err(), $valid, $elen));
1114+
const _: () = match from_utf8($bytes) {
1115+
Ok(_) => panic!(concat!("shouldn't pass: ", stringify!($bytes))),
1116+
Err(e) => assert!(utf8_error_eq(&e, $valid, $elen)),
1117+
};
1118+
}};
1119+
}
1120+
expect_utf8_error!(b"\xc3\x28", 0, Some(1));
1121+
expect_utf8_error!(b"\xa0\xa1", 0, Some(1));
1122+
expect_utf8_error!(b"\xe2\x28\xa1", 0, Some(1));
1123+
expect_utf8_error!(b"\xe2\x82\x28", 0, Some(2));
1124+
expect_utf8_error!(b"\xf0\x28\x8c\xbc", 0, Some(1));
1125+
expect_utf8_error!(b"\xf0\x90\x28\xbc", 0, Some(2));
1126+
expect_utf8_error!(b"\xf0\x28\x8c\x28", 0, Some(1));
1127+
expect_utf8_error!(b"\xc0\x9f", 0, Some(1));
1128+
expect_utf8_error!(b"\xf5\xff\xff\xff", 0, Some(1));
1129+
expect_utf8_error!(b"\xed\xa0\x81", 0, Some(1));
1130+
expect_utf8_error!(b"\xf8\x90\x80\x80\x80", 0, Some(1));
1131+
expect_utf8_error!(b"123456789012345\xed", 15, None);
1132+
expect_utf8_error!(b"123456789012345\xf1", 15, None);
1133+
expect_utf8_error!(b"123456789012345\xc2", 15, None);
1134+
expect_utf8_error!(b"\xC2\x7F", 0, Some(1));
1135+
expect_utf8_error!(b"\xce", 0, None);
1136+
expect_utf8_error!(b"\xce\xba\xe1", 2, None);
1137+
expect_utf8_error!(b"\xce\xba\xe1\xbd", 2, None);
1138+
expect_utf8_error!(b"\xce\xba\xe1\xbd\xb9\xcf", 5, None);
1139+
expect_utf8_error!(b"\xce\xba\xe1\xbd\xb9\xcf\x83\xce", 7, None);
1140+
expect_utf8_error!(b"\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce", 9, None);
1141+
expect_utf8_error!(b"\xdf", 0, None);
1142+
expect_utf8_error!(b"\xef\xbf", 0, None);
1143+
expect_utf8_error!(b"\x80", 0, Some(1));
1144+
expect_utf8_error!(b"\x91\x85\x95\x9e", 0, Some(1));
1145+
expect_utf8_error!(b"\x6c\x02\x8e\x18", 2, Some(1));
1146+
expect_utf8_error!(
1147+
&[
1148+
0x25, 0x5b, 0x6e, 0x2c, 0x32, 0x2c, 0x5b, 0x5b, 0x33, 0x2c, 0x34, 0x2c, 0x05, 0x29,
1149+
0x2c, 0x33, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1150+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1151+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1152+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1153+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x5b, 0x5b,
1154+
0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
1155+
0x5b, 0x5d, 0x2c, 0x35, 0x2e, 0x33, 0x2c, 0x39, 0x2e, 0x33, 0x2c, 0x37, 0x2e, 0x33,
1156+
0x2c, 0x39, 0x2e, 0x34, 0x2c, 0x37, 0x2e, 0x33, 0x2c, 0x39, 0x2e, 0x33, 0x2c, 0x37,
1157+
0x2e, 0x33, 0x2c, 0x39, 0x2e, 0x34, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d,
1158+
0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1159+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1160+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01,
1161+
0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1162+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1163+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23, 0x0a, 0x01, 0x01, 0x01, 0x01, 0x01,
1164+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1165+
0x01, 0x01, 0x01, 0x01, 0x7e, 0x7e, 0x0a, 0x0a, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1166+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1167+
0x01, 0x01, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
1168+
0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5d, 0x2c, 0x37, 0x2e, 0x33, 0x2c, 0x39, 0x2e, 0x33,
1169+
0x2c, 0x37, 0x2e, 0x33, 0x2c, 0x39, 0x2e, 0x34, 0x2c, 0x37, 0x2e, 0x33, 0x2c, 0x39,
1170+
0x2e, 0x33, 0x2c, 0x37, 0x2e, 0x33, 0x2c, 0x39, 0x2e, 0x34, 0x5d, 0x5d, 0x5d, 0x5d,
1171+
0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x01, 0x01, 0x80,
1172+
0x01, 0x01, 0x01, 0x79, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1173+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1174+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1175+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1176+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1177+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1178+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1179+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1180+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1181+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1182+
0x01,
1183+
],
1184+
335,
1185+
Some(1),
1186+
);
1187+
expect_utf8_error!(
1188+
&[
1189+
0x5bu8, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
1190+
0x5b, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1191+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1192+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1193+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1194+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1195+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1196+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1197+
0x01, 0x01, 0x01, 0x01, b'0', 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1198+
0x01, 0x01,
1199+
],
1200+
15,
1201+
Some(1),
1202+
);
1203+
expect_utf8_error!(
1204+
&[
1205+
0x20, 0x0b, 0x01, 0x01, 0x01, 0x64, 0x3a, 0x64, 0x3a, 0x64, 0x3a, 0x5b, 0x5b, 0x5b,
1206+
0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
1207+
0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
1208+
0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x30, 0x01, 0x01, 0x01,
1209+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1210+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1211+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1212+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1213+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1214+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1215+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1216+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1217+
0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1218+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1219+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1220+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1221+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1222+
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
1223+
0x01, 0x01, 0x01, 0x01, 0x01u8,
1224+
],
1225+
172,
1226+
Some(1),
1227+
);
1228+
}
1229+
9861230
#[test]
9871231
fn test_as_bytes() {
9881232
// no null
@@ -996,6 +1240,29 @@ fn test_as_bytes() {
9961240
assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
9971241
}
9981242

1243+
#[test]
1244+
#[cfg(not(miri))]
1245+
fn from_utf8_all_chars() {
1246+
for i in 0..(0x10FFFF + 1) {
1247+
let Some(cp) = char::from_u32(i) else {
1248+
continue;
1249+
};
1250+
let mut buf = [0; 4];
1251+
let s: &str = cp.encode_utf8(&mut buf);
1252+
assert_eq!(Ok(s), from_utf8(s.as_bytes()));
1253+
}
1254+
}
1255+
1256+
#[test]
1257+
fn test_multi() {
1258+
assert!(from_utf8(b"abc").is_ok());
1259+
assert!(from_utf8(b"a\xE2\x98\x83a").is_ok());
1260+
assert!(from_utf8(b"a\xF0\x9D\x9C\xB7a").is_ok());
1261+
assert!(from_utf8(b"\xE2\x98\x83\xF0\x9D\x9C\xB7").is_ok());
1262+
assert!(from_utf8(b"a\xE2\x98\x83a\xF0\x9D\x9C\xB7a").is_ok());
1263+
assert!(from_utf8(b"\xEF\xBF\xBD\xE2\x98\x83\xEF\xBF\xBD").is_ok());
1264+
}
1265+
9991266
#[test]
10001267
#[should_panic]
10011268
fn test_as_bytes_fail() {

0 commit comments

Comments
 (0)