diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index c9919d92b..6efeaaeec 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -402,7 +402,7 @@ impl<'a> fmt::Display for Unexpected<'a> { Bool(b) => write!(formatter, "boolean `{}`", b), Unsigned(i) => write!(formatter, "integer `{}`", i), Signed(i) => write!(formatter, "integer `{}`", i), - Float(f) => write!(formatter, "floating point `{}`", f), + Float(f) => write!(formatter, "floating point `{}`", WithDecimalPoint(f)), Char(c) => write!(formatter, "character `{}`", c), Str(s) => write!(formatter, "string {:?}", s), Bytes(_) => write!(formatter, "byte array"), @@ -2290,3 +2290,36 @@ impl Display for OneOf { } } } + +struct WithDecimalPoint(f64); + +impl Display for WithDecimalPoint { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + struct LookForDecimalPoint<'f, 'a> { + formatter: &'f mut fmt::Formatter<'a>, + has_decimal_point: bool, + } + + impl<'f, 'a> fmt::Write for LookForDecimalPoint<'f, 'a> { + fn write_str(&mut self, fragment: &str) -> fmt::Result { + self.has_decimal_point |= fragment.contains('.'); + self.formatter.write_str(fragment) + } + + fn write_char(&mut self, ch: char) -> fmt::Result { + self.has_decimal_point |= ch == '.'; + self.formatter.write_char(ch) + } + } + + let mut writer = LookForDecimalPoint { + formatter, + has_decimal_point: false, + }; + tri!(write!(writer, "{}", self.0)); + if !writer.has_decimal_point { + tri!(formatter.write_str(".0")); + } + Ok(()) + } +} diff --git a/serde/src/lib.rs b/serde/src/lib.rs index b0756af6d..1a17a25ae 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -182,7 +182,7 @@ mod lib { pub use self::core::cmp::Reverse; pub use self::core::convert::{self, From, Into}; pub use self::core::default::{self, Default}; - pub use self::core::fmt::{self, Debug, Display}; + pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite}; pub use self::core::marker::{self, PhantomData}; pub use self::core::num::Wrapping; pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo}; diff --git a/test_suite/tests/test_de_error.rs b/test_suite/tests/test_de_error.rs index d4449fdd8..d1ea2b910 100644 --- a/test_suite/tests/test_de_error.rs +++ b/test_suite/tests/test_de_error.rs @@ -1434,7 +1434,7 @@ fn test_number_from_string() { fn test_integer_from_float() { assert_de_tokens_error::( &[Token::F32(0.0)], - "invalid type: floating point `0`, expected isize", + "invalid type: floating point `0.0`, expected isize", ); }