Skip to content

Commit 35765f4

Browse files
committed
The default unescaping buffer length is now 0, not 128, with an error case specifying if a buffer is required
1 parent c6e7e38 commit 35765f4

File tree

1 file changed

+77
-27
lines changed

1 file changed

+77
-27
lines changed

src/de/mod.rs

Lines changed: 77 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ pub enum Error {
7070
/// Invalid String Escape Sequence
7171
InvalidEscapeSequence,
7272

73+
/// Unescaping and Escaped String requires a buffer
74+
EscapedStringRequiresBuffer,
75+
7376
/// Escaped String length exceeds buffer size
7477
EscapedStringIsTooLong,
7578

@@ -850,7 +853,13 @@ pub fn from_slice<'a, T>(v: &'a [u8]) -> Result<(T, usize)>
850853
where
851854
T: de::Deserialize<'a>,
852855
{
853-
from_slice_using_string_unescape_buffer(v, &mut [0; 128])
856+
from_slice_using_string_unescape_buffer(v, &mut []).map_err(|error| {
857+
if let Error::EscapedStringIsTooLong = error {
858+
Error::EscapedStringRequiresBuffer
859+
} else {
860+
error
861+
}
862+
})
854863
}
855864

856865
/// Deserializes an instance of type T from a string of JSON text, using the provided buffer to unescape strings
@@ -937,18 +946,24 @@ mod tests {
937946

938947
#[test]
939948
fn char() {
940-
assert_eq!(crate::from_str(r#""n""#), Ok(('n', 3)));
941-
assert_eq!(crate::from_str(r#""\"""#), Ok(('"', 4)));
942-
assert_eq!(crate::from_str(r#""\\""#), Ok(('\\', 4)));
943-
assert_eq!(crate::from_str(r#""/""#), Ok(('/', 3)));
944-
assert_eq!(crate::from_str(r#""\b""#), Ok(('\x08', 4)));
945-
assert_eq!(crate::from_str(r#""\f""#), Ok(('\x0C', 4)));
946-
assert_eq!(crate::from_str(r#""\n""#), Ok(('\n', 4)));
947-
assert_eq!(crate::from_str(r#""\r""#), Ok(('\r', 4)));
948-
assert_eq!(crate::from_str(r#""\t""#), Ok(('\t', 4)));
949-
assert_eq!(crate::from_str(r#""\u000b""#), Ok(('\x0B', 8)));
950-
assert_eq!(crate::from_str(r#""\u000B""#), Ok(('\x0B', 8)));
951-
assert_eq!(crate::from_str(r#""Σ""#), Ok(('Σ', 4)));
949+
fn from_str_test<'de, T: serde::Deserialize<'de>>(
950+
s: &'de str,
951+
) -> super::Result<(T, usize)> {
952+
crate::from_str_using_string_unescape_buffer(s, &mut [0; 8])
953+
}
954+
955+
assert_eq!(from_str_test(r#""n""#), Ok(('n', 3)));
956+
assert_eq!(from_str_test(r#""\"""#), Ok(('"', 4)));
957+
assert_eq!(from_str_test(r#""\\""#), Ok(('\\', 4)));
958+
assert_eq!(from_str_test(r#""/""#), Ok(('/', 3)));
959+
assert_eq!(from_str_test(r#""\b""#), Ok(('\x08', 4)));
960+
assert_eq!(from_str_test(r#""\f""#), Ok(('\x0C', 4)));
961+
assert_eq!(from_str_test(r#""\n""#), Ok(('\n', 4)));
962+
assert_eq!(from_str_test(r#""\r""#), Ok(('\r', 4)));
963+
assert_eq!(from_str_test(r#""\t""#), Ok(('\t', 4)));
964+
assert_eq!(from_str_test(r#""\u000b""#), Ok(('\x0B', 8)));
965+
assert_eq!(from_str_test(r#""\u000B""#), Ok(('\x0B', 8)));
966+
assert_eq!(from_str_test(r#""Σ""#), Ok(('Σ', 4)));
952967
}
953968

954969
#[test]
@@ -963,41 +978,76 @@ mod tests {
963978
core::str::FromStr::from_str(s).expect("Failed to create test string")
964979
}
965980

981+
fn from_str_test<'de, T: serde::Deserialize<'de>>(
982+
s: &'de str,
983+
) -> super::Result<(T, usize)> {
984+
crate::from_str_using_string_unescape_buffer(s, &mut [0; 16])
985+
}
986+
966987
// escaped " in the string content
988+
assert_eq!(from_str_test(r#" "foo\"bar" "#), Ok((s(r#"foo"bar"#), 12)));
967989
assert_eq!(
968-
crate::from_str(r#" "foo\"bar" "#),
969-
Ok((s(r#"foo"bar"#), 12))
970-
);
971-
assert_eq!(
972-
crate::from_str(r#" "foo\\\"bar" "#),
990+
from_str_test(r#" "foo\\\"bar" "#),
973991
Ok((s(r#"foo\"bar"#), 14))
974992
);
975993
assert_eq!(
976-
crate::from_str(r#" "foo\"\"bar" "#),
994+
from_str_test(r#" "foo\"\"bar" "#),
977995
Ok((s(r#"foo""bar"#), 14))
978996
);
979-
assert_eq!(crate::from_str(r#" "\"bar" "#), Ok((s(r#""bar"#), 9)));
980-
assert_eq!(crate::from_str(r#" "foo\"" "#), Ok((s(r#"foo""#), 9)));
981-
assert_eq!(crate::from_str(r#" "\"" "#), Ok((s(r#"""#), 6)));
997+
assert_eq!(from_str_test(r#" "\"bar" "#), Ok((s(r#""bar"#), 9)));
998+
assert_eq!(from_str_test(r#" "foo\"" "#), Ok((s(r#"foo""#), 9)));
999+
assert_eq!(from_str_test(r#" "\"" "#), Ok((s(r#"""#), 6)));
9821000

9831001
// non-excaped " preceded by backslashes
9841002
assert_eq!(
985-
crate::from_str(r#" "foo bar\\" "#),
1003+
from_str_test(r#" "foo bar\\" "#),
9861004
Ok((s(r#"foo bar\"#), 13))
9871005
);
9881006
assert_eq!(
989-
crate::from_str(r#" "foo bar\\\\" "#),
1007+
from_str_test(r#" "foo bar\\\\" "#),
9901008
Ok((s(r#"foo bar\\"#), 15))
9911009
);
9921010
assert_eq!(
993-
crate::from_str(r#" "foo bar\\\\\\" "#),
1011+
from_str_test(r#" "foo bar\\\\\\" "#),
9941012
Ok((s(r#"foo bar\\\"#), 17))
9951013
);
9961014
assert_eq!(
997-
crate::from_str(r#" "foo bar\\\\\\\\" "#),
1015+
from_str_test(r#" "foo bar\\\\\\\\" "#),
9981016
Ok((s(r#"foo bar\\\\"#), 19))
9991017
);
1000-
assert_eq!(crate::from_str(r#" "\\" "#), Ok((s(r#"\"#), 6)));
1018+
assert_eq!(from_str_test(r#" "\\" "#), Ok((s(r#"\"#), 6)));
1019+
}
1020+
1021+
#[test]
1022+
fn tuple_of_str() {
1023+
fn s(s: &'static str) -> heapless::String<1024> {
1024+
core::str::FromStr::from_str(s).expect("Failed to create test string")
1025+
}
1026+
1027+
fn from_str_test<'de, T: serde::Deserialize<'de>>(
1028+
s: &'de str,
1029+
) -> super::Result<(T, usize)> {
1030+
crate::from_str_using_string_unescape_buffer(s, &mut [0; 16])
1031+
}
1032+
1033+
// The combined length of the first and third strings are longer than the buffer, but that's OK,
1034+
// as escaped strings are deserialized into owned str types, e.g. `heapless::String`.
1035+
// The second string is longer than the buffer, but that's OK, as strings which aren't escaped
1036+
// are deserialized as str's borrowed from the input
1037+
1038+
assert_eq!(
1039+
from_str_test(
1040+
r#" [ "AAAAAAAAAAAA\n", "BBBBBBBBBBBBBBBBBBBBBBBB", "CCCCCCCCCCCC\n" ] "#
1041+
),
1042+
Ok((
1043+
(
1044+
s("AAAAAAAAAAAA\n"),
1045+
"BBBBBBBBBBBBBBBBBBBBBBBB",
1046+
s("CCCCCCCCCCCC\n")
1047+
),
1048+
68
1049+
))
1050+
);
10011051
}
10021052

10031053
#[test]

0 commit comments

Comments
 (0)