diff --git a/CHANGELOG.md b/CHANGELOG.md index 29749eed..3ffb9111 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ HEAD * Fix `call of overloaded 'String(const char*, int)' is ambiguous` * Fix `JsonString` operator `==` and `!=` for non-zero-terminated string * Fix `-Wsign-conversion` on GCC 8 (issue #1715) +* MessagePack: serialize round floats as integers (issue #1718) v6.19.2 (2022-02-14) ------- diff --git a/extras/tests/MsgPackSerializer/serializeVariant.cpp b/extras/tests/MsgPackSerializer/serializeVariant.cpp index 7817946e..1fd8ba18 100644 --- a/extras/tests/MsgPackSerializer/serializeVariant.cpp +++ b/extras/tests/MsgPackSerializer/serializeVariant.cpp @@ -144,4 +144,18 @@ TEST_CASE("serialize MsgPack value") { checkVariant(serialized("\xDA\xFF\xFF"), "\xDA\xFF\xFF"); checkVariant(serialized("\xDB\x00\x01\x00\x00", 5), "\xDB\x00\x01\x00\x00"); } + + SECTION("serialize round double as integer") { // Issue #1718 + checkVariant(-32768.0, "\xD1\x80\x00"); + checkVariant(-129.0, "\xD1\xFF\x7F"); + checkVariant(-128.0, "\xD0\x80"); + checkVariant(-33.0, "\xD0\xDF"); + checkVariant(-32.0, "\xE0"); + checkVariant(-1.0, "\xFF"); + checkVariant(0.0, "\x00"); + checkVariant(127.0, "\x7F"); + checkVariant(128.0, "\xCC\x80"); + checkVariant(255.0, "\xCC\xFF"); + checkVariant(256.0, "\xCD\x01\x00"); + } } diff --git a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp index 51e929be..a1053f0a 100644 --- a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp @@ -23,6 +23,11 @@ class MsgPackSerializer : public Visitor { template typename enable_if::type visitFloat(T value32) { + if (canConvertNumber(value32)) { + Integer truncatedValue = Integer(value32); + if (value32 == T(truncatedValue)) + return visitSignedInteger(truncatedValue); + } writeByte(0xCA); writeInteger(value32); return bytesWritten(); @@ -32,13 +37,10 @@ class MsgPackSerializer : public Visitor { ARDUINOJSON_NO_SANITIZE("float-cast-overflow") typename enable_if::type visitFloat(T value64) { float value32 = float(value64); - if (value32 == value64) { - writeByte(0xCA); - writeInteger(value32); - } else { - writeByte(0xCB); - writeInteger(value64); - } + if (value32 == value64) + return visitFloat(value32); + writeByte(0xCB); + writeInteger(value64); return bytesWritten(); }