summaryrefslogtreecommitdiff
path: root/include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp')
-rw-r--r--include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp599
1 files changed, 599 insertions, 0 deletions
diff --git a/include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp
new file mode 100644
index 0000000..49c6fd4
--- /dev/null
+++ b/include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp
@@ -0,0 +1,599 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Deserialization/deserialize.hpp>
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/MsgPack/endianess.hpp>
+#include <ArduinoJson/MsgPack/ieee754.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TReader, typename TStringStorage>
+class MsgPackDeserializer {
+ public:
+ MsgPackDeserializer(MemoryPool &pool, TReader reader,
+ TStringStorage stringStorage)
+ : _pool(&pool),
+ _reader(reader),
+ _stringStorage(stringStorage),
+ _error(DeserializationError::Ok),
+ _foundSomething(false) {}
+
+ template <typename TFilter>
+ DeserializationError parse(VariantData &variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ parseVariant(&variant, filter, nestingLimit);
+ return _foundSomething ? _error : DeserializationError::EmptyInput;
+ }
+
+ private:
+ // Prevent VS warning "assignment operator could not be generated"
+ MsgPackDeserializer &operator=(const MsgPackDeserializer &);
+
+ bool invalidInput() {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+
+ template <typename TFilter>
+ bool parseVariant(VariantData *variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ uint8_t code = 0; // TODO: why do we need to initialize this variable?
+ if (!readByte(code))
+ return false;
+
+ _foundSomething = true;
+
+ bool allowValue = filter.allowValue();
+
+ switch (code) {
+ case 0xc0:
+ // already null
+ return true;
+
+ case 0xc1:
+ return invalidInput();
+
+ case 0xc2:
+ if (allowValue)
+ variant->setBoolean(false);
+ return true;
+
+ case 0xc3:
+ if (allowValue)
+ variant->setBoolean(true);
+ return true;
+
+ case 0xc4: // bin 8 (not supported)
+ return skipString<uint8_t>();
+
+ case 0xc5: // bin 16 (not supported)
+ return skipString<uint16_t>();
+
+ case 0xc6: // bin 32 (not supported)
+ return skipString<uint32_t>();
+
+ case 0xc7: // ext 8 (not supported)
+ return skipExt<uint8_t>();
+
+ case 0xc8: // ext 16 (not supported)
+ return skipExt<uint16_t>();
+
+ case 0xc9: // ext 32 (not supported)
+ return skipExt<uint32_t>();
+
+ case 0xca:
+ if (allowValue)
+ return readFloat<float>(variant);
+ else
+ return skipBytes(4);
+
+ case 0xcb:
+ if (allowValue)
+ return readDouble<double>(variant);
+ else
+ return skipBytes(8);
+
+ case 0xcc:
+ if (allowValue)
+ return readInteger<uint8_t>(variant);
+ else
+ return skipBytes(1);
+
+ case 0xcd:
+ if (allowValue)
+ return readInteger<uint16_t>(variant);
+ else
+ return skipBytes(2);
+
+ case 0xce:
+ if (allowValue)
+ return readInteger<uint32_t>(variant);
+ else
+ return skipBytes(4);
+
+ case 0xcf:
+#if ARDUINOJSON_USE_LONG_LONG
+ if (allowValue)
+ return readInteger<uint64_t>(variant);
+ else
+ return skipBytes(8);
+#else
+ return skipBytes(8); // not supported
+#endif
+
+ case 0xd0:
+ if (allowValue)
+ return readInteger<int8_t>(variant);
+ else
+ return skipBytes(1);
+
+ case 0xd1:
+ if (allowValue)
+ return readInteger<int16_t>(variant);
+ else
+ return skipBytes(2);
+
+ case 0xd2:
+ if (allowValue)
+ return readInteger<int32_t>(variant);
+ else
+ return skipBytes(4);
+
+ case 0xd3:
+#if ARDUINOJSON_USE_LONG_LONG
+ if (allowValue)
+ return readInteger<int64_t>(variant);
+ else
+ return skipBytes(8); // not supported
+#else
+ return skipBytes(8);
+#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);
+
+ case 0xd9:
+ if (allowValue)
+ return readString<uint8_t>(variant);
+ else
+ return skipString<uint8_t>();
+
+ case 0xda:
+ if (allowValue)
+ return readString<uint16_t>(variant);
+ else
+ return skipString<uint16_t>();
+
+ case 0xdb:
+ if (allowValue)
+ return readString<uint32_t>(variant);
+ else
+ return skipString<uint32_t>();
+
+ case 0xdc:
+ return readArray<uint16_t>(variant, filter, nestingLimit);
+
+ case 0xdd:
+ return readArray<uint32_t>(variant, filter, nestingLimit);
+
+ case 0xde:
+ return readObject<uint16_t>(variant, filter, nestingLimit);
+
+ case 0xdf:
+ return readObject<uint32_t>(variant, filter, nestingLimit);
+ }
+
+ switch (code & 0xf0) {
+ case 0x80:
+ return readObject(variant, code & 0x0F, filter, nestingLimit);
+
+ case 0x90:
+ return readArray(variant, code & 0x0F, filter, nestingLimit);
+ }
+
+ if ((code & 0xe0) == 0xa0) {
+ if (allowValue)
+ return readString(variant, code & 0x1f);
+ else
+ return skipBytes(code & 0x1f);
+ }
+
+ if (allowValue)
+ variant->setInteger(static_cast<int8_t>(code));
+
+ return true;
+ }
+
+ bool readByte(uint8_t &value) {
+ int c = _reader.read();
+ if (c < 0) {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ value = static_cast<uint8_t>(c);
+ return true;
+ }
+
+ bool readBytes(uint8_t *p, size_t n) {
+ if (_reader.readBytes(reinterpret_cast<char *>(p), n) == n)
+ return true;
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+
+ template <typename T>
+ bool readBytes(T &value) {
+ return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
+ }
+
+ bool skipBytes(size_t n) {
+ for (; n; --n) {
+ if (_reader.read() < 0) {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ template <typename T>
+ bool readInteger(T &value) {
+ if (!readBytes(value))
+ return false;
+ fixEndianess(value);
+ return true;
+ }
+
+ template <typename T>
+ bool readInteger(VariantData *variant) {
+ T value;
+ if (!readInteger(value))
+ return false;
+ variant->setInteger(value);
+ return true;
+ }
+
+ template <typename T>
+ typename enable_if<sizeof(T) == 4, bool>::type readFloat(
+ VariantData *variant) {
+ T value;
+ if (!readBytes(value))
+ return false;
+ fixEndianess(value);
+ variant->setFloat(value);
+ return true;
+ }
+
+ template <typename T>
+ typename enable_if<sizeof(T) == 8, bool>::type readDouble(
+ VariantData *variant) {
+ T value;
+ if (!readBytes(value))
+ return false;
+ fixEndianess(value);
+ variant->setFloat(value);
+ return true;
+ }
+
+ template <typename T>
+ typename enable_if<sizeof(T) == 4, bool>::type readDouble(
+ VariantData *variant) {
+ uint8_t i[8]; // input is 8 bytes
+ T value; // output is 4 bytes
+ uint8_t *o = reinterpret_cast<uint8_t *>(&value);
+ if (!readBytes(i, 8))
+ return false;
+ doubleToFloat(i, o);
+ fixEndianess(value);
+ variant->setFloat(value);
+ return true;
+ }
+
+ template <typename T>
+ bool readString(VariantData *variant) {
+ T size;
+ if (!readInteger(size))
+ return false;
+ return readString(variant, size);
+ }
+
+ template <typename T>
+ bool readString() {
+ T size;
+ if (!readInteger(size))
+ return false;
+ return readString(size);
+ }
+
+ template <typename T>
+ bool skipString() {
+ T size;
+ if (!readInteger(size))
+ return false;
+ return skipBytes(size);
+ }
+
+ bool readString(VariantData *variant, size_t n) {
+ if (!readString(n))
+ return false;
+ variant->setStringPointer(_stringStorage.save(),
+ typename TStringStorage::storage_policy());
+ return true;
+ }
+
+ bool readString(size_t n) {
+ _stringStorage.startString();
+ for (; n; --n) {
+ uint8_t c;
+ if (!readBytes(c))
+ return false;
+ _stringStorage.append(static_cast<char>(c));
+ }
+ _stringStorage.append('\0');
+ if (!_stringStorage.isValid()) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+
+ return true;
+ }
+
+ template <typename TSize, typename TFilter>
+ bool readArray(VariantData *variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ TSize size;
+ if (!readInteger(size))
+ return false;
+ return readArray(variant, size, filter, nestingLimit);
+ }
+
+ template <typename TFilter>
+ bool readArray(VariantData *variant, size_t n, TFilter filter,
+ NestingLimit nestingLimit) {
+ if (nestingLimit.reached()) {
+ _error = DeserializationError::TooDeep;
+ return false;
+ }
+
+ bool allowArray = filter.allowArray();
+
+ CollectionData *array = allowArray ? &variant->toArray() : 0;
+
+ TFilter memberFilter = filter[0U];
+
+ for (; n; --n) {
+ VariantData *value;
+
+ if (memberFilter.allow()) {
+ value = array->addElement(_pool);
+ if (!value) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+ } else {
+ value = 0;
+ }
+
+ if (!parseVariant(value, memberFilter, nestingLimit.decrement()))
+ return false;
+ }
+
+ return true;
+ }
+
+ template <typename TSize, typename TFilter>
+ bool readObject(VariantData *variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ TSize size;
+ if (!readInteger(size))
+ return false;
+ return readObject(variant, size, filter, nestingLimit);
+ }
+
+ template <typename TFilter>
+ bool readObject(VariantData *variant, size_t n, TFilter filter,
+ NestingLimit nestingLimit) {
+ if (nestingLimit.reached()) {
+ _error = DeserializationError::TooDeep;
+ return false;
+ }
+
+ CollectionData *object = filter.allowObject() ? &variant->toObject() : 0;
+
+ for (; n; --n) {
+ if (!readKey())
+ return false;
+
+ const char *key = _stringStorage.c_str();
+ TFilter memberFilter = filter[key];
+ VariantData *member;
+
+ if (memberFilter.allow()) {
+ // Save key in memory pool.
+ // This MUST be done before adding the slot.
+ key = _stringStorage.save();
+
+ VariantSlot *slot = object->addSlot(_pool);
+ if (!slot) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+
+ slot->setKey(key, typename TStringStorage::storage_policy());
+
+ member = slot->data();
+ } else {
+ member = 0;
+ }
+
+ if (!parseVariant(member, memberFilter, nestingLimit.decrement()))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool readKey() {
+ uint8_t code;
+ if (!readByte(code))
+ return false;
+
+ if ((code & 0xe0) == 0xa0)
+ return readString(code & 0x1f);
+
+ switch (code) {
+ case 0xd9:
+ return readString<uint8_t>();
+
+ case 0xda:
+ return readString<uint16_t>();
+
+ case 0xdb:
+ return readString<uint32_t>();
+
+ default:
+ return invalidInput();
+ }
+ }
+
+ template <typename T>
+ bool skipExt() {
+ T size;
+ if (!readInteger(size))
+ return false;
+ return skipBytes(size + 1);
+ }
+
+ MemoryPool *_pool;
+ TReader _reader;
+ TStringStorage _stringStorage;
+ DeserializationError _error;
+ bool _foundSomething;
+};
+
+//
+// deserializeMsgPack(JsonDocument&, const std::string&, ...)
+//
+// ... = NestingLimit
+template <typename TString>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, const TString &input,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TString>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, const TString &input, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TString>
+DeserializationError deserializeMsgPack(JsonDocument &doc, const TString &input,
+ NestingLimit nestingLimit,
+ Filter filter) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeMsgPack(JsonDocument&, std::istream&, ...)
+//
+// ... = NestingLimit
+template <typename TStream>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TStream &input,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TStream>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TStream &input, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TStream>
+DeserializationError deserializeMsgPack(JsonDocument &doc, TStream &input,
+ NestingLimit nestingLimit,
+ Filter filter) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeMsgPack(JsonDocument&, char*, ...)
+//
+// ... = NestingLimit
+template <typename TChar>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TChar *input,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TChar>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TChar *input, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TChar>
+DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
+ NestingLimit nestingLimit,
+ Filter filter) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeMsgPack(JsonDocument&, char*, size_t, ...)
+//
+// ... = NestingLimit
+template <typename TChar>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TChar *input, size_t inputSize,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TChar>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
+ filter);
+}
+// ... = NestingLimit, Filter
+template <typename TChar>
+DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
+ size_t inputSize,
+ NestingLimit nestingLimit,
+ Filter filter) {
+ return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
+ filter);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE