// ArduinoJson - arduinojson.org // Copyright Benoit Blanchon 2014-2018 // MIT License #pragma once #include "../Deserialization/deserialize.hpp" #include "../Memory/MemoryPool.hpp" #include "../Polyfills/type_traits.hpp" #include "../Variant/VariantRef.hpp" #include "endianess.hpp" #include "ieee754.hpp" namespace ARDUINOJSON_NAMESPACE { template class MsgPackDeserializer { typedef typename remove_reference::type::StringBuilder StringBuilder; typedef typename StringBuilder::StringType StringType; public: MsgPackDeserializer(MemoryPool &memoryPool, TReader reader, TStringStorage stringStorage, uint8_t nestingLimit) : _memoryPool(&memoryPool), _reader(reader), _stringStorage(stringStorage), _nestingLimit(nestingLimit) {} DeserializationError parse(VariantRef variant) { uint8_t code; if (!readByte(code)) return DeserializationError::IncompleteInput; if ((code & 0x80) == 0) { variant.set(code); return DeserializationError::Ok; } if ((code & 0xe0) == 0xe0) { variant.set(static_cast(code)); return DeserializationError::Ok; } if ((code & 0xe0) == 0xa0) { return readString(variant, code & 0x1f); } if ((code & 0xf0) == 0x90) return readArray(variant, code & 0x0F); if ((code & 0xf0) == 0x80) return readObject(variant, code & 0x0F); switch (code) { case 0xc0: // already null return DeserializationError::Ok; case 0xc2: variant.set(false); return DeserializationError::Ok; case 0xc3: variant.set(true); return DeserializationError::Ok; case 0xcc: return readInteger(variant); case 0xcd: return readInteger(variant); case 0xce: return readInteger(variant); case 0xcf: #if ARDUINOJSON_USE_LONG_LONG return readInteger(variant); #else readInteger(); return readInteger(variant); #endif case 0xd0: return readInteger(variant); case 0xd1: return readInteger(variant); case 0xd2: return readInteger(variant); case 0xd3: #if ARDUINOJSON_USE_LONG_LONG return readInteger(variant); #else if (!skip(4)) return DeserializationError::IncompleteInput; return readInteger(variant); #endif case 0xca: return readFloat(variant); case 0xcb: return readDouble(variant); case 0xd9: return readString(variant); case 0xda: return readString(variant); case 0xdb: return readString(variant); case 0xdc: return readArray(variant); case 0xdd: return readArray(variant); case 0xde: return readObject(variant); case 0xdf: return readObject(variant); default: return DeserializationError::NotSupported; } } private: // Prevent VS warning "assignment operator could not be generated" MsgPackDeserializer &operator=(const MsgPackDeserializer &); bool skip(uint8_t n) { while (n--) { if (_reader.ended()) return false; _reader.read(); } return true; } bool readByte(uint8_t &value) { if (_reader.ended()) return false; value = static_cast(_reader.read()); return true; } bool readBytes(uint8_t *p, size_t n) { for (size_t i = 0; i < n; i++) { if (!readByte(p[i])) return false; } return true; } template bool readBytes(T &value) { return readBytes(reinterpret_cast(&value), sizeof(value)); } template T readInteger() { T value; readBytes(value); fixEndianess(value); return value; } template bool readInteger(T &value) { if (!readBytes(value)) return false; fixEndianess(value); return true; } template DeserializationError readInteger(VariantRef variant) { T value; if (!readInteger(value)) return DeserializationError::IncompleteInput; variant.set(value); return DeserializationError::Ok; } template typename enable_if::type readFloat( VariantRef variant) { T value; if (!readBytes(value)) return DeserializationError::IncompleteInput; fixEndianess(value); variant.set(value); return DeserializationError::Ok; } template typename enable_if::type readDouble( VariantRef variant) { T value; if (!readBytes(value)) return DeserializationError::IncompleteInput; fixEndianess(value); variant.set(value); return DeserializationError::Ok; } template typename enable_if::type readDouble( VariantRef variant) { uint8_t i[8]; // input is 8 bytes T value; // output is 4 bytes uint8_t *o = reinterpret_cast(&value); if (!readBytes(i, 8)) return DeserializationError::IncompleteInput; doubleToFloat(i, o); fixEndianess(value); variant.set(value); return DeserializationError::Ok; } template DeserializationError readString(VariantRef variant) { T size; if (!readInteger(size)) return DeserializationError::IncompleteInput; return readString(variant, size); } template DeserializationError readString(StringType &str) { T size; if (!readInteger(size)) return DeserializationError::IncompleteInput; return readString(str, size); } DeserializationError readString(VariantRef variant, size_t n) { StringType s; DeserializationError err = readString(s, n); if (!err) variant.set(s); return err; } DeserializationError readString(StringType &s, size_t n) { StringBuilder builder = _stringStorage.startString(); for (; n; --n) { uint8_t c; if (!readBytes(c)) return DeserializationError::IncompleteInput; builder.append(static_cast(c)); } s = builder.complete(); if (s.isNull()) return DeserializationError::NoMemory; return DeserializationError::Ok; } template DeserializationError readArray(VariantRef variant) { TSize size; if (!readInteger(size)) return DeserializationError::IncompleteInput; return readArray(variant, size); } DeserializationError readArray(VariantRef variant, size_t n) { ArrayRef array = variant.to(); if (array.isNull()) return DeserializationError::NoMemory; return readArray(array, n); } DeserializationError readArray(ArrayRef array, size_t n) { if (_nestingLimit == 0) return DeserializationError::TooDeep; --_nestingLimit; for (; n; --n) { VariantRef value = array.add(); if (value.isInvalid()) return DeserializationError::NoMemory; DeserializationError err = parse(value); if (err) return err; } ++_nestingLimit; return DeserializationError::Ok; } template DeserializationError readObject(VariantRef variant) { TSize size; if (!readInteger(size)) return DeserializationError::IncompleteInput; return readObject(variant, size); } DeserializationError readObject(VariantRef variant, size_t n) { ObjectRef object = variant.to(); if (object.isNull()) return DeserializationError::NoMemory; return readObject(object, n); } DeserializationError readObject(ObjectRef object, size_t n) { if (_nestingLimit == 0) return DeserializationError::TooDeep; --_nestingLimit; for (; n; --n) { StringType key; DeserializationError err = parseKey(key); if (err) return err; VariantRef value = object.set(key); if (value.isInvalid()) return DeserializationError::NoMemory; err = parse(value); if (err) return err; } ++_nestingLimit; return DeserializationError::Ok; } DeserializationError parseKey(StringType &key) { uint8_t code; if (!readByte(code)) return DeserializationError::IncompleteInput; if ((code & 0xe0) == 0xa0) return readString(key, code & 0x1f); switch (code) { case 0xd9: return readString(key); case 0xda: return readString(key); case 0xdb: return readString(key); default: return DeserializationError::NotSupported; } } MemoryPool *_memoryPool; TReader _reader; TStringStorage _stringStorage; uint8_t _nestingLimit; }; template DeserializationError deserializeMsgPack(TDocument &doc, const TInput &input) { return deserialize(doc, input); } template DeserializationError deserializeMsgPack(TDocument &doc, TInput *input) { return deserialize(doc, input); } template DeserializationError deserializeMsgPack(TDocument &doc, TInput *input, size_t inputSize) { return deserialize(doc, input, inputSize); } template DeserializationError deserializeMsgPack(TDocument &doc, TInput &input) { return deserialize(doc, input); } } // namespace ARDUINOJSON_NAMESPACE