mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-23 15:27:30 +02:00
Add support for MsgPack extension
This commit is contained in:
@ -5,7 +5,8 @@ HEAD
|
|||||||
----
|
----
|
||||||
|
|
||||||
* Add `ARDUINOJSON_STRING_LENGTH_SIZE` to the namespace name
|
* Add `ARDUINOJSON_STRING_LENGTH_SIZE` to the namespace name
|
||||||
* Add MsgPack bin8/bin16/bin32 support (PR #2078 by @Sanae6)
|
* Add support for MsgPack binary (PR #2078 by @Sanae6)
|
||||||
|
* Add support for MsgPack extension
|
||||||
* Make string support even more generic (PR #2084 by @d-a-v)
|
* Make string support even more generic (PR #2084 by @d-a-v)
|
||||||
* Optimize `deserializeMsgPack()`
|
* Optimize `deserializeMsgPack()`
|
||||||
* Allow using a `JsonVariant` as a key or index (issue #2080)
|
* Allow using a `JsonVariant` as a key or index (issue #2080)
|
||||||
|
@ -26,6 +26,7 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE("null" == variant.as<std::string>());
|
REQUIRE("null" == variant.as<std::string>());
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(4.2)") {
|
SECTION("set(4.2)") {
|
||||||
@ -38,6 +39,7 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<unsigned>() == 4U);
|
REQUIRE(variant.as<unsigned>() == 4U);
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(0.0)") {
|
SECTION("set(0.0)") {
|
||||||
@ -47,6 +49,7 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<long>() == 0L);
|
REQUIRE(variant.as<long>() == 0L);
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(false)") {
|
SECTION("set(false)") {
|
||||||
@ -58,6 +61,7 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<std::string>() == "false");
|
REQUIRE(variant.as<std::string>() == "false");
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(true)") {
|
SECTION("set(true)") {
|
||||||
@ -69,6 +73,7 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<std::string>() == "true");
|
REQUIRE(variant.as<std::string>() == "true");
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(42)") {
|
SECTION("set(42)") {
|
||||||
@ -81,6 +86,7 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<std::string>() == "42");
|
REQUIRE(variant.as<std::string>() == "42");
|
||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("set(42L)") {
|
SECTION("set(42L)") {
|
||||||
@ -205,6 +211,13 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
REQUIRE(variant.as<JsonString>().isNull());
|
REQUIRE(variant.as<JsonString>().isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("set(serialized(\"hello\"))") {
|
||||||
|
variant.set(serialized("hello"));
|
||||||
|
|
||||||
|
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
|
REQUIRE(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("to<JsonObject>()") {
|
SECTION("to<JsonObject>()") {
|
||||||
JsonObject obj = variant.to<JsonObject>();
|
JsonObject obj = variant.to<JsonObject>();
|
||||||
obj["key"] = "value";
|
obj["key"] = "value";
|
||||||
@ -262,10 +275,4 @@ TEST_CASE("JsonVariant::as()") {
|
|||||||
|
|
||||||
REQUIRE(variant.as<MY_ENUM>() == ONE);
|
REQUIRE(variant.as<MY_ENUM>() == ONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SerializedValue as MsgPackBinary") {
|
|
||||||
variant.set(serialized("hello"));
|
|
||||||
|
|
||||||
REQUIRE(variant.as<MsgPackBinary>().data() == nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ TEST_CASE("Unbound JsonVariant") {
|
|||||||
CHECK(variant.as<JsonString>().isNull());
|
CHECK(variant.as<JsonString>().isNull());
|
||||||
CHECK(variant.as<MsgPackBinary>().data() == nullptr);
|
CHECK(variant.as<MsgPackBinary>().data() == nullptr);
|
||||||
CHECK(variant.as<MsgPackBinary>().size() == 0);
|
CHECK(variant.as<MsgPackBinary>().size() == 0);
|
||||||
|
CHECK(variant.as<MsgPackExtension>().data() == nullptr);
|
||||||
|
CHECK(variant.as<MsgPackExtension>().size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("is<T>()") {
|
SECTION("is<T>()") {
|
||||||
@ -49,6 +51,7 @@ TEST_CASE("Unbound JsonVariant") {
|
|||||||
CHECK_FALSE(variant.set(serialized(std::string("42"))));
|
CHECK_FALSE(variant.set(serialized(std::string("42"))));
|
||||||
CHECK_FALSE(variant.set(true));
|
CHECK_FALSE(variant.set(true));
|
||||||
CHECK_FALSE(variant.set(MsgPackBinary("hello", 5)));
|
CHECK_FALSE(variant.set(MsgPackBinary("hello", 5)));
|
||||||
|
CHECK_FALSE(variant.set(MsgPackExtension(1, "hello", 5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("add()") {
|
SECTION("add()") {
|
||||||
|
@ -41,6 +41,24 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 1") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("set(MsgPackExtension)") {
|
||||||
|
SECTION("returns true if size <= 252") {
|
||||||
|
auto str = std::string(252, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns false if size >= 253") {
|
||||||
|
auto str = std::string(253, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc.overflowed() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("deserializeJson()") {
|
SECTION("deserializeJson()") {
|
||||||
SECTION("returns Ok if string length <= 255") {
|
SECTION("returns Ok if string length <= 255") {
|
||||||
auto input = "\"" + std::string(255, '?') + "\"";
|
auto input = "\"" + std::string(255, '?') + "\"";
|
||||||
@ -91,5 +109,21 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 1") {
|
|||||||
|
|
||||||
REQUIRE(err == DeserializationError::NoMemory);
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("returns Ok if extension size <= 252") {
|
||||||
|
auto input = "\xc7\xfc\x01" + std::string(252, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if binary size >= 253") {
|
||||||
|
auto input = "\xc7\xfd\x01" + std::string(253, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,24 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 2") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("set(MsgPackExtension)") {
|
||||||
|
SECTION("returns true if size <= 65531") {
|
||||||
|
auto str = std::string(65531, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns false if size >= 65532") {
|
||||||
|
auto str = std::string(65532, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == false);
|
||||||
|
REQUIRE(doc.overflowed() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("deserializeJson()") {
|
SECTION("deserializeJson()") {
|
||||||
SECTION("returns Ok if string length <= 65535") {
|
SECTION("returns Ok if string length <= 65535") {
|
||||||
auto input = "\"" + std::string(65535, '?') + "\"";
|
auto input = "\"" + std::string(65535, '?') + "\"";
|
||||||
@ -92,5 +110,21 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 2") {
|
|||||||
|
|
||||||
REQUIRE(err == DeserializationError::NoMemory);
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("returns Ok if extension size <= 65531") {
|
||||||
|
auto input = "\xc8\xff\xfb\x01" + std::string(65531, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns NoMemory if binary size >= 65532") {
|
||||||
|
auto input = "\xc8\xff\xfc\x01" + std::string(65532, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,16 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 4") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("set(MsgPackExtension)") {
|
||||||
|
SECTION("returns true if size >= 65532") {
|
||||||
|
auto str = std::string(65532, '?');
|
||||||
|
auto result = doc.set(MsgPackExtension(1, str.data(), str.size()));
|
||||||
|
|
||||||
|
REQUIRE(result == true);
|
||||||
|
REQUIRE(doc.overflowed() == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("deserializeJson()") {
|
SECTION("deserializeJson()") {
|
||||||
SECTION("returns Ok if string length >= 65536") {
|
SECTION("returns Ok if string length >= 65536") {
|
||||||
auto input = "\"" + std::string(65536, '?') + "\"";
|
auto input = "\"" + std::string(65536, '?') + "\"";
|
||||||
@ -52,6 +62,14 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 4") {
|
|||||||
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("returns Ok if extension size >= 65532") {
|
||||||
|
auto input = "\xc8\xff\xfb\x01" + std::string(65532, '?');
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("bin 32 deserialization") {
|
SECTION("bin 32 deserialization") {
|
||||||
@ -79,4 +97,31 @@ TEST_CASE("ARDUINOJSON_STRING_LENGTH_SIZE == 4") {
|
|||||||
REQUIRE(result == 5 + str.size());
|
REQUIRE(result == 5 + str.size());
|
||||||
REQUIRE(output == std::string("\xc6\x00\x01\x00\x00", 5) + str);
|
REQUIRE(output == std::string("\xc6\x00\x01\x00\x00", 5) + str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("ext 32 deserialization") {
|
||||||
|
auto str = std::string(65536, '?');
|
||||||
|
auto input = std::string("\xc9\x00\x01\x00\x00\x2a", 6) + str;
|
||||||
|
|
||||||
|
auto err = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto value = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(value.type() == 42);
|
||||||
|
REQUIRE(value.size() == 65536);
|
||||||
|
REQUIRE(value.data() != nullptr);
|
||||||
|
REQUIRE(std::string(reinterpret_cast<const char*>(value.data()),
|
||||||
|
value.size()) == str);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 32 serialization") {
|
||||||
|
auto str = std::string(65536, '?');
|
||||||
|
doc.set(MsgPackExtension(42, str.data(), str.size()));
|
||||||
|
|
||||||
|
std::string output;
|
||||||
|
auto result = serializeMsgPack(doc, output);
|
||||||
|
|
||||||
|
REQUIRE(result == 6 + str.size());
|
||||||
|
REQUIRE(output == std::string("\xc9\x00\x01\x00\x00\x2a", 6) + str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,6 @@ TEST_CASE("deserialize MsgPack value") {
|
|||||||
|
|
||||||
SECTION("bin 16") {
|
SECTION("bin 16") {
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
auto str = std::string(256, '?');
|
auto str = std::string(256, '?');
|
||||||
auto input = std::string("\xc5\x01\x00", 3) + str;
|
auto input = std::string("\xc5\x01\x00", 3) + str;
|
||||||
|
|
||||||
@ -169,6 +168,127 @@ TEST_CASE("deserialize MsgPack value") {
|
|||||||
REQUIRE(std::string(reinterpret_cast<const char*>(binary.data()),
|
REQUIRE(std::string(reinterpret_cast<const char*>(binary.data()),
|
||||||
binary.size()) == str);
|
binary.size()) == str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 1") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd4\x01\x02");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 1);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 2") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd5\x01\x02\x03");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 2);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 2);
|
||||||
|
REQUIRE(data[1] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 4") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd6\x01\x02\x03\x04\x05");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 4);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 2);
|
||||||
|
REQUIRE(data[1] == 3);
|
||||||
|
REQUIRE(data[2] == 4);
|
||||||
|
REQUIRE(data[3] == 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 8") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd7\x01????????");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 8);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == '?');
|
||||||
|
REQUIRE(data[7] == '?');
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 16") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xd8\x01?????????????????");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 16);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == '?');
|
||||||
|
REQUIRE(data[15] == '?');
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 8") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xc7\x02\x01\x03\x04");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 2);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 3);
|
||||||
|
REQUIRE(data[1] == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 16") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xc8\x00\x02\x01\x03\x04");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 2);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 3);
|
||||||
|
REQUIRE(data[1] == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 32") {
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
auto error = deserializeMsgPack(doc, "\xc9\x00\x00\x00\x02\x01\x03\x04");
|
||||||
|
|
||||||
|
REQUIRE(error == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.is<MsgPackExtension>());
|
||||||
|
auto ext = doc.as<MsgPackExtension>();
|
||||||
|
REQUIRE(ext.type() == 1);
|
||||||
|
REQUIRE(ext.size() == 2);
|
||||||
|
auto data = reinterpret_cast<const uint8_t*>(ext.data());
|
||||||
|
REQUIRE(data[0] == 3);
|
||||||
|
REQUIRE(data[1] == 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("deserializeMsgPack() under memory constaints") {
|
TEST_CASE("deserializeMsgPack() under memory constaints") {
|
||||||
|
@ -184,53 +184,6 @@ TEST_CASE("deserializeMsgPack() returns IncompleteInput") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string msgPackToJson(const char* input, size_t inputSize) {
|
|
||||||
JsonDocument doc;
|
|
||||||
auto err = deserializeMsgPack(doc, input, inputSize);
|
|
||||||
REQUIRE(err == DeserializationError::Ok);
|
|
||||||
return doc.as<std::string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("deserializeMsgPack() replaces ext types by null") {
|
|
||||||
SECTION("ext 8") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xc7\x01\x01\x01\x2A", 6) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("ext 16") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xc8\x00\x01\x01\x01\x2A", 7) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("ext 32") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xc9\x00\x00\x00\x01\x01\x01\x2A", 9) ==
|
|
||||||
"[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 1") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd4\x01\x01\x2A", 5) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 2") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd5\x01\x01\x02\x2A", 6) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 4") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd6\x01\x01\x02\x03\x04\x2A", 8) ==
|
|
||||||
"[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 8") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd7\x01\x01\x02\x03\x04\x05\x06\x07\x08\x2A",
|
|
||||||
12) == "[null,42]");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("fixext 16") {
|
|
||||||
REQUIRE(msgPackToJson("\x92\xd8\x01\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A"
|
|
||||||
"\x0B\x0C\x0D\x0E"
|
|
||||||
"\x0F\x10\x2A",
|
|
||||||
20) == "[null,42]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE(
|
TEST_CASE(
|
||||||
"deserializeMsgPack() returns NoMemory when string allocation fails") {
|
"deserializeMsgPack() returns NoMemory when string allocation fails") {
|
||||||
TimebombAllocator allocator(0);
|
TimebombAllocator allocator(0);
|
||||||
|
@ -147,16 +147,56 @@ TEST_CASE("serialize MsgPack value") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("bin 8") {
|
SECTION("bin 8") {
|
||||||
auto str = std::string(1, 1);
|
checkVariant(MsgPackBinary("?", 1), "\xC4\x01?");
|
||||||
checkVariant(MsgPackBinary(str.data(), str.size()), "\xC4\x01\x01");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("bin 16") {
|
SECTION("bin 16") {
|
||||||
auto str = std::string(256, 1);
|
auto str = std::string(256, '?');
|
||||||
checkVariant(MsgPackBinary(str.data(), str.size()),
|
checkVariant(MsgPackBinary(str.data(), str.size()),
|
||||||
std::string("\xC5\x01\x00", 3) + str);
|
std::string("\xC5\x01\x00", 3) + str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bin 32 is tested in string_length_size_4.cpp
|
||||||
|
|
||||||
|
SECTION("fixext 1") {
|
||||||
|
checkVariant(MsgPackExtension(1, "\x02", 1), "\xD4\x01\x02");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 2") {
|
||||||
|
checkVariant(MsgPackExtension(1, "\x03\x04", 2), "\xD5\x01\x03\x04");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 4") {
|
||||||
|
checkVariant(MsgPackExtension(1, "\x05\x06\x07\x08", 4),
|
||||||
|
"\xD6\x01\x05\x06\x07\x08");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 8") {
|
||||||
|
checkVariant(MsgPackExtension(1, "????????", 8), "\xD7\x01????????");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("fixext 16") {
|
||||||
|
checkVariant(MsgPackExtension(1, "????????????????", 16),
|
||||||
|
"\xD8\x01????????????????");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 8") {
|
||||||
|
checkVariant(MsgPackExtension(2, "???", 3), "\xC7\x03\x02???");
|
||||||
|
checkVariant(MsgPackExtension(2, "?????", 5), "\xC7\x05\x02?????");
|
||||||
|
checkVariant(MsgPackExtension(2, "???????", 7), "\xC7\x07\x02???????");
|
||||||
|
checkVariant(MsgPackExtension(2, "?????????", 9), "\xC7\x09\x02?????????");
|
||||||
|
checkVariant(MsgPackExtension(2, "???????????????", 15),
|
||||||
|
"\xC7\x0F\x02???????????????");
|
||||||
|
checkVariant(MsgPackExtension(2, "?????????????????", 17),
|
||||||
|
"\xC7\x11\x02?????????????????");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ext 16") {
|
||||||
|
auto str = std::string(256, '?');
|
||||||
|
checkVariant(MsgPackExtension(2, str.data(), str.size()),
|
||||||
|
std::string("\xC8\x01\x00\x02", 4) + str);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("serialize round double as integer") { // Issue #1718
|
SECTION("serialize round double as integer") { // Issue #1718
|
||||||
checkVariant(-32768.0, "\xD1\x80\x00");
|
checkVariant(-32768.0, "\xD1\x80\x00");
|
||||||
checkVariant(-129.0, "\xD1\xFF\x7F");
|
checkVariant(-129.0, "\xD1\xFF\x7F");
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
|
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
|
||||||
#include "ArduinoJson/MsgPack/MsgPackBinary.hpp"
|
#include "ArduinoJson/MsgPack/MsgPackBinary.hpp"
|
||||||
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
||||||
|
#include "ArduinoJson/MsgPack/MsgPackExtension.hpp"
|
||||||
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
|
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
|
||||||
|
|
||||||
#include "ArduinoJson/compatibility.hpp"
|
#include "ArduinoJson/compatibility.hpp"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Variant/Converter.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
class MsgPackBinary {
|
class MsgPackBinary {
|
||||||
|
@ -38,11 +38,13 @@ class MsgPackDeserializer {
|
|||||||
DeserializationOption::NestingLimit nestingLimit) {
|
DeserializationOption::NestingLimit nestingLimit) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
uint8_t code = 0; // TODO: why do we need to initialize this variable?
|
uint8_t header[5];
|
||||||
err = readByte(code);
|
err = readBytes(header, 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
const uint8_t& code = header[0];
|
||||||
|
|
||||||
foundSomething_ = true;
|
foundSomething_ = true;
|
||||||
|
|
||||||
bool allowValue = filter.allowValue();
|
bool allowValue = filter.allowValue();
|
||||||
@ -52,82 +54,6 @@ class MsgPackDeserializer {
|
|||||||
ARDUINOJSON_ASSERT(variant != 0);
|
ARDUINOJSON_ASSERT(variant != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
switch (code) {
|
|
||||||
case 0xc4: // bin 8
|
|
||||||
case 0xc7: // ext 8
|
|
||||||
case 0xd9: // str 8
|
|
||||||
uint8_t size8;
|
|
||||||
err = readInteger(size8);
|
|
||||||
size = size8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc5: // bin 16
|
|
||||||
case 0xc8: // ext 16
|
|
||||||
case 0xda: // str 16
|
|
||||||
case 0xdc: // array 16
|
|
||||||
case 0xde: // map 16
|
|
||||||
uint16_t size16;
|
|
||||||
err = readInteger(size16);
|
|
||||||
size = size16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc6: // bin 32
|
|
||||||
case 0xc9: // ext 32
|
|
||||||
case 0xdb: // str 32
|
|
||||||
case 0xdd: // array 32
|
|
||||||
case 0xdf: // map 32
|
|
||||||
uint32_t size32;
|
|
||||||
err = readInteger(size32);
|
|
||||||
size = size32;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
switch (code & 0xf0) {
|
|
||||||
case 0x90: // fixarray
|
|
||||||
case 0x80: // fixmap
|
|
||||||
size = code & 0x0F;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (code & 0xe0) {
|
|
||||||
case 0xa0: // fixstr
|
|
||||||
size = code & 0x1f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// array 16, 32 and fixarray
|
|
||||||
if (code == 0xdc || code == 0xdd || (code & 0xf0) == 0x90)
|
|
||||||
return readArray(variant, size, filter, nestingLimit);
|
|
||||||
|
|
||||||
// map 16, 32 and fixmap
|
|
||||||
if (code == 0xde || code == 0xdf || (code & 0xf0) == 0x80)
|
|
||||||
return readObject(variant, size, filter, nestingLimit);
|
|
||||||
|
|
||||||
// str 8, 16, 32 and fixstr
|
|
||||||
if (code == 0xd9 || code == 0xda || code == 0xdb || (code & 0xe0) == 0xa0) {
|
|
||||||
if (allowValue)
|
|
||||||
return readString(variant, size);
|
|
||||||
else
|
|
||||||
return skipBytes(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bin 8, 16, 32
|
|
||||||
if (code == 0xc4 || code == 0xc5 || code == 0xc6) {
|
|
||||||
if (allowValue)
|
|
||||||
return readBinary(variant, size);
|
|
||||||
else
|
|
||||||
return skipBytes(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ext 8, 16, 32
|
|
||||||
if (code == 0xc7 || code == 0xc8 || code == 0xc9)
|
|
||||||
return skipBytes(size + 1);
|
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 0xc0:
|
case 0xc0:
|
||||||
// already null
|
// already null
|
||||||
@ -209,31 +135,96 @@ class MsgPackDeserializer {
|
|||||||
if (allowValue)
|
if (allowValue)
|
||||||
return readInteger<int64_t>(variant);
|
return readInteger<int64_t>(variant);
|
||||||
else
|
else
|
||||||
return skipBytes(8); // not supported
|
return skipBytes(8);
|
||||||
#else
|
#else
|
||||||
return skipBytes(8);
|
return skipBytes(8); // not supported
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 0xd4: // fixext 1 (not supported)
|
|
||||||
return skipBytes(2);
|
|
||||||
|
|
||||||
case 0xd5: // fixext 2 (not supported)
|
|
||||||
return skipBytes(3);
|
|
||||||
|
|
||||||
case 0xd6: // fixext 4 (not supported)
|
|
||||||
return skipBytes(5);
|
|
||||||
|
|
||||||
case 0xd7: // fixext 8 (not supported)
|
|
||||||
return skipBytes(9);
|
|
||||||
|
|
||||||
case 0xd8: // fixext 16 (not supported)
|
|
||||||
return skipBytes(17);
|
|
||||||
|
|
||||||
default: // fixint
|
|
||||||
if (allowValue)
|
|
||||||
variant->setInteger(static_cast<int8_t>(code));
|
|
||||||
return DeserializationError::Ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (code <= 0x7f || code >= 0xe0) { // fixint
|
||||||
|
if (allowValue)
|
||||||
|
variant->setInteger(static_cast<int8_t>(code));
|
||||||
|
return DeserializationError::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sizeBytes = 0;
|
||||||
|
size_t size = 0;
|
||||||
|
bool isExtension = code >= 0xc7 && code <= 0xc9;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case 0xc4: // bin 8
|
||||||
|
case 0xc7: // ext 8
|
||||||
|
case 0xd9: // str 8
|
||||||
|
sizeBytes = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc5: // bin 16
|
||||||
|
case 0xc8: // ext 16
|
||||||
|
case 0xda: // str 16
|
||||||
|
case 0xdc: // array 16
|
||||||
|
case 0xde: // map 16
|
||||||
|
sizeBytes = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc6: // bin 32
|
||||||
|
case 0xc9: // ext 32
|
||||||
|
case 0xdb: // str 32
|
||||||
|
case 0xdd: // array 32
|
||||||
|
case 0xdf: // map 32
|
||||||
|
sizeBytes = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code >= 0xd4 && code <= 0xd8) { // fixext
|
||||||
|
size = size_t(1) << (code - 0xd4);
|
||||||
|
isExtension = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (code & 0xf0) {
|
||||||
|
case 0x90: // fixarray
|
||||||
|
case 0x80: // fixmap
|
||||||
|
size = code & 0x0F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (code & 0xe0) {
|
||||||
|
case 0xa0: // fixstr
|
||||||
|
size = code & 0x1f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeBytes) {
|
||||||
|
err = readBytes(header + 1, sizeBytes);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeBytes; i++)
|
||||||
|
size = (size << 8) | header[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// array 16, 32 and fixarray
|
||||||
|
if (code == 0xdc || code == 0xdd || (code & 0xf0) == 0x90)
|
||||||
|
return readArray(variant, size, filter, nestingLimit);
|
||||||
|
|
||||||
|
// map 16, 32 and fixmap
|
||||||
|
if (code == 0xde || code == 0xdf || (code & 0xf0) == 0x80)
|
||||||
|
return readObject(variant, size, filter, nestingLimit);
|
||||||
|
|
||||||
|
// str 8, 16, 32 and fixstr
|
||||||
|
if (code == 0xd9 || code == 0xda || code == 0xdb || (code & 0xe0) == 0xa0) {
|
||||||
|
if (allowValue)
|
||||||
|
return readString(variant, size);
|
||||||
|
else
|
||||||
|
return skipBytes(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isExtension)
|
||||||
|
size++; // to include the type
|
||||||
|
|
||||||
|
if (allowValue)
|
||||||
|
return readRawString(variant, header, uint8_t(1 + sizeBytes), size);
|
||||||
|
else
|
||||||
|
return skipBytes(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeserializationError::Code readByte(uint8_t& value) {
|
DeserializationError::Code readByte(uint8_t& value) {
|
||||||
@ -372,47 +363,16 @@ class MsgPackDeserializer {
|
|||||||
return readBytes(p, n);
|
return readBytes(p, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeserializationError::Code readBinary(VariantData* variant, size_t n) {
|
DeserializationError::Code readRawString(VariantData* variant,
|
||||||
uint8_t headerSize;
|
const void* header,
|
||||||
|
uint8_t headerSize, size_t n) {
|
||||||
if (n <= 0xFF) {
|
|
||||||
headerSize = 2;
|
|
||||||
}
|
|
||||||
#if ARDUINOJSON_STRING_LENGTH_SIZE >= 2
|
|
||||||
else if (n <= 0xFFFF) {
|
|
||||||
headerSize = 3;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if ARDUINOJSON_STRING_LENGTH_SIZE >= 4
|
|
||||||
else {
|
|
||||||
headerSize = 5;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
else {
|
|
||||||
return DeserializationError::NoMemory;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char* p = stringBuffer_.reserve(headerSize + n);
|
char* p = stringBuffer_.reserve(headerSize + n);
|
||||||
if (!p)
|
if (!p)
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
if (n <= 0xFF) {
|
memcpy(p, header, headerSize);
|
||||||
*p++ = '\xc4';
|
|
||||||
*p++ = char(n & 0xFF);
|
|
||||||
} else if (n <= 0xFFFF) {
|
|
||||||
*p++ = '\xc5';
|
|
||||||
*p++ = char(n >> 8 & 0xFF);
|
|
||||||
*p++ = char(n & 0xFF);
|
|
||||||
} else {
|
|
||||||
*p++ = '\xc6';
|
|
||||||
*p++ = char(n >> 24 & 0xFF);
|
|
||||||
*p++ = char(n >> 16 & 0xFF);
|
|
||||||
*p++ = char(n >> 8 & 0xFF);
|
|
||||||
*p++ = char(n & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto err = readBytes(p, n);
|
auto err = readBytes(p + headerSize, n);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
120
src/ArduinoJson/MsgPack/MsgPackExtension.hpp
Normal file
120
src/ArduinoJson/MsgPack/MsgPackExtension.hpp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Variant/Converter.hpp>
|
||||||
|
|
||||||
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
|
class MsgPackExtension {
|
||||||
|
public:
|
||||||
|
MsgPackExtension() : data_(nullptr), size_(0), type_(0) {}
|
||||||
|
explicit MsgPackExtension(int8_t type, const void* data, size_t size)
|
||||||
|
: data_(data), size_(size), type_(type) {}
|
||||||
|
|
||||||
|
int8_t type() const {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* data() const {
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const void* data_;
|
||||||
|
size_t size_;
|
||||||
|
int8_t type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Converter<MsgPackExtension> : private detail::VariantAttorney {
|
||||||
|
static void toJson(MsgPackExtension src, JsonVariant dst) {
|
||||||
|
auto data = VariantAttorney::getData(dst);
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
auto resources = getResourceManager(dst);
|
||||||
|
if (src.data()) {
|
||||||
|
uint8_t format, sizeBytes;
|
||||||
|
if (src.size() >= 0x10000) {
|
||||||
|
format = 0xc9; // ext 32
|
||||||
|
sizeBytes = 4;
|
||||||
|
} else if (src.size() >= 0x100) {
|
||||||
|
format = 0xc8; // ext 16
|
||||||
|
sizeBytes = 2;
|
||||||
|
} else if (src.size() == 16) {
|
||||||
|
format = 0xd8; // fixext 16
|
||||||
|
sizeBytes = 0;
|
||||||
|
} else if (src.size() == 8) {
|
||||||
|
format = 0xd7; // fixext 8
|
||||||
|
sizeBytes = 0;
|
||||||
|
} else if (src.size() == 4) {
|
||||||
|
format = 0xd6; // fixext 4
|
||||||
|
sizeBytes = 0;
|
||||||
|
} else if (src.size() == 2) {
|
||||||
|
format = 0xd5; // fixext 2
|
||||||
|
sizeBytes = 0;
|
||||||
|
} else if (src.size() == 1) {
|
||||||
|
format = 0xd4; // fixext 1
|
||||||
|
sizeBytes = 0;
|
||||||
|
} else {
|
||||||
|
format = 0xc7; // ext 8
|
||||||
|
sizeBytes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto str = resources->createString(src.size() + 2 + sizeBytes);
|
||||||
|
if (str) {
|
||||||
|
resources->saveString(str);
|
||||||
|
auto ptr = reinterpret_cast<uint8_t*>(str->data);
|
||||||
|
*ptr++ = uint8_t(format);
|
||||||
|
for (uint8_t i = 0; i < sizeBytes; i++)
|
||||||
|
*ptr++ = uint8_t(src.size() >> (sizeBytes - i - 1) * 8 & 0xff);
|
||||||
|
*ptr++ = uint8_t(src.type());
|
||||||
|
memcpy(ptr, src.data(), src.size());
|
||||||
|
data->setRawString(str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data->setNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
static MsgPackExtension fromJson(JsonVariantConst src) {
|
||||||
|
auto data = getData(src);
|
||||||
|
if (!data)
|
||||||
|
return {};
|
||||||
|
auto rawstr = data->asRawString();
|
||||||
|
if (rawstr.size() == 0)
|
||||||
|
return {};
|
||||||
|
auto p = reinterpret_cast<const uint8_t*>(rawstr.c_str());
|
||||||
|
|
||||||
|
size_t payloadSize = 0;
|
||||||
|
uint8_t headerSize = 0;
|
||||||
|
|
||||||
|
const uint8_t& code = p[0];
|
||||||
|
|
||||||
|
if (code >= 0xd4 && code <= 0xd8) { // fixext 1
|
||||||
|
headerSize = 2;
|
||||||
|
payloadSize = size_t(1) << (code - 0xd4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code >= 0xc7 && code <= 0xc9) {
|
||||||
|
uint8_t sizeBytes = uint8_t(1 << (code - 0xc7));
|
||||||
|
for (uint8_t i = 0; i < sizeBytes; i++)
|
||||||
|
payloadSize = (payloadSize << 8) | p[1 + i];
|
||||||
|
headerSize = uint8_t(2 + sizeBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawstr.size() == headerSize + payloadSize)
|
||||||
|
return MsgPackExtension(int8_t(p[headerSize - 1]), p + headerSize,
|
||||||
|
payloadSize);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkJson(JsonVariantConst src) {
|
||||||
|
return fromJson(src).data() != nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
Reference in New Issue
Block a user