Skip to content

Commit 238c8fe

Browse files
bors[bot]dflemstrjaparic
authored
Merge #24
24: Add support for preserving parts of custom error messages r=japaric a=dflemstr This essentially addresses a TODO from the code Co-authored-by: David Flemström <dflemstr@spotify.com> Co-authored-by: David Flemström <david.flemstrom@gmail.com> Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2 parents dd9dcc9 + 829eac7 commit 238c8fe

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ version = "1.0.80"
2222
serde_derive = "1.0.80"
2323

2424
[features]
25+
custom-error-messages = []
2526
std = ["serde/std"]
2627

2728
[badges]

ci/script.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ main() {
1010

1111
if [ $TARGET = x86_64-unknown-linux-gnu ]; then
1212
cargo test --target $TARGET
13+
cargo test --features custom-error-messages --target $TARGET
1314

1415
return
1516
fi

src/de/mod.rs

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ pub enum Error {
7070
/// Error with a custom message that we had to discard.
7171
CustomError,
7272

73+
/// Error with a custom message that was preserved.
74+
#[cfg(feature = "custom-error-messages")]
75+
CustomErrorWithMessage(heapless::String<heapless::consts::U64>),
76+
7377
#[doc(hidden)]
7478
__Extensible,
7579
}
@@ -608,17 +612,23 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
608612
}
609613

610614
impl de::Error for Error {
611-
// We can’t alloc a String to save the msg in, so we have this less-than-useful
612-
// error as better than panicking with unreachable!. These errors can arise from
613-
// derive, such as "not enough elements in a tuple" and "missing required field".
614-
//
615-
// TODO: consider using a heapless::String to save the first n characters of this
616-
// message.
617-
fn custom<T>(_msg: T) -> Self
615+
#[cfg_attr(not(feature = "custom-error-messages"), allow(unused_variables))]
616+
fn custom<T>(msg: T) -> Self
618617
where
619618
T: fmt::Display,
620619
{
621-
Error::CustomError
620+
#[cfg(not(feature = "custom-error-messages"))]
621+
{
622+
Error::CustomError
623+
}
624+
#[cfg(feature = "custom-error-messages")]
625+
{
626+
use core::fmt::Write;
627+
628+
let mut string = heapless::String::new();
629+
write!(string, "{:.64}", msg).unwrap();
630+
Error::CustomErrorWithMessage(string)
631+
}
622632
}
623633
}
624634

@@ -659,6 +669,8 @@ impl fmt::Display for Error {
659669
}
660670
Error::TrailingComma => "JSON has a comma after the last value in an array or map.",
661671
Error::CustomError => "JSON does not match deserializer’s expected format.",
672+
#[cfg(feature = "custom-error-messages")]
673+
Error::CustomErrorWithMessage(msg) => msg.as_str(),
662674
_ => "Invalid JSON",
663675
}
664676
)
@@ -867,6 +879,7 @@ mod tests {
867879
}
868880

869881
#[test]
882+
#[cfg(not(feature = "custom-error-messages"))]
870883
fn struct_tuple() {
871884
#[derive(Debug, Deserialize, PartialEq)]
872885
struct Xy(i8, i8);
@@ -885,6 +898,28 @@ mod tests {
885898
);
886899
}
887900

901+
#[test]
902+
#[cfg(feature = "custom-error-messages")]
903+
fn struct_tuple() {
904+
#[derive(Debug, Deserialize, PartialEq)]
905+
struct Xy(i8, i8);
906+
907+
assert_eq!(crate::from_str(r#"[10, 20]"#), Ok(Xy(10, 20)));
908+
assert_eq!(crate::from_str(r#"[10, -20]"#), Ok(Xy(10, -20)));
909+
910+
// wrong number of args
911+
assert_eq!(
912+
crate::from_str::<Xy>(r#"[10]"#),
913+
Err(crate::de::Error::CustomErrorWithMessage(
914+
"invalid length 1, expected tuple struct Xy with 2 elements".into()
915+
))
916+
);
917+
assert_eq!(
918+
crate::from_str::<Xy>(r#"[10, 20, 30]"#),
919+
Err(crate::de::Error::TrailingCharacters)
920+
);
921+
}
922+
888923
#[test]
889924
fn ignoring_extra_fields() {
890925
#[derive(Debug, Deserialize, PartialEq)]
@@ -937,6 +972,28 @@ mod tests {
937972
);
938973
}
939974

975+
#[test]
976+
#[cfg(feature = "custom-error-messages")]
977+
fn preserve_short_error_message() {
978+
use serde::de::Error;
979+
assert_eq!(
980+
crate::de::Error::custom("something bad happened"),
981+
crate::de::Error::CustomErrorWithMessage("something bad happened".into())
982+
);
983+
}
984+
985+
#[test]
986+
#[cfg(feature = "custom-error-messages")]
987+
fn truncate_error_message() {
988+
use serde::de::Error;
989+
assert_eq!(
990+
crate::de::Error::custom("0123456789012345678901234567890123456789012345678901234567890123 <- after here the message should be truncated"),
991+
crate::de::Error::CustomErrorWithMessage(
992+
"0123456789012345678901234567890123456789012345678901234567890123".into()
993+
)
994+
);
995+
}
996+
940997
// See https://iot.mozilla.org/wot/#thing-resource
941998
#[test]
942999
#[ignore]

0 commit comments

Comments
 (0)