Minh Nguyen / ArduinoJson

Files at this revision

API Documentation at this revision

Comitter:
khaiminhvn
Date:
Fri Mar 19 19:30:50 2021 +0000
Commit message:
removed extras

Changed in this revision

ArduinoJson.h Show annotated file Show diff for this revision Revisions of this file
CHANGELOG.md Show annotated file Show diff for this revision Revisions of this file
CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
CONTRIBUTING.md Show annotated file Show diff for this revision Revisions of this file
LICENSE.md Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
SUPPORT.md Show annotated file Show diff for this revision Revisions of this file
component.mk Show annotated file Show diff for this revision Revisions of this file
keywords.txt Show annotated file Show diff for this revision Revisions of this file
library.json Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson.h Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Array/ArrayFunctions.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Array/ArrayImpl.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Array/ArrayIterator.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Array/ArrayRef.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Array/ArrayShortcuts.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Array/ElementProxy.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Array/Utilities.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Collection/CollectionData.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Collection/CollectionImpl.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Configuration.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/DeserializationError.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/Filter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/NestingLimit.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/Reader.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/Readers/FlashReader.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/Readers/IteratorReader.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/Readers/RamReader.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/Readers/VariantReader.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Deserialization/deserialize.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Document/BasicJsonDocument.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Document/DynamicJsonDocument.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Document/JsonDocument.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Document/StaticJsonDocument.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Json/EscapeSequence.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Json/JsonDeserializer.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Json/JsonSerializer.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Json/Latch.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Json/PrettyJsonSerializer.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Json/TextFormatter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Json/Utf16.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Json/Utf8.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Memory/Alignment.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Memory/MemoryPool.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Misc/SerializedValue.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Misc/Visitable.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/MsgPack/MsgPackSerializer.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/MsgPack/endianess.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/MsgPack/ieee754.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Namespace.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Numbers/Float.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Numbers/FloatParts.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Numbers/FloatTraits.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Numbers/Integer.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Numbers/arithmeticCompare.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Numbers/convertNumber.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Numbers/parseNumber.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Object/MemberProxy.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Object/ObjectFunctions.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Object/ObjectImpl.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Object/ObjectIterator.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Object/ObjectRef.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Object/ObjectShortcuts.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Object/Pair.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/alias_cast.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/assert.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/attributes.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/ctype.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/integer.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/limits.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/math.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/mpl/max.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/pgmspace.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/pgmspace_generic.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/preprocessor.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/safe_strcmp.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/static_array.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/conditional.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/declval.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/enable_if.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/integral_constant.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_array.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_class.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_const.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_convertible.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_enum.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_integral.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_pointer.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_same.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_signed.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/remove_const.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/remove_reference.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/type_traits/type_identity.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Polyfills/utility.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/CountingDecorator.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/Writer.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/Writers/DummyWriter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/Writers/PrintWriter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/Writers/StdStringWriter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/measure.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Serialization/serialize.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/StringStorage/StringCopier.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/StringStorage/StringMover.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/StringStorage/StringStorage.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/ArduinoStringAdapter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/ConstRamStringAdapter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/FlashStringAdapter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/FlashStringIterator.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/IsString.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/IsWriteableString.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/RamStringAdapter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/SizedFlashStringAdapter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/SizedRamStringAdapter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/StdStringAdapter.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/StoragePolicy.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/String.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Strings/StringAdapters.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/SlotFunctions.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantAs.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantAsImpl.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantCompare.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantContent.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantData.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantFunctions.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantImpl.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantOperators.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantRef.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantShortcuts.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantSlot.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantTag.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/Variant/VariantTo.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/compatibility.hpp Show annotated file Show diff for this revision Revisions of this file
src/ArduinoJson/version.hpp Show annotated file Show diff for this revision Revisions of this file
src/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ArduinoJson.h	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,5 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#include "src/ArduinoJson.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CHANGELOG.md	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,1034 @@
+ArduinoJson: change log
+=======================
+
+HEAD
+----
+
+* Made `JsonDocument`'s destructor protected (issue #1480)
+* Added missing calls to `client.stop()` in `JsonHttpClient.ino` (issue #1485)
+* Fixed error `expected ')' before 'char'` when `isdigit()` is a macro (issue #1487)
+* Fixed error `definition of implicit copy constructor is deprecated` on Clang 10
+
+v6.17.2 (2020-11-14)
+-------
+
+* Fixed invalid conversion error in `operator|(JsonVariant, char*)` (issue #1432)
+* Changed the default value of `ARDUINOJSON_ENABLE_PROGMEM` (issue #1433).
+  It now checks that the `pgm_read_XXX` macros are defined before enabling `PROGMEM`.
+
+v6.17.1 (2020-11-07)
+-------
+
+* Fixed error `ambiguous overload for 'operator|'` (issue #1411)
+* Fixed `operator|(MemberProxy, JsonObject)` (issue #1415)
+* Allowed more than 32767 values in non-embedded mode (issue #1414)
+
+v6.17.0 (2020-10-19)
+-------
+
+* Added a build failure when nullptr is defined as a macro (issue #1355)
+* Added `JsonDocument::overflowed()` which tells if the memory pool was too small (issue #1358)
+* Added `DeserializationError::EmptyInput` which tells if the input was empty
+* Added `DeserializationError::f_str()` which returns a `const __FlashStringHelper*` (issue #846)
+* Added `operator|(JsonVariantConst, JsonVariantConst)`
+* Added filtering for MessagePack (issue #1298, PR #1394 by Luca Passarella)
+* Moved float convertion tables to PROGMEM
+* Fixed `JsonVariant::set((char*)0)` which returned false instead of true (issue #1368)
+* Fixed error `No such file or directory #include <WString.h>` (issue #1381)
+
+v6.16.1 (2020-08-04)
+-------
+
+* Fixed `deserializeJson()` that stopped reading after `{}` (issue #1335)
+
+v6.16.0 (2020-08-01)
+-------
+
+* Added comparisons (`>`, `>=`, `==`, `!=`, `<`, and `<=`) between `JsonVariant`s
+* Added string deduplication (issue #1303)
+* Added `JsonString::operator!=`
+* Added wildcard key (`*`) for filters (issue #1309)
+* Set `ARDUINOJSON_DECODE_UNICODE` to `1` by default
+* Fixed `copyArray()` not working with `String`, `ElementProxy`, and `MemberProxy`
+* Fixed error `getOrAddElement is not a member of ElementProxy` (issue #1311)
+* Fixed excessive stack usage when compiled with `-Og` (issues #1210 and #1314)
+* Fixed `Warning[Pa093]: implicit conversion from floating point to integer` on IAR compiler (PR #1328 by @stawiski)
+
+v6.15.2 (2020-05-15)
+-------
+
+* CMake: don't build tests when imported in another project
+* CMake: made project arch-independent
+* Visual Studio: fixed error C2766 with flag `/Zc:__cplusplus` (issue #1250)
+* Added support for `JsonDocument` to `copyArray()` (issue #1255)
+* Added support for `enum`s in `as<T>()` and `is<T>()`  (issue #1256)
+* Added `JsonVariant` as an input type for `deserializeXxx()`  
+  For example, you can do: `deserializeJson(doc2, doc1["payload"])`
+* Break the build if using 64-bit integers with ARDUINOJSON_USE_LONG_LONG==0
+
+v6.15.1 (2020-04-08)
+-------
+
+* Fixed "maybe-uninitialized" warning (issue #1217)
+* Fixed "statement is unreachable" warning on IAR (issue #1233)
+* Fixed "pointless integer comparison" warning on IAR (issue #1233)
+* Added CMake "install" target (issue #1209)
+* Disabled alignment on AVR (issue #1231)
+
+v6.15.0 (2020-03-22)
+-------
+
+* Added `DeserializationOption::Filter` (issue #959)
+* Added example `JsonFilterExample.ino`
+* Changed the array subscript operator to automatically add missing elements
+* Fixed "deprecated-copy" warning on GCC 9 (fixes #1184)
+* Fixed `MemberProxy::set(char[])` not duplicating the string (issue #1191)
+* Fixed enums serialized as booleans (issue #1197)
+* Fixed incorrect string comparison on some platforms (issue #1198)
+* Added move-constructor and move-assignment to `BasicJsonDocument`
+* Added `BasicJsonDocument::garbageCollect()` (issue #1195)
+* Added `StaticJsonDocument::garbageCollect()`
+* Changed copy-constructor of `BasicJsonDocument` to preserve the capacity of the source.
+* Removed copy-constructor of `JsonDocument` (issue #1189)
+
+> ### BREAKING CHANGES
+> 
+> #### Copy-constructor of `BasicJsonDocument`
+>
+> In previous versions, the copy constructor of `BasicJsonDocument` looked at the source's `memoryUsage()` to choose its capacity.
+> Now, the copy constructor of `BasicJsonDocument` uses the same capacity as the source.
+>
+> Example:
+>
+> ```c++
+> DynamicJsonDocument doc1(64);
+> doc1.set(String("example"));
+>
+> DynamicJsonDocument doc2 = doc1;
+> Serial.print(doc2.capacity());  // 8 with ArduinoJson 6.14
+>                                 // 64 with ArduinoJson 6.15
+> ```
+>
+> I made this change to get consistent results between copy-constructor and move-constructor, and whether RVO applies or not.
+>
+> If you use the copy-constructor to optimize your documents, you can use `garbageCollect()` or `shrinkToFit()` instead.
+>
+> #### Copy-constructor of `JsonDocument`
+>
+> In previous versions, it was possible to create a function that take a `JsonDocument` by value.
+>
+> ```c++
+> void myFunction(JsonDocument doc) {}
+> ```
+>
+> This function gives the wrong clues because it doesn't receive a copy of the `JsonDocument`, only a sliced version.
+> It worked because the copy constructor copied the internal pointers, but it was an accident.
+>
+> From now, if you need to pass a `JsonDocument` to a function, you must use a reference:
+>
+> ```c++
+> void myFunction(JsonDocument& doc) {}
+> ```
+
+v6.14.1 (2020-01-27)
+-------
+
+* Fixed regression in UTF16 decoding (issue #1173)
+* Fixed `containsKey()` on `JsonVariantConst`
+* Added `getElement()` and `getMember()` to `JsonVariantConst`
+
+v6.14.0 (2020-01-16)
+-------
+
+* Added `BasicJsonDocument::shrinkToFit()`
+* Added support of `uint8_t` for `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` (issue #1142)
+* Added `ARDUINOJSON_ENABLE_COMMENTS` to enable support for comments (defaults to 0)
+* Auto enable support for `std::string` and `std::stream` on modern compilers (issue #1156)
+  (No need to define `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_STD_STREAM` anymore)
+* Improved decoding of UTF-16 surrogate pairs (PR #1157 by @kaysievers)
+  (ArduinoJson now produces standard UTF-8 instead of CESU-8)
+* Added `measureJson`, `measureJsonPretty`, and `measureMsgPack` to `keywords.txt`
+  (This file is used for syntax highlighting in the Arduino IDE) 
+* Fixed `variant.is<nullptr_t>()`
+* Fixed value returned by `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` when writing to a `String`
+* Improved speed of `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` when writing to a `String`
+
+> ### BREAKING CHANGES
+> 
+> #### Comments
+> 
+> Support for comments in input is now optional and disabled by default.
+>
+> If you need support for comments, you must defined `ARDUINOJSON_ENABLE_COMMENTS` to `1`; otherwise, you'll receive `InvalidInput` errors.
+>
+> ```c++
+> #define ARDUINOJSON_ENABLE_COMMENTS 1
+> #include <ArduinoJson.h>
+> ```
+
+v6.13.0 (2019-11-01)
+-------
+
+* Added support for custom writer/reader classes (issue #1088)
+* Added conversion from `JsonArray` and `JsonObject` to `bool`, to be consistent with `JsonVariant`
+* Fixed `deserializeJson()` when input contains duplicate keys (issue #1095)
+* Improved `deserializeMsgPack()` speed by reading several bytes at once
+* Added detection of Atmel AVR8/GNU C Compiler (issue #1112)
+* Fixed deserializer that stopped reading at the first `0xFF` (PR #1118 by @mikee47)
+* Fixed dangling reference in copies of `MemberProxy` and `ElementProxy` (issue #1120)
+
+v6.12.0 (2019-09-05)
+-------
+
+* Use absolute instead of relative includes (issue #1072)
+* Changed `JsonVariant::as<bool>()` to return `true` for any non-null value (issue #1005)
+* Moved ancillary files to `extras/` (issue #1011)
+
+v6.11.5 (2019-08-23)
+-------
+
+* Added fallback implementations of `strlen_P()`, `strncmp_P()`, `strcmp_P()`, and `memcpy_P()` (issue #1073)
+
+v6.11.4 (2019-08-12)
+-------
+
+* Added `measureJson()` to the `ArduinoJson` namespace (PR #1069 by @nomis)
+* Added support for `basic_string<char, traits, allocator>` (issue #1045)
+* Fixed example `JsonConfigFile.ino` for ESP8266
+* Include `Arduino.h` if `ARDUINO` is defined (PR #1071 by @nomis)
+
+v6.11.3 (2019-07-22)
+-------
+
+* Added operators `==` and `!=` for `JsonDocument`, `ElementProxy`, and `MemberProxy`
+* Fixed comparison of `JsonVariant` when one contains a linked string and the other contains an owned string (issue #1051)
+
+v6.11.2 (2019-07-08)
+-------
+
+* Fixed assignment of `JsonDocument` to `JsonVariant` (issue #1023)
+* Fix invalid conversion error on Particle Argon (issue #1035)
+
+v6.11.1 (2019-06-21)
+-------
+
+* Fixed `serialized()` not working with Flash strings (issue #1030)
+
+v6.11.0 (2019-05-26)
+-------
+
+* Fixed `deserializeJson()` silently accepting a `Stream*` (issue #978)
+* Fixed invalid result from `operator|` (issue #981)
+* Made `deserializeJson()` more picky about trailing characters (issue #980)
+* Added `ARDUINOJSON_ENABLE_NAN` (default=0) to enable NaN in JSON (issue #973)
+* Added `ARDUINOJSON_ENABLE_INFINITY` (default=0) to enable Infinity in JSON
+* Removed implicit conversion in comparison operators (issue #998)
+* Added lexicographical comparison for `JsonVariant`
+* Added support for `nullptr` (issue #998)
+
+> ### BREAKING CHANGES
+> 
+> #### NaN and Infinity
+> 
+> The JSON specification allows neither NaN not Infinity, but previous
+> versions of ArduinoJson supported it. Now, ArduinoJson behaves like most
+> other libraries: a NaN or and Infinity in the `JsonDocument`, becomes
+> a `null` in the output JSON. Also, `deserializeJson()` returns
+> `InvalidInput` if the JSON document contains NaN or Infinity.
+> 
+> This version still supports NaN and Infinity in JSON documents, but
+> it's disabled by default to be compatible with other JSON parsers.
+> If you need the old behavior back, define `ARDUINOJSON_ENABLE_NAN` and
+> `ARDUINOJSON_ENABLE_INFINITY` to `1`;:
+> 
+> ```c++
+> #define ARDUINOJSON_ENABLE_NAN 1
+> #define ARDUINOJSON_ENABLE_INFINITY 1
+> #include <ArduinoJson.h>
+> ```
+> 
+> #### The "or" operator
+> 
+> This version slightly changes the behavior of the | operator when the 
+> variant contains a float and the user requests an integer.
+>
+> Older versions returned the floating point value truncated.
+> Now, it returns the default value.
+> 
+> ```c++
+> // suppose variant contains 1.2
+> int value = variant | 3;
+> 
+> // old behavior:
+> value == 1
+> 
+> // new behavior
+> value == 3
+> ```
+> 
+> If you need the old behavior, you must add `if (variant.is<float>())`.
+
+v6.10.1 (2019-04-23)
+-------
+
+* Fixed error "attributes are not allowed on a function-definition"
+* Fixed `deserializeJson()` not being picky enough (issue #969)
+* Fixed error "no matching function for call to write(uint8_t)" (issue #972)
+
+v6.10.0 (2019-03-22)
+-------
+
+* Fixed an integer overflow in the JSON deserializer
+* Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`.
+   - `as<T>()` returns `0` if the integer `T` overflows
+   - `is<T>()` returns `false` if the integer `T` overflows
+* Added `BasicJsonDocument` to support custom allocator (issue #876)
+* Added `JsonDocument::containsKey()` (issue #938)
+* Added `JsonVariant::containsKey()`
+
+v6.9.1 (2019-03-01)
+------
+
+* Fixed warning "unused variable" with GCC 4.4 (issue #912)
+* Fixed warning "cast  increases required alignment" (issue #914)
+* Fixed warning "conversion may alter value" (issue #914)
+* Fixed naming conflict with "CAPACITY" (issue #839)
+* Muted warning "will change in GCC 7.1" (issue #914)
+* Added a clear error message for `StaticJsonBuffer` and `DynamicJsonBuffer`
+* Marked ArduinoJson.h  as a "system header"
+
+v6.9.0 (2019-02-26)
+------
+
+* Decode escaped Unicode characters like \u00DE (issue #304, PR #791)
+  Many thanks to Daniel Schulte (aka @trilader) who implemented this feature.
+* Added option ARDUINOJSON_DECODE_UNICODE to enable it
+* Converted `JsonArray::copyFrom()/copyTo()` to free functions `copyArray()`
+* Renamed `JsonArray::copyFrom()` and `JsonObject::copyFrom()` to `set()`
+* Renamed `JsonArray::get()` to `getElement()`
+* Renamed `JsonArray::add()` (without arg) to `addElement()`
+* Renamed `JsonObject::get()` to `getMember()`
+* Renamed `JsonObject::getOrCreate()` to `getOrAddMember()`
+* Fixed `JsonVariant::isNull()` not returning `true` after `set((char*)0)`
+* Fixed segfault after `variant.set(serialized((char*)0))`
+* Detect `IncompleteInput` in `false`, `true`, and `null`
+* Added `JsonDocument::size()`
+* Added `JsonDocument::remove()`
+* Added `JsonVariant::clear()`
+* Added `JsonVariant::remove()`
+
+v6.8.0-beta (2019-01-30)
+-----------
+
+* Import functions in the ArduinoJson namespace to get clearer errors
+* Improved syntax highlighting in Arduino IDE
+* Removed default capacity of `DynamicJsonDocument`
+* `JsonArray::copyFrom()` accepts `JsonArrayConst`
+* `JsonVariant::set()` accepts `JsonArrayConst` and `JsonObjectConst`
+* `JsonDocument` was missing in the ArduinoJson namespace
+* Added `memoryUsage()` to `JsonArray`, `JsonObject`, and `JsonVariant`
+* Added `nesting()` to `JsonArray`, `JsonDocument`, `JsonObject`, and `JsonVariant`
+* Replaced `JsonDocument::nestingLimit` with an additional parameter
+  to `deserializeJson()` and `deserializeMsgPack()`
+* Fixed uninitialized variant in `JsonDocument`
+* Fixed `StaticJsonDocument` copy constructor and copy assignment
+* The copy constructor of `DynamicJsonDocument` chooses the capacity according to the memory usage of the source, not from the capacity of the source.
+* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
+* Added `JsonDocument::isNull()`
+* Added `JsonDocument::operator[]`
+* Added `ARDUINOJSON_TAB` to configure the indentation character
+* Reduced the size of the pretty JSON serializer
+* Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant`
+* `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write.
+  Calling `JsonVariant::to<T>()` is not required anymore.
+* `JsonDocument` now support the same operations as `JsonVariant`.
+  Calling `JsonDocument::as<T>()` is not required anymore.
+* Fixed example `JsonHttpClient.ino`
+* User can now use a `JsonString` as a key or a value
+
+> ### BREAKING CHANGES
+> 
+> #### `DynamicJsonDocument`'s constructor
+> 
+> The parameter to the constructor of `DynamicJsonDocument` is now mandatory
+>
+> Old code:
+>
+> ```c++
+> DynamicJsonDocument doc;
+> ```
+>
+> New code:
+>
+> ```c++
+> DynamicJsonDocument doc(1024);
+> ```
+> 
+> #### Nesting limit
+> 
+> `JsonDocument::nestingLimit` was replaced with a new parameter to `deserializeJson()` and `deserializeMsgPack()`.
+> 
+> Old code:
+> 
+> ```c++
+> doc.nestingLimit = 15;
+> deserializeJson(doc, input);
+> ```
+> 
+> New code: 
+> 
+> ```c++
+> deserializeJson(doc, input, DeserializationOption::NestingLimit(15));
+> ```
+
+v6.7.0-beta (2018-12-07)
+-----------
+
+* Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity.
+* Restored the monotonic allocator because the code was getting too big
+* Reduced the memory usage
+* Reduced the code size
+* Renamed `JsonKey` to `JsonString`
+* Removed spurious files in the Particle library
+
+v6.6.0-beta (2018-11-13)
+-----------
+
+* Removed `JsonArray::is<T>(i)` and `JsonArray::set(i,v)`
+* Removed `JsonObject::is<T>(k)` and `JsonObject::set(k,v)`
+* Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)`
+* Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)`
+* Added `JSON_STRING_SIZE()`
+* ~~Replacing or removing a value now releases the memory~~
+* Added `DeserializationError::code()` to be used in switch statements (issue #846)
+
+v6.5.0-beta (2018-10-13)
+-----------
+
+* Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant`
+* Allow mixed configuration in compilation units (issue #809)
+* Fixed object keys not being duplicated
+* `JsonPair::key()` now returns a `JsonKey`
+* Increased the default capacity of `DynamicJsonDocument`
+* Fixed `JsonVariant::is<String>()` (closes #763)
+* Added `JsonArrayConst`, `JsonObjectConst`, and `JsonVariantConst`
+* Added copy-constructor and copy-assignment-operator for `JsonDocument` (issue #827)
+
+v6.4.0-beta (2018-09-11)
+-----------
+
+* Copy `JsonArray` and `JsonObject`, instead of storing pointers (issue #780)
+* Added `JsonVariant::to<JsonArray>()` and `JsonVariant::to<JsonObject>()`
+
+v6.3.0-beta (2018-08-31)
+-----------
+
+* Implemented reference semantics for `JsonVariant`
+* Replaced `JsonPair`'s `key` and `value` with `key()` and `value()`
+* Fixed `serializeJson(obj[key], dst)` (issue #794)
+
+> ### BREAKING CHANGES
+>
+> #### JsonVariant
+> 
+> `JsonVariant` now has a semantic similar to `JsonObject` and `JsonArray`.
+> It's a reference to a value stored in the `JsonDocument`.
+> As a consequence, a `JsonVariant` cannot be used as a standalone variable anymore.
+>
+> Old code:
+>
+> ```c++
+> JsonVariant myValue = 42;
+> ```
+>
+> New code:
+>
+> ```c++
+> DynamicJsonDocument doc;
+> JsonVariant myValue = doc.to<JsonVariant>();
+> myValue.set(42);
+> ```
+>
+> #### JsonPair
+>
+> Old code:
+>
+> ```c++
+> for(JsonPair p : myObject) {
+>   Serial.println(p.key);
+>   Serial.println(p.value.as<int>());
+> }
+> ```
+>
+> New code:
+>
+> ```c++
+> for(JsonPair p : myObject) {
+>   Serial.println(p.key());
+>   Serial.println(p.value().as<int>());
+> }
+> ```
+>
+> CAUTION: the key is now read only!
+
+v6.2.3-beta (2018-07-19)
+-----------
+
+* Fixed exception when using Flash strings as object keys (issue #784)
+
+v6.2.2-beta (2018-07-18)
+-----------
+
+* Fixed `invalid application of 'sizeof' to incomplete type '__FlashStringHelper'` (issue #783)
+* Fixed `char[]` not duplicated when passed to `JsonVariant::operator[]`
+
+v6.2.1-beta (2018-07-17)
+-----------
+
+* Fixed `JsonObject` not inserting keys of type `String` (issue #782)
+
+v6.2.0-beta (2018-07-12)
+-----------
+
+* Disabled lazy number deserialization (issue #772)
+* Fixed `JsonVariant::is<int>()` that returned true for empty strings
+* Improved float serialization when `-fsingle-precision-constant` is used
+* Renamed function `RawJson()` to `serialized()`
+* `serializeMsgPack()` now supports values marked with `serialized()`
+
+> ### BREAKING CHANGES
+>
+> #### Non quoted strings
+>
+> Non quoted strings are now forbidden in values, but they are still allowed in keys.
+> For example, `{key:"value"}` is accepted, but `{key:value}` is not.
+>
+> #### Preformatted values
+>
+> Old code:
+>
+> ```c++
+> object["values"] = RawJson("[1,2,3,4]");
+> ```
+> 
+> New code:
+> 
+> ```c++
+> object["values"] = serialized("[1,2,3,4]");
+> ```
+
+v6.1.0-beta (2018-07-02)
+-----------
+
+* Return `JsonArray` and `JsonObject` by value instead of reference (issue #309)
+* Replaced `success()` with `isNull()`
+
+> ### BREAKING CHANGES
+> 
+> Old code:
+>
+> ```c++
+> JsonObject& obj = doc.to<JsonObject>();
+> JsonArray& arr = obj.createNestedArray("key");
+> if (!arr.success()) {
+>   Serial.println("Not enough memory");
+>   return;
+> }
+> ```
+> 
+> New code:
+> 
+> ```c++
+> JsonObject obj = doc.to<JsonObject>();
+> JsonArray arr = obj.createNestedArray("key");
+> if (arr.isNull()) {
+>   Serial.println("Not enough memory");
+>   return;
+> }
+> ```
+
+v6.0.1-beta (2018-06-11)
+-----------
+
+* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752)
+
+v6.0.0-beta (2018-06-07)
+-----------
+
+* Added `DynamicJsonDocument` and `StaticJsonDocument`
+* Added `deserializeJson()`
+* Added `serializeJson()` and `serializeJsonPretty()`
+* Added `measureJson()` and `measureJsonPretty()`
+* Added `serializeMsgPack()`, `deserializeMsgPack()` and `measureMsgPack()` (issue #358)
+* Added example `MsgPackParser.ino` (issue #358)
+* Added support for non zero-terminated strings (issue #704)
+* Removed `JsonBuffer::parseArray()`, `parseObject()` and `parse()`
+* Removed `JsonBuffer::createArray()` and `createObject()`
+* Removed `printTo()` and `prettyPrintTo()`
+* Removed `measureLength()` and `measurePrettyLength()`
+* Removed all deprecated features
+
+> ### BREAKING CHANGES
+> 
+> #### Deserialization
+> 
+> Old code:
+> 
+> ```c++
+> DynamicJsonBuffer jb;
+> JsonObject& obj = jb.parseObject(json);
+> if (obj.success()) {
+> 
+> }
+> ```
+> 
+> New code:
+> 
+> ```c++
+> DynamicJsonDocument doc;
+> DeserializationError error = deserializeJson(doc, json);
+> if (error) {
+> 
+> }
+> JsonObject& obj = doc.as<JsonObject>();
+> ```
+> 
+> #### Serialization
+> 
+> Old code:
+> 
+> ```c++
+> DynamicJsonBuffer jb;
+> JsonObject& obj = jb.createObject();
+> obj["key"] = "value";
+> obj.printTo(Serial);
+> ```
+> 
+> New code:
+> 
+> ```c++
+> DynamicJsonDocument obj;
+> JsonObject& obj = doc.to<JsonObject>();
+> obj["key"] = "value";
+> serializeJson(doc, Serial);
+> ```
+
+v5.13.2
+-------
+
+* Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693)
+* Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu)
+* Fixed null values that could be pass to `strcmp()` (PR #745 from Mike Karlesky)
+* Added macros `ARDUINOJSON_VERSION`, `ARDUINOJSON_VERSION_MAJOR`...
+
+v5.13.1
+-------
+
+* Fixed `JsonVariant::operator|(int)` that returned the default value if the variant contained a double (issue #675)
+* Allowed non-quoted key to contain underscores (issue #665)
+
+v5.13.0
+-------
+
+* Changed the rules of string duplication (issue #658)
+* `RawJson()` accepts any kind of string and obeys to the same rules for duplication
+* Changed the return type of `strdup()` to `const char*` to prevent double duplication
+* Marked `strdup()` as deprecated
+
+> ### New rules for string duplication
+>
+> | type                       | duplication |
+> |:---------------------------|:------------|
+> | const char*                | no          |
+> | char*                      | ~~no~~ yes  |
+> | String                     | yes         |
+> | std::string                | yes         |
+> | const __FlashStringHelper* | yes         |
+>
+> These new rules make `JsonBuffer::strdup()` useless.
+
+v5.12.0
+-------
+
+* Added `JsonVariant::operator|` to return a default value (see below)
+* Added a clear error message when compiled as C instead of C++ (issue #629)
+* Added detection of MPLAB XC compiler (issue #629)
+* Added detection of Keil ARM Compiler (issue #629)
+* Added an example that shows how to save and load a configuration file
+* Reworked all other examples
+
+> ### How to use the new feature?
+>
+> If you have a block like this:
+>
+> ```c++
+> const char* ssid = root["ssid"];
+> if (!ssid)
+>   ssid = "default ssid";
+> ```
+>
+> You can simplify like that:
+>
+> ```c++
+> const char* ssid = root["ssid"] | "default ssid";
+> ```
+
+v5.11.2
+-------
+
+* Fixed `DynamicJsonBuffer::clear()` not resetting allocation size (issue #561)
+* Fixed incorrect rounding for float values (issue #588)
+
+v5.11.1
+-------
+
+* Removed dependency on `PGM_P` as Particle 0.6.2 doesn't define it (issue #546)
+* Fixed warning "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]"
+* Fixed warning "floating constant exceeds range of 'float' [-Woverflow]" (issue #544)
+* Fixed warning "this statement may fall through" [-Wimplicit-fallthrough=] (issue #539)
+* Removed `ARDUINOJSON_DOUBLE_IS_64BITS` as it became useless.
+* Fixed too many decimals places in float serialization (issue #543)
+
+v5.11.0
+-------
+
+* Made `JsonBuffer` non-copyable (PR #524 by @luisrayas3)
+* Added `StaticJsonBuffer::clear()`
+* Added `DynamicJsonBuffer::clear()`
+
+v5.10.1
+-------
+
+* Fixed IntelliSense errors in Visual Micro (issue #483)
+* Fixed compilation in IAR Embedded Workbench (issue #515)
+* Fixed reading "true" as a float (issue #516)
+* Added `ARDUINOJSON_DOUBLE_IS_64BITS`
+* Added `ARDUINOJSON_EMBEDDED_MODE`
+
+v5.10.0
+-------
+
+* Removed configurable number of decimal places (issues #288, #427 and #506)
+* Changed exponentiation thresholds to `1e7` and `1e-5` (issues #288, #427 and #506)
+* `JsonVariant::is<double>()` now returns `true` for integers
+* Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495)
+* Fixed error `forming reference to reference` (issue #495)
+
+> ### BREAKING CHANGES :warning:
+>
+> | Old syntax                      | New syntax          |
+> |:--------------------------------|:--------------------|
+> | `double_with_n_digits(3.14, 2)` | `3.14`              |
+> | `float_with_n_digits(3.14, 2)`  | `3.14f`             |
+> | `obj.set("key", 3.14, 2)`       | `obj["key"] = 3.14` |
+> | `arr.add(3.14, 2)`              | `arr.add(3.14)`     |
+>
+> | Input     | Old output | New output |
+> |:----------|:-----------|:-----------|
+> | `3.14159` | `3.14`     | `3.14159`  |
+> | `42.0`    | `42.00`    | `42`       |
+> | `0.0`     | `0.00`     | `0`        |
+>
+> | Expression                     | Old result | New result |
+> |:-------------------------------|:-----------|:-----------|
+> | `JsonVariant(42).is<int>()`    | `true`     | `true`     |
+> | `JsonVariant(42).is<float>()`  | `false`    | `true`     |
+> | `JsonVariant(42).is<double>()` | `false`    | `true`     |
+
+v5.9.0
+------
+
+* Added `JsonArray::remove(iterator)` (issue #479)
+* Added `JsonObject::remove(iterator)`
+* Renamed `JsonArray::removeAt(size_t)` into `remove(size_t)`
+* Renamed folder `include/` to `src/`
+* Fixed warnings `floating constant exceeds range of float`and `floating constant truncated to zero` (issue #483)
+* Removed `Print` class and converted `printTo()` to a template method (issue #276)
+* Removed example `IndentedPrintExample.ino`
+* Now compatible with Particle 0.6.1, thanks to Jacob Nite (issue #294 and PR #461 by @foodbag)
+
+v5.8.4
+------
+
+* Added custom implementation of `strtod()` (issue #453)
+* Added custom implementation of `strtol()` (issue #465)
+* `char` is now treated as an integral type (issue #337, #370)
+
+v5.8.3
+------
+
+* Fixed an access violation in `DynamicJsonBuffer` when memory allocation fails (issue #433)
+* Added operators `==` and `!=` for two `JsonVariant`s (issue #436)
+* Fixed `JsonVariant::operator[const FlashStringHelper*]` (issue #441)
+
+v5.8.2
+------
+
+* Fixed parsing of comments (issue #421)
+* Fixed ignored `Stream` timeout (issue #422)
+* Made sure we don't read more that necessary (issue #422)
+* Fixed error when the key of a `JsonObject` is a `char[]` (issue #423)
+* Reduced code size when using `const` references
+* Fixed error with string of type `unsigned char*` (issue #428)
+* Added `deprecated` attribute on `asArray()`, `asObject()` and `asString()` (issue #420)
+
+v5.8.1
+------
+
+* Fixed error when assigning a `volatile int` to a `JsonVariant` (issue #415)
+* Fixed errors with Variable Length Arrays (issue #416)
+* Fixed error when both `ARDUINOJSON_ENABLE_STD_STREAM` and `ARDUINOJSON_ENABLE_ARDUINO_STREAM` are set to `1`
+* Fixed error "Stream does not name a type" (issue #412)
+
+v5.8.0
+------
+
+* Added operator `==` to compare `JsonVariant` and strings (issue #402)
+* Added support for `Stream` (issue #300)
+* Reduced memory consumption by not duplicating spaces and comments
+
+> ### BREAKING CHANGES :warning:
+>
+> `JsonBuffer::parseObject()` and  `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`.
+>
+> This means that if you have code like:
+>
+> ```c++
+> void myFunction(JsonBuffer& jsonBuffer);
+> ```
+>
+> you need to replace it with one of the following:
+>
+> ```c++
+> void myFunction(DynamicJsonBuffer& jsonBuffer);
+> void myFunction(StaticJsonBufferBase& jsonBuffer);
+> template<typename TJsonBuffer> void myFunction(TJsonBuffer& jsonBuffer);
+> ```
+
+v5.7.3
+------
+
+* Added an `printTo(char[N])` and `prettyPrintTo(char[N])` (issue #292)
+* Added ability to set a nested value like this: `root["A"]["B"] = "C"` (issue #352)
+* Renamed `*.ipp` to `*Impl.hpp` because they were ignored by Arduino IDE (issue #396)
+
+v5.7.2
+------
+
+* Made PROGMEM available on more platforms (issue #381)
+* Fixed PROGMEM causing an exception on ESP8266 (issue #383)
+
+v5.7.1
+------
+
+* Added support for PROGMEM (issue #76)
+* Fixed compilation error when index is not an `int` (issue #381)
+
+v5.7.0
+------
+
+* Templatized all functions using `String` or `std::string`
+* Removed `ArduinoJson::String`
+* Removed `JsonVariant::defaultValue<T>()`
+* Removed non-template `JsonObject::get()` and `JsonArray.get()`
+* Fixed support for `StringSumHelper` (issue #184)
+* Replaced `ARDUINOJSON_USE_ARDUINO_STRING` by `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_ARDUINO_STRING` (issue #378)
+* Added example `StringExample.ino` to show where `String` can be used
+* Increased default nesting limit to 50 when compiled for a computer (issue #349)
+
+> ### BREAKING CHANGES :warning:
+>
+> The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return.
+>
+> Old code:
+>
+> ```c++
+> #define ARDUINOJSON_USE_ARDUINO_STRING 0
+> JsonVariant value1 = myObject.get("myKey");
+> JsonVariant value2 = myArray.get(0);
+> ```
+>
+> New code:
+>
+> ```c++
+> #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
+> #define ARDUINOJSON_ENABLE_STD_STRING 1
+> JsonVariant value1 = myObject.get<JsonVariant>("myKey");
+> JsonVariant value2 = myArray.get<JsonVariant>(0);
+> ```
+
+v5.6.7
+------
+
+* Fixed `array[idx].as<JsonVariant>()` and `object[key].as<JsonVariant>()`
+* Fixed return value of `JsonObject::set()` (issue #350)
+* Fixed undefined behavior in `Prettyfier` and `Print` (issue #354)
+* Fixed parser that incorrectly rejected floats containing a `+` (issue #349)
+
+v5.6.6
+------
+
+* Fixed `-Wparentheses` warning introduced in v5.6.5 (PR #335 by @nuket)
+* Added `.mbedignore` for ARM mbdeb (PR #334 by @nuket)
+* Fixed  `JsonVariant::success()` which didn't propagate `JsonArray::success()` nor `JsonObject::success()` (issue #342).
+
+v5.6.5
+------
+
+* `as<char*>()` now returns `true` when input is `null` (issue #330)
+
+v5.6.4
+------
+
+* Fixed error in float serialization (issue #324)
+
+v5.6.3
+------
+
+* Improved speed of float serialization (about twice faster)
+* Added `as<JsonArray>()` as a synonym for `as<JsonArray&>()`... (issue #291)
+* Fixed `call of overloaded isinf(double&) is ambiguous` (issue #284)
+
+v5.6.2
+------
+
+* Fixed build when another lib does `#undef isnan` (issue #284)
+
+v5.6.1
+------
+
+* Added missing `#pragma once` (issue #310)
+
+v5.6.0
+------
+
+* ArduinoJson is now a header-only library (issue #199)
+
+v5.5.1
+------
+
+* Fixed compilation error with Intel Galileo (issue #299)
+
+v5.5.0
+------
+
+* Added `JsonVariant::success()` (issue #279)
+* Renamed `JsonVariant::invalid<T>()` to `JsonVariant::defaultValue<T>()`
+
+v5.4.0
+------
+
+* Changed `::String` to `ArduinoJson::String` (issue #275)
+* Changed `::Print` to `ArduinoJson::Print` too
+
+v5.3.0
+------
+
+* Added custom implementation of `ftoa` (issues #266, #267, #269 and #270)
+* Added `JsonVariant JsonBuffer::parse()` (issue #265)
+* Fixed `unsigned long` printed as `signed long` (issue #170)
+
+v5.2.0
+------
+
+* Added `JsonVariant::as<char*>()` as a synonym for `JsonVariant::as<const char*>()` (issue #257)
+* Added example `JsonHttpClient` (issue #256)
+* Added `JsonArray::copyTo()` and `JsonArray::copyFrom()` (issue #254)
+* Added `RawJson()` to insert pregenerated JSON portions (issue #259)
+
+v5.1.1
+------
+
+* Removed `String` duplication when one replaces a value in a `JsonObject` (PR #232 by @ulion)
+
+v5.1.0
+------
+
+* Added support of `long long` (issue #171)
+* Moved all build settings to `ArduinoJson/Configuration.hpp`
+
+> ### BREAKING CHANGE :warning:
+>
+> If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`.
+
+v5.0.8
+------
+
+* Made the library compatible with [PlatformIO](http://platformio.org/) (issue #181)
+* Fixed `JsonVariant::is<bool>()` that was incorrectly returning false (issue #214)
+
+v5.0.7
+------
+
+* Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)`
+* Changed `String` to be a `typedef` of `std::string` (issues #142 and #161)
+
+> ### BREAKING CHANGES :warning:
+>
+> - `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"`
+> - `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"`
+
+v5.0.6
+------
+
+* Added parameter to `DynamicJsonBuffer` constructor to set initial size (issue #152)
+* Fixed warning about library category in Arduino 1.6.6 (issue #147)
+* Examples: Added a loop to wait for serial port to be ready (issue #156)
+
+v5.0.5
+------
+
+* Added overload `JsonObjectSuscript::set(value, decimals)` (issue #143)
+* Use `float` instead of `double` to reduce the size of `JsonVariant` (issue #134)
+
+v5.0.4
+------
+
+* Fixed ambiguous overload with `JsonArraySubscript` and `JsonObjectSubscript` (issue #122)
+
+v5.0.3
+------
+
+* Fixed `printTo(String)` which wrote numbers instead of strings (issue #120)
+* Fixed return type of `JsonArray::is<T>()` and some others (issue #121)
+
+v5.0.2
+------
+
+* Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the
+  `StaticJsonBuffer` is too small to hold a copy of the string
+* Fixed Clang warning "register specifier is deprecated" (issue #102)
+* Fixed GCC warning "declaration shadows a member" (issue #103)
+* Fixed memory alignment, which made ESP8266 crash (issue #104)
+* Fixed compilation on Visual Studio 2010 and 2012 (issue #107)
+
+v5.0.1
+------
+
+* Fixed compilation with Arduino 1.0.6 (issue #99)
+
+v5.0.0
+------
+
+* Added support of `String` class (issues #55, #56, #70, #77)
+* Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57)
+* Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87)
+* Added support of non standard JSON input (issue #44)
+* Added support of comments in JSON input (issue #88)
+* Added implicit cast between numerical types (issues #64, #69, #93)
+* Added ability to read number values as string (issue #90)
+* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66)
+* Switched to new the library layout (requires Arduino 1.0.6 or above)
+
+> ### BREAKING CHANGES :warning:
+>
+> - `JsonObject::add()` was renamed to `set()`
+> - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
+> - Number of digits of floating point value are now set with `double_with_n_digits()`
+
+**Personal note about the `String` class**:
+Support of the `String` class has been added to the library because many people use it in their programs.
+However, you should not see this as an invitation to use the `String` class.
+The `String` class is **bad** because it uses dynamic memory allocation.
+Compared to static allocation, it compiles to a bigger, slower program, and is less predictable.
+You certainly don't want that in an embedded environment!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CMakeLists.txt	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,19 @@
+# ArduinoJson - arduinojson.org
+# Copyright Benoit Blanchon 2014-2021
+# MIT License
+
+cmake_minimum_required(VERSION 3.0)
+
+project(ArduinoJson VERSION 6.17.2)
+
+if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
+    include(CTest)
+endif()
+
+add_subdirectory(src)
+
+if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
+	include(extras/CompileOptions.cmake)
+	add_subdirectory(extras/tests)
+	add_subdirectory(extras/fuzzing)
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CONTRIBUTING.md	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,10 @@
+# Contribution to ArduinoJson
+
+First, thank you for taking the time to contribute to this project.
+
+You can submit changes via GitHub Pull Requests.
+
+Please:
+
+1. Update the test suite for any change of behavior
+2. Use clang-format in "file" mode to format the code
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE.md	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2014-2021 Benoit BLANCHON
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,139 @@
+![ArduinoJson](banner.svg)
+
+---
+
+[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.17.2)](https://www.ardu-badge.com/ArduinoJson/6.17.2)
+[![Continuous Integration](https://github.com/bblanchon/ArduinoJson/workflows/Continuous%20Integration/badge.svg?branch=6.x)](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A6.x)
+[![Continuous Integration](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
+[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
+[![Coverage Status](https://coveralls.io/repos/github/bblanchon/ArduinoJson/badge.svg?branch=6.x)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
+[![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat)](https://github.com/bblanchon/ArduinoJson/stargazers)
+
+ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
+
+## Features
+
+* [JSON deserialization](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme)
+    * [Optionally decodes UTF-16 escape sequences to UTF-8](https://arduinojson.org/v6/api/config/decode_unicode/?utm_source=github&utm_medium=readme)
+    * [Optionally stores links to the input buffer (zero-copy)](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme)
+    * [Optionally supports comments in the input](https://arduinojson.org/v6/api/config/enable_comments/?utm_source=github&utm_medium=readme)
+    * [Optionally filters the input to keep only desired values](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#filtering)
+    * Supports single quotes as a string delimiter
+    * Compatible with [NDJSON](http://ndjson.org/) and [JSON Lines](https://jsonlines.org/)
+* [JSON serialization](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme)
+    * [Can write to a buffer or a stream](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme)
+    * [Optionally indents the document (prettified JSON)](https://arduinojson.org/v6/api/json/serializejsonpretty/?utm_source=github&utm_medium=readme)
+* [MessagePack serialization](https://arduinojson.org/v6/api/msgpack/serializemsgpack/?utm_source=github&utm_medium=readme)
+* [MessagePack deserialization](https://arduinojson.org/v6/api/msgpack/deserializemsgpack/?utm_source=github&utm_medium=readme)
+* Efficient
+    * [Twice smaller than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme)
+    * [Almost 10% faster than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme)
+    * [Consumes roughly 10% less RAM than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme)
+    * [Fixed memory allocation, no heap fragmentation](https://arduinojson.org/v6/api/jsondocument/?utm_source=github&utm_medium=readme)
+    * [Optionally works without heap memory (zero malloc)](https://arduinojson.org/v6/api/staticjsondocument/?utm_source=github&utm_medium=readme)
+    * Deduplicates strings
+* Versatile
+    * [Supports custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v6/how-to/use-external-ram-on-esp32/?utm_source=github&utm_medium=readme)
+    * Supports [Arduino's `String`](https://arduinojson.org/v6/api/config/enable_arduino_string/) and [STL's `std::string`](https://arduinojson.org/v6/api/config/enable_std_string/?utm_source=github&utm_medium=readme)
+    * Supports Arduino's `Stream` and [STL's `std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/?utm_source=github&utm_medium=readme)
+    * [Supports Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/?utm_source=github&utm_medium=readme)
+    * Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme#custom-writer)
+* Portable
+    * Usable on any C++ project (not limited to Arduino)
+    * Compatible with C++98
+    * Zero warnings with `-Wall -Wextra -pedantic` and `/W4`
+    * [Header-only library](https://en.wikipedia.org/wiki/Header-only)
+    * Works with virtually any board
+        * Arduino boards: [Uno](https://amzn.to/38aL2ik), [Due](https://amzn.to/36YkWi2), [Micro](https://amzn.to/35WkdwG), [Nano](https://amzn.to/2QTvwRX), [Mega](https://amzn.to/36XWhuf), [Yun](https://amzn.to/30odURc), [Leonardo](https://amzn.to/36XWjlR)...
+        * Espressif chips: [ESP8266](https://amzn.to/36YluV8), [ESP32](https://amzn.to/2G4pRCB)
+        * Lolin (WeMos) boards: [D1 mini](https://amzn.to/2QUpz7q), [D1 Mini Pro](https://amzn.to/36UsGSs)...
+        * Teensy boards: [4.0](https://amzn.to/30ljXGq), [3.2](https://amzn.to/2FT0EuC), [2.0](https://amzn.to/2QXUMXj) 
+        * Particle boards: [Argon](https://amzn.to/2FQHa9X), [Boron](https://amzn.to/36WgLUd), [Electron](https://amzn.to/30vEc4k), [Photon](https://amzn.to/387F9Cd)...
+        * Texas Instruments boards: [MSP430](https://amzn.to/30nJWgg)...
+    * Tested on all major development environments
+        * [Arduino IDE](https://www.arduino.cc/en/Main/Software)
+        * [Atmel Studio](http://www.atmel.com/microsite/atmel-studio/)
+        * [Atollic TrueSTUDIO](https://atollic.com/truestudio/)
+        * [Energia](http://energia.nu/)
+        * [IAR Embedded Workbench](https://www.iar.com/iar-embedded-workbench/)
+        * [Keil uVision](http://www.keil.com/)
+        * [MPLAB X IDE](http://www.microchip.com/mplab/mplab-x-ide)
+        * [Particle](https://www.particle.io/)
+        * [PlatformIO](http://platformio.org/)
+        * [Sloeber plugin for Eclipse](https://eclipse.baeyens.it/)
+        * [Visual Micro](http://www.visualmicro.com/)
+        * [Visual Studio](https://www.visualstudio.com/)
+    * [Even works with online compilers like wandbox.org](https://wandbox.org/permlink/RlZSKy17DjJ6HcdN)
+    * [CMake friendly](https://arduinojson.org/v6/how-to/use-arduinojson-with-cmake/?utm_source=github&utm_medium=readme)
+* Well designed
+    * [Elegant API](http://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme)
+    * [Thread-safe](https://en.wikipedia.org/wiki/Thread_safety)
+    * Self-contained (no external dependency)
+    * `const` friendly
+    * [`for` friendly](https://arduinojson.org/v6/api/jsonobject/begin_end/?utm_source=github&utm_medium=readme)
+    * [TMP friendly](https://en.wikipedia.org/wiki/Template_metaprogramming)
+    * Handles [integer overflows](https://arduinojson.org/v6/api/jsonvariant/as/?utm_source=github&utm_medium=readme#integer-overflows)
+* Well tested
+    * [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
+    * Continuously tested on
+        * [Visual Studio 2010, 2012, 2013, 2015, 2017, 2019](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
+        * [GCC 4.4, 4.6, 4.7, 4.8, 4.9, 5, 6, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22)
+        * [Clang 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22)
+    * [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
+* Well documented
+    * [Tutorials](https://arduinojson.org/v6/doc/deserialization/?utm_source=github&utm_medium=readme)
+    * [Examples](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme)
+    * [How-tos](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme)
+    * [FAQ](https://arduinojson.org/v6/faq/?utm_source=github&utm_medium=readme)
+    * [Book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme)
+    * [Changelog](changelog.md)
+* Vibrant user community
+    * Most popular of all Arduino libraries on [GitHub](https://github.com/search?o=desc&q=arduino+library&s=stars&type=Repositories) and [PlatformIO](https://platformio.org/lib/search)
+    * [Used in hundreds of projects](https://www.hackster.io/search?i=projects&q=arduinojson)
+    * [Responsive support](https://github.com/bblanchon/ArduinoJson/issues?q=is%3Aissue+is%3Aclosed)
+
+## Quickstart
+
+### Deserialization
+
+Here is a program that parses a JSON document with ArduinoJson.
+
+```c++
+char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
+
+DynamicJsonDocument doc(1024);
+deserializeJson(doc, json);
+
+const char* sensor = doc["sensor"];
+long time          = doc["time"];
+double latitude    = doc["data"][0];
+double longitude   = doc["data"][1];
+```
+
+See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme)
+
+### Serialization
+
+Here is a program that generates a JSON document with ArduinoJson:
+
+```c++
+DynamicJsonDocument doc(1024);
+
+doc["sensor"] = "gps";
+doc["time"]   = 1351824120;
+doc["data"][0] = 48.756080;
+doc["data"][1] = 2.302038;
+
+serializeJson(doc, Serial);
+// This prints:
+// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
+```
+
+See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme)
+
+## Support the project
+
+Do you like this library? Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)!
+
+What? You don't like it but you *love* it?  
+We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SUPPORT.md	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,27 @@
+# ArduinoJson Support
+
+First off, thank you very much for using ArduinoJson.
+
+We'll be very happy to help you, but first please read the following.
+
+## Before asking for help
+
+1. Read the [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=support)
+2. Search in the [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=support)
+
+If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new).
+
+It is OK to add a comment to a currently opened issue, but please avoid adding comments to a closed issue.
+
+## Before hitting the Submit button
+
+Please provide all the relevant information:
+
+* Good title
+* Short description of the problem
+* Target platform
+* Compiler model and version
+* [MVCE](https://stackoverflow.com/help/mcve)
+* Compiler output
+
+Good questions get fast answers!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/component.mk	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,1 @@
+COMPONENT_ADD_INCLUDEDIRS := src
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keywords.txt	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,40 @@
+# Macros
+JSON_ARRAY_SIZE	KEYWORD2
+JSON_OBJECT_SIZE	KEYWORD2
+JSON_STRING_SIZE	KEYWORD2
+
+# Free functions
+deserializeJson	KEYWORD2
+deserializeMsgPack	KEYWORD2
+serialized	KEYWORD2
+serializeJson	KEYWORD2
+serializeJsonPretty	KEYWORD2
+serializeMsgPack	KEYWORD2
+measureJson	KEYWORD2
+measureJsonPretty	KEYWORD2
+measureMsgPack	KEYWORD2
+
+# Methods
+add	KEYWORD2
+as	KEYWORD2
+createNestedArray	KEYWORD2
+createNestedObject	KEYWORD2
+get	KEYWORD2
+set	KEYWORD2
+to	KEYWORD2
+
+# Type names
+DeserializationError	KEYWORD1	DATA_TYPE
+DynamicJsonDocument	KEYWORD1	DATA_TYPE
+JsonArray	KEYWORD1	DATA_TYPE
+JsonArrayConst	KEYWORD1	DATA_TYPE
+JsonDocument	KEYWORD1	DATA_TYPE
+JsonFloat	KEYWORD1	DATA_TYPE
+JsonInteger	KEYWORD1	DATA_TYPE
+JsonObject	KEYWORD1	DATA_TYPE
+JsonObjectConst	KEYWORD1	DATA_TYPE
+JsonString	KEYWORD1	DATA_TYPE
+JsonUInt	KEYWORD1	DATA_TYPE
+JsonVariant	KEYWORD1	DATA_TYPE
+JsonVariantConst	KEYWORD1	DATA_TYPE
+StaticJsonDocument	KEYWORD1	DATA_TYPE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/library.json	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,21 @@
+{
+  "name": "ArduinoJson",
+  "keywords": "json, rest, http, web",
+  "description": "A simple and efficient JSON library for embedded C++. ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ MessagePack, ✔ fixed allocation, ✔ zero-copy, ✔ streams, ✔ filtering, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.",
+  "homepage": "https://arduinojson.org/?utm_source=meta&utm_medium=library.json",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/bblanchon/ArduinoJson.git"
+  },
+  "version": "6.17.2",
+  "authors": {
+    "name": "Benoit Blanchon",
+    "url": "https://blog.benoitblanchon.fr"
+  },
+  "exclude": [
+    ".github",
+    "extras"
+  ],
+  "frameworks": "arduino",
+  "platforms": "*"
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson.h	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,17 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#ifdef __cplusplus
+
+#include "ArduinoJson.hpp"
+
+using namespace ArduinoJson;
+
+#else
+
+#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,73 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "ArduinoJson/Configuration.hpp"
+
+#if !ARDUINOJSON_DEBUG
+#ifdef __clang__
+#pragma clang system_header
+#elif defined __GNUC__
+#pragma GCC system_header
+#endif
+#endif
+
+#include "ArduinoJson/Array/ArrayRef.hpp"
+#include "ArduinoJson/Object/ObjectRef.hpp"
+#include "ArduinoJson/Variant/VariantRef.hpp"
+
+#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
+#include "ArduinoJson/Document/StaticJsonDocument.hpp"
+
+#include "ArduinoJson/Array/ArrayImpl.hpp"
+#include "ArduinoJson/Array/ElementProxy.hpp"
+#include "ArduinoJson/Array/Utilities.hpp"
+#include "ArduinoJson/Collection/CollectionImpl.hpp"
+#include "ArduinoJson/Object/MemberProxy.hpp"
+#include "ArduinoJson/Object/ObjectImpl.hpp"
+#include "ArduinoJson/Variant/VariantAsImpl.hpp"
+#include "ArduinoJson/Variant/VariantCompare.hpp"
+#include "ArduinoJson/Variant/VariantImpl.hpp"
+
+#include "ArduinoJson/Json/JsonDeserializer.hpp"
+#include "ArduinoJson/Json/JsonSerializer.hpp"
+#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
+#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
+#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
+
+#include "ArduinoJson/compatibility.hpp"
+
+namespace ArduinoJson {
+typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
+typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
+typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
+typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
+typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
+typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
+typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
+typedef ARDUINOJSON_NAMESPACE::PairConst JsonPairConst;
+typedef ARDUINOJSON_NAMESPACE::String JsonString;
+typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
+typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
+typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
+using ARDUINOJSON_NAMESPACE::BasicJsonDocument;
+using ARDUINOJSON_NAMESPACE::copyArray;
+using ARDUINOJSON_NAMESPACE::DeserializationError;
+using ARDUINOJSON_NAMESPACE::deserializeJson;
+using ARDUINOJSON_NAMESPACE::deserializeMsgPack;
+using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
+using ARDUINOJSON_NAMESPACE::JsonDocument;
+using ARDUINOJSON_NAMESPACE::measureJson;
+using ARDUINOJSON_NAMESPACE::serialized;
+using ARDUINOJSON_NAMESPACE::serializeJson;
+using ARDUINOJSON_NAMESPACE::serializeJsonPretty;
+using ARDUINOJSON_NAMESPACE::serializeMsgPack;
+using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
+
+namespace DeserializationOption {
+using ARDUINOJSON_NAMESPACE::Filter;
+using ARDUINOJSON_NAMESPACE::NestingLimit;
+}  // namespace DeserializationOption
+}  // namespace ArduinoJson
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Array/ArrayFunctions.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,31 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Collection/CollectionData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) {
+  return arr ? arr->addElement(pool) : 0;
+}
+
+template <typename TVisitor>
+inline typename TVisitor::result_type arrayAccept(const CollectionData *arr,
+                                                  TVisitor &visitor) {
+  if (arr)
+    return visitor.visitArray(*arr);
+  else
+    return visitor.visitNull();
+}
+
+inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
+  if (lhs == rhs)
+    return true;
+  if (!lhs || !rhs)
+    return false;
+  return lhs->equalsArray(*rhs);
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Array/ArrayImpl.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,28 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayRef.hpp>
+#include <ArduinoJson/Object/ObjectRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TArray>
+inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const {
+  return impl()->addElement().template to<ArrayRef>();
+}
+
+template <typename TArray>
+inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
+  return impl()->addElement().template to<ObjectRef>();
+}
+
+template <typename TArray>
+inline ElementProxy<TArray> ArrayShortcuts<TArray>::operator[](
+    size_t index) const {
+  return ElementProxy<TArray>(*impl(), index);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Array/ArrayIterator.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,121 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Variant/SlotFunctions.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class VariantPtr {
+ public:
+  VariantPtr(MemoryPool *pool, VariantData *data) : _variant(pool, data) {}
+
+  VariantRef *operator->() {
+    return &_variant;
+  }
+
+  VariantRef &operator*() {
+    return _variant;
+  }
+
+ private:
+  VariantRef _variant;
+};
+
+class ArrayIterator {
+ public:
+  ArrayIterator() : _slot(0) {}
+  explicit ArrayIterator(MemoryPool *pool, VariantSlot *slot)
+      : _pool(pool), _slot(slot) {}
+
+  VariantRef operator*() const {
+    return VariantRef(_pool, _slot->data());
+  }
+  VariantPtr operator->() {
+    return VariantPtr(_pool, _slot->data());
+  }
+
+  bool operator==(const ArrayIterator &other) const {
+    return _slot == other._slot;
+  }
+
+  bool operator!=(const ArrayIterator &other) const {
+    return _slot != other._slot;
+  }
+
+  ArrayIterator &operator++() {
+    _slot = _slot->next();
+    return *this;
+  }
+
+  ArrayIterator &operator+=(size_t distance) {
+    _slot = _slot->next(distance);
+    return *this;
+  }
+
+  VariantSlot *internal() {
+    return _slot;
+  }
+
+ private:
+  MemoryPool *_pool;
+  VariantSlot *_slot;
+};
+
+class VariantConstPtr {
+ public:
+  VariantConstPtr(const VariantData *data) : _variant(data) {}
+
+  VariantConstRef *operator->() {
+    return &_variant;
+  }
+
+  VariantConstRef &operator*() {
+    return _variant;
+  }
+
+ private:
+  VariantConstRef _variant;
+};
+
+class ArrayConstRefIterator {
+ public:
+  ArrayConstRefIterator() : _slot(0) {}
+  explicit ArrayConstRefIterator(const VariantSlot *slot) : _slot(slot) {}
+
+  VariantConstRef operator*() const {
+    return VariantConstRef(_slot->data());
+  }
+  VariantConstPtr operator->() {
+    return VariantConstPtr(_slot->data());
+  }
+
+  bool operator==(const ArrayConstRefIterator &other) const {
+    return _slot == other._slot;
+  }
+
+  bool operator!=(const ArrayConstRefIterator &other) const {
+    return _slot != other._slot;
+  }
+
+  ArrayConstRefIterator &operator++() {
+    _slot = _slot->next();
+    return *this;
+  }
+
+  ArrayConstRefIterator &operator+=(size_t distance) {
+    _slot = _slot->next(distance);
+    return *this;
+  }
+
+  const VariantSlot *internal() {
+    return _slot;
+  }
+
+ private:
+  const VariantSlot *_slot;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Array/ArrayRef.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,167 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayFunctions.hpp>
+#include <ArduinoJson/Array/ArrayIterator.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+// Returns the size (in bytes) of an array with n elements.
+// Can be very handy to determine the size of a StaticMemoryPool.
+#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
+  ((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class ObjectRef;
+template <typename>
+class ElementProxy;
+
+template <typename TData>
+class ArrayRefBase {
+ public:
+  operator VariantConstRef() const {
+    const void* data = _data;  // prevent warning cast-align
+    return VariantConstRef(reinterpret_cast<const VariantData*>(data));
+  }
+
+  template <typename TVisitor>
+  FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const {
+    return arrayAccept(_data, visitor);
+  }
+
+  FORCE_INLINE bool isNull() const {
+    return _data == 0;
+  }
+
+  FORCE_INLINE operator bool() const {
+    return _data != 0;
+  }
+
+  FORCE_INLINE size_t memoryUsage() const {
+    return _data ? _data->memoryUsage() : 0;
+  }
+
+  FORCE_INLINE size_t nesting() const {
+    return _data ? _data->nesting() : 0;
+  }
+
+  FORCE_INLINE size_t size() const {
+    return _data ? _data->size() : 0;
+  }
+
+ protected:
+  ArrayRefBase(TData* data) : _data(data) {}
+  TData* _data;
+};
+
+class ArrayConstRef : public ArrayRefBase<const CollectionData>,
+                      public Visitable {
+  friend class ArrayRef;
+  typedef ArrayRefBase<const CollectionData> base_type;
+
+ public:
+  typedef ArrayConstRefIterator iterator;
+
+  FORCE_INLINE iterator begin() const {
+    if (!_data)
+      return iterator();
+    return iterator(_data->head());
+  }
+
+  FORCE_INLINE iterator end() const {
+    return iterator();
+  }
+
+  FORCE_INLINE ArrayConstRef() : base_type(0) {}
+  FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {}
+
+  FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
+    return arrayEquals(_data, rhs._data);
+  }
+
+  FORCE_INLINE VariantConstRef operator[](size_t index) const {
+    return getElement(index);
+  }
+
+  FORCE_INLINE VariantConstRef getElement(size_t index) const {
+    return VariantConstRef(_data ? _data->getElement(index) : 0);
+  }
+};
+
+class ArrayRef : public ArrayRefBase<CollectionData>,
+                 public ArrayShortcuts<ArrayRef>,
+                 public Visitable {
+  typedef ArrayRefBase<CollectionData> base_type;
+
+ public:
+  typedef ArrayIterator iterator;
+
+  FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {}
+  FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data)
+      : base_type(data), _pool(pool) {}
+
+  operator VariantRef() {
+    void* data = _data;  // prevent warning cast-align
+    return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
+  }
+
+  operator ArrayConstRef() const {
+    return ArrayConstRef(_data);
+  }
+
+  VariantRef addElement() const {
+    return VariantRef(_pool, arrayAdd(_data, _pool));
+  }
+
+  FORCE_INLINE iterator begin() const {
+    if (!_data)
+      return iterator();
+    return iterator(_pool, _data->head());
+  }
+
+  FORCE_INLINE iterator end() const {
+    return iterator();
+  }
+
+  // Copy a ArrayRef
+  FORCE_INLINE bool set(ArrayConstRef src) const {
+    if (!_data || !src._data)
+      return false;
+    return _data->copyFrom(*src._data, _pool);
+  }
+
+  FORCE_INLINE bool operator==(ArrayRef rhs) const {
+    return arrayEquals(_data, rhs._data);
+  }
+
+  // Internal use
+  FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
+    return VariantRef(_pool, _data ? _data->getOrAddElement(index, _pool) : 0);
+  }
+
+  // Gets the value at the specified index.
+  FORCE_INLINE VariantRef getElement(size_t index) const {
+    return VariantRef(_pool, _data ? _data->getElement(index) : 0);
+  }
+
+  // Removes element at specified position.
+  FORCE_INLINE void remove(iterator it) const {
+    if (!_data)
+      return;
+    _data->removeSlot(it.internal());
+  }
+
+  // Removes element at specified index.
+  FORCE_INLINE void remove(size_t index) const {
+    if (!_data)
+      return;
+    _data->removeElement(index);
+  }
+
+ private:
+  MemoryPool* _pool;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Array/ArrayShortcuts.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,47 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+// Forward declarations.
+template <typename>
+class ElementProxy;
+
+template <typename TArray>
+class ArrayShortcuts {
+ public:
+  // Returns the element at specified index if the variant is an array.
+  FORCE_INLINE ElementProxy<TArray> operator[](size_t index) const;
+
+  FORCE_INLINE ObjectRef createNestedObject() const;
+
+  FORCE_INLINE ArrayRef createNestedArray() const;
+
+  // Adds the specified value at the end of the array.
+  //
+  // bool add(TValue);
+  // TValue = bool, long, int, short, float, double, serialized, VariantRef,
+  //          std::string, String, ObjectRef
+  template <typename T>
+  FORCE_INLINE bool add(const T &value) const {
+    return impl()->addElement().set(value);
+  }
+  //
+  // bool add(TValue);
+  // TValue = char*, const char*, const __FlashStringHelper*
+  template <typename T>
+  FORCE_INLINE bool add(T *value) const {
+    return impl()->addElement().set(value);
+  }
+
+ private:
+  const TArray *impl() const {
+    return static_cast<const TArray *>(this);
+  }
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Array/ElementProxy.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,181 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Variant/VariantOperators.hpp>
+#include <ArduinoJson/Variant/VariantShortcuts.hpp>
+#include <ArduinoJson/Variant/VariantTo.hpp>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4522)
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TArray>
+class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
+                     public VariantShortcuts<ElementProxy<TArray> >,
+                     public Visitable,
+                     public VariantTag {
+  typedef ElementProxy<TArray> this_type;
+
+ public:
+  typedef VariantRef variant_type;
+
+  FORCE_INLINE ElementProxy(TArray array, size_t index)
+      : _array(array), _index(index) {}
+
+  FORCE_INLINE ElementProxy(const ElementProxy& src)
+      : _array(src._array), _index(src._index) {}
+
+  FORCE_INLINE this_type& operator=(const this_type& src) {
+    getOrAddUpstreamElement().set(src.as<VariantConstRef>());
+    return *this;
+  }
+
+  // Replaces the value
+  //
+  // operator=(const TValue&)
+  // TValue = bool, long, int, short, float, double, serialized, VariantRef,
+  //          std::string, String, ArrayRef, ObjectRef
+  template <typename T>
+  FORCE_INLINE this_type& operator=(const T& src) {
+    getOrAddUpstreamElement().set(src);
+    return *this;
+  }
+  //
+  // operator=(TValue)
+  // TValue = char*, const char*, const __FlashStringHelper*
+  template <typename T>
+  FORCE_INLINE this_type& operator=(T* src) {
+    getOrAddUpstreamElement().set(src);
+    return *this;
+  }
+
+  FORCE_INLINE void clear() const {
+    getUpstreamElement().clear();
+  }
+
+  FORCE_INLINE bool isNull() const {
+    return getUpstreamElement().isNull();
+  }
+
+  template <typename T>
+  FORCE_INLINE typename VariantAs<T>::type as() const {
+    return getUpstreamElement().template as<T>();
+  }
+
+  template <typename T>
+  FORCE_INLINE operator T() const {
+    return getUpstreamElement();
+  }
+
+  template <typename T>
+  FORCE_INLINE bool is() const {
+    return getUpstreamElement().template is<T>();
+  }
+
+  template <typename T>
+  FORCE_INLINE typename VariantTo<T>::type to() const {
+    return getOrAddUpstreamElement().template to<T>();
+  }
+
+  // Replaces the value
+  //
+  // bool set(const TValue&)
+  // TValue = bool, long, int, short, float, double, serialized, VariantRef,
+  //          std::string, String, ArrayRef, ObjectRef
+  template <typename TValue>
+  FORCE_INLINE bool set(const TValue& value) const {
+    return getOrAddUpstreamElement().set(value);
+  }
+  //
+  // bool set(TValue)
+  // TValue = char*, const char*, const __FlashStringHelper*
+  template <typename TValue>
+  FORCE_INLINE bool set(TValue* value) const {
+    return getOrAddUpstreamElement().set(value);
+  }
+
+  template <typename TVisitor>
+  typename TVisitor::result_type accept(TVisitor& visitor) const {
+    return getUpstreamElement().accept(visitor);
+  }
+
+  FORCE_INLINE size_t size() const {
+    return getUpstreamElement().size();
+  }
+
+  template <typename TNestedKey>
+  VariantRef getMember(TNestedKey* key) const {
+    return getUpstreamElement().getMember(key);
+  }
+
+  template <typename TNestedKey>
+  VariantRef getMember(const TNestedKey& key) const {
+    return getUpstreamElement().getMember(key);
+  }
+
+  template <typename TNestedKey>
+  VariantRef getOrAddMember(TNestedKey* key) const {
+    return getOrAddUpstreamElement().getOrAddMember(key);
+  }
+
+  template <typename TNestedKey>
+  VariantRef getOrAddMember(const TNestedKey& key) const {
+    return getOrAddUpstreamElement().getOrAddMember(key);
+  }
+
+  VariantRef addElement() const {
+    return getOrAddUpstreamElement().addElement();
+  }
+
+  VariantRef getElement(size_t index) const {
+    return getOrAddUpstreamElement().getElement(index);
+  }
+
+  VariantRef getOrAddElement(size_t index) const {
+    return getOrAddUpstreamElement().getOrAddElement(index);
+  }
+
+  FORCE_INLINE void remove(size_t index) const {
+    getUpstreamElement().remove(index);
+  }
+  // remove(char*) const
+  // remove(const char*) const
+  // remove(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
+      TChar* key) const {
+    getUpstreamElement().remove(key);
+  }
+  // remove(const std::string&) const
+  // remove(const String&) const
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
+      const TString& key) const {
+    getUpstreamElement().remove(key);
+  }
+
+ private:
+  FORCE_INLINE VariantRef getUpstreamElement() const {
+    return _array.getElement(_index);
+  }
+
+  FORCE_INLINE VariantRef getOrAddUpstreamElement() const {
+    return _array.getOrAddElement(_index);
+  }
+
+  TArray _array;
+  const size_t _index;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Array/Utilities.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,171 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayRef.hpp>
+#include <ArduinoJson/Document/JsonDocument.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Copy a 1D array to a JsonArray
+template <typename T, size_t N, typename TDestination>
+inline typename enable_if<!is_array<T>::value &&
+                              !is_base_of<JsonDocument, TDestination>::value,
+                          bool>::type
+copyArray(T (&src)[N], const TDestination& dst) {
+  return copyArray(src, N, dst);
+}
+
+// Copy a 1D array to a JsonDocument
+template <typename T, size_t N>
+inline bool copyArray(T (&src)[N], JsonDocument& dst) {
+  return copyArray(src, dst.to<ArrayRef>());
+}
+
+// Copy a 1D array to a JsonArray
+template <typename T, typename TDestination>
+inline typename enable_if<!is_array<T>::value &&
+                              !is_base_of<JsonDocument, TDestination>::value,
+                          bool>::type
+copyArray(T* src, size_t len, const TDestination& dst) {
+  bool ok = true;
+  for (size_t i = 0; i < len; i++) {
+    ok &= dst.add(src[i]);
+  }
+  return ok;
+}
+
+// Copy a 1D array to a JsonDocument
+template <typename T>
+inline bool copyArray(T* src, size_t len, JsonDocument& dst) {
+  return copyArray(src, len, dst.to<ArrayRef>());
+}
+
+// Copy a 2D array to a JsonArray
+template <typename T, size_t N1, size_t N2, typename TDestination>
+inline typename enable_if<!is_base_of<JsonDocument, TDestination>::value,
+                          bool>::type
+copyArray(T (&src)[N1][N2], const TDestination& dst) {
+  bool ok = true;
+  for (size_t i = 0; i < N1; i++) {
+    ArrayRef nestedArray = dst.createNestedArray();
+    for (size_t j = 0; j < N2; j++) {
+      ok &= nestedArray.add(src[i][j]);
+    }
+  }
+  return ok;
+}
+
+// Copy a 2D array to a JsonDocument
+template <typename T, size_t N1, size_t N2>
+inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) {
+  return copyArray(src, dst.to<ArrayRef>());
+}
+
+template <typename T>
+class ArrayCopier1D : public Visitor<size_t> {
+ public:
+  ArrayCopier1D(T* destination, size_t capacity)
+      : _destination(destination), _capacity(capacity) {}
+
+  size_t visitArray(const CollectionData& array) {
+    size_t size = 0;
+    VariantSlot* slot = array.head();
+
+    while (slot != 0 && size < _capacity) {
+      _destination[size++] = variantAs<T>(slot->data());
+      slot = slot->next();
+    }
+    return size;
+  }
+
+  size_t visitObject(const CollectionData&) {
+    return 0;
+  }
+
+  size_t visitFloat(Float) {
+    return 0;
+  }
+
+  size_t visitString(const char*) {
+    return 0;
+  }
+
+  size_t visitRawJson(const char*, size_t) {
+    return 0;
+  }
+
+  size_t visitNegativeInteger(UInt) {
+    return 0;
+  }
+
+  size_t visitPositiveInteger(UInt) {
+    return 0;
+  }
+
+  size_t visitBoolean(bool) {
+    return 0;
+  }
+
+  size_t visitNull() {
+    return 0;
+  }
+
+ private:
+  T* _destination;
+  size_t _capacity;
+};
+
+template <typename T, size_t N1, size_t N2>
+class ArrayCopier2D : public Visitor<void> {
+ public:
+  ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {}
+
+  void visitArray(const CollectionData& array) {
+    VariantSlot* slot = array.head();
+    size_t n = 0;
+    while (slot != 0 && n < N1) {
+      ArrayCopier1D<T> copier((*_destination)[n++], N2);
+      variantAccept(slot->data(), copier);
+      slot = slot->next();
+    }
+  }
+  void visitObject(const CollectionData&) {}
+  void visitFloat(Float) {}
+  void visitString(const char*) {}
+  void visitRawJson(const char*, size_t) {}
+  void visitNegativeInteger(UInt) {}
+  void visitPositiveInteger(UInt) {}
+  void visitBoolean(bool) {}
+  void visitNull() {}
+
+ private:
+  T (*_destination)[N1][N2];
+  size_t _capacity1, _capacity2;
+};
+
+// Copy a JsonArray to a 1D array
+template <typename TSource, typename T, size_t N>
+inline typename enable_if<!is_array<T>::value, size_t>::type copyArray(
+    const TSource& src, T (&dst)[N]) {
+  return copyArray(src, dst, N);
+}
+
+// Copy a JsonArray to a 1D array
+template <typename TSource, typename T>
+inline size_t copyArray(const TSource& src, T* dst, size_t len) {
+  ArrayCopier1D<T> copier(dst, len);
+
+  return src.accept(copier);
+}
+
+// Copy a JsonArray to a 2D array
+template <typename TSource, typename T, size_t N1, size_t N2>
+inline void copyArray(const TSource& src, T (&dst)[N1][N2]) {
+  ArrayCopier2D<T, N1, N2> copier(&dst);
+  src.accept(copier);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Collection/CollectionData.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,88 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+
+#include <stddef.h>  // size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class MemoryPool;
+class VariantData;
+class VariantSlot;
+
+class CollectionData {
+  VariantSlot *_head;
+  VariantSlot *_tail;
+
+ public:
+  // Must be a POD!
+  // - no constructor
+  // - no destructor
+  // - no virtual
+  // - no inheritance
+
+  // Array only
+
+  VariantData *addElement(MemoryPool *pool);
+
+  VariantData *getElement(size_t index) const;
+
+  VariantData *getOrAddElement(size_t index, MemoryPool *pool);
+
+  void removeElement(size_t index);
+
+  bool equalsArray(const CollectionData &other) const;
+
+  // Object only
+
+  template <typename TAdaptedString>
+  VariantData *addMember(TAdaptedString key, MemoryPool *pool);
+
+  template <typename TAdaptedString>
+  VariantData *getMember(TAdaptedString key) const;
+
+  template <typename TAdaptedString>
+  VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool);
+
+  template <typename TAdaptedString>
+  void removeMember(TAdaptedString key) {
+    removeSlot(getSlot(key));
+  }
+
+  template <typename TAdaptedString>
+  bool containsKey(const TAdaptedString &key) const;
+
+  bool equalsObject(const CollectionData &other) const;
+
+  // Generic
+
+  void clear();
+  size_t memoryUsage() const;
+  size_t nesting() const;
+  size_t size() const;
+
+  VariantSlot *addSlot(MemoryPool *);
+  void removeSlot(VariantSlot *slot);
+
+  bool copyFrom(const CollectionData &src, MemoryPool *pool);
+
+  VariantSlot *head() const {
+    return _head;
+  }
+
+  void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance);
+
+ private:
+  VariantSlot *getSlot(size_t index) const;
+
+  template <typename TAdaptedString>
+  VariantSlot *getSlot(TAdaptedString key) const;
+
+  VariantSlot *getPreviousSlot(VariantSlot *) const;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Collection/CollectionImpl.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,232 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Collection/CollectionData.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+inline bool variantEquals(const VariantData* a, const VariantData* b) {
+  return variantCompare(a, b) == COMPARE_RESULT_EQUAL;
+}
+
+inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
+  VariantSlot* slot = pool->allocVariant();
+  if (!slot)
+    return 0;
+
+  if (_tail) {
+    _tail->setNextNotNull(slot);
+    _tail = slot;
+  } else {
+    _head = slot;
+    _tail = slot;
+  }
+
+  slot->clear();
+  return slot;
+}
+
+inline VariantData* CollectionData::addElement(MemoryPool* pool) {
+  return slotData(addSlot(pool));
+}
+
+template <typename TAdaptedString>
+inline VariantData* CollectionData::addMember(TAdaptedString key,
+                                              MemoryPool* pool) {
+  VariantSlot* slot = addSlot(pool);
+  if (!slotSetKey(slot, key, pool)) {
+    removeSlot(slot);
+    return 0;
+  }
+  return slot->data();
+}
+
+inline void CollectionData::clear() {
+  _head = 0;
+  _tail = 0;
+}
+
+template <typename TAdaptedString>
+inline bool CollectionData::containsKey(const TAdaptedString& key) const {
+  return getSlot(key) != 0;
+}
+
+inline bool CollectionData::copyFrom(const CollectionData& src,
+                                     MemoryPool* pool) {
+  clear();
+  for (VariantSlot* s = src._head; s; s = s->next()) {
+    VariantData* var;
+    if (s->key() != 0) {
+      if (s->ownsKey())
+        var = addMember(RamStringAdapter(s->key()), pool);
+      else
+        var = addMember(ConstRamStringAdapter(s->key()), pool);
+    } else {
+      var = addElement(pool);
+    }
+    if (!var)
+      return false;
+    if (!var->copyFrom(*s->data(), pool))
+      return false;
+  }
+  return true;
+}
+
+inline bool CollectionData::equalsObject(const CollectionData& other) const {
+  size_t count = 0;
+  for (VariantSlot* slot = _head; slot; slot = slot->next()) {
+    VariantData* v1 = slot->data();
+    VariantData* v2 = other.getMember(adaptString(slot->key()));
+    if (!variantEquals(v1, v2))
+      return false;
+    count++;
+  }
+  return count == other.size();
+}
+
+inline bool CollectionData::equalsArray(const CollectionData& other) const {
+  VariantSlot* s1 = _head;
+  VariantSlot* s2 = other._head;
+  for (;;) {
+    if (s1 == s2)
+      return true;
+    if (!s1 || !s2)
+      return false;
+    if (!variantEquals(s1->data(), s2->data()))
+      return false;
+    s1 = s1->next();
+    s2 = s2->next();
+  }
+}
+
+template <typename TAdaptedString>
+inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
+  VariantSlot* slot = _head;
+  while (slot) {
+    if (key.equals(slot->key()))
+      break;
+    slot = slot->next();
+  }
+  return slot;
+}
+
+inline VariantSlot* CollectionData::getSlot(size_t index) const {
+  return _head->next(index);
+}
+
+inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
+  VariantSlot* current = _head;
+  while (current) {
+    VariantSlot* next = current->next();
+    if (next == target)
+      return current;
+    current = next;
+  }
+  return 0;
+}
+
+template <typename TAdaptedString>
+inline VariantData* CollectionData::getMember(TAdaptedString key) const {
+  VariantSlot* slot = getSlot(key);
+  return slot ? slot->data() : 0;
+}
+
+template <typename TAdaptedString>
+inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
+                                                   MemoryPool* pool) {
+  // ignore null key
+  if (key.isNull())
+    return 0;
+
+  // search a matching key
+  VariantSlot* slot = getSlot(key);
+  if (slot)
+    return slot->data();
+
+  return addMember(key, pool);
+}
+
+inline VariantData* CollectionData::getElement(size_t index) const {
+  VariantSlot* slot = getSlot(index);
+  return slot ? slot->data() : 0;
+}
+
+inline VariantData* CollectionData::getOrAddElement(size_t index,
+                                                    MemoryPool* pool) {
+  VariantSlot* slot = _head;
+  while (slot && index > 0) {
+    slot = slot->next();
+    index--;
+  }
+  if (!slot)
+    index++;
+  while (index > 0) {
+    slot = addSlot(pool);
+    index--;
+  }
+  return slotData(slot);
+}
+
+inline void CollectionData::removeSlot(VariantSlot* slot) {
+  if (!slot)
+    return;
+  VariantSlot* prev = getPreviousSlot(slot);
+  VariantSlot* next = slot->next();
+  if (prev)
+    prev->setNext(next);
+  else
+    _head = next;
+  if (!next)
+    _tail = prev;
+}
+
+inline void CollectionData::removeElement(size_t index) {
+  removeSlot(getSlot(index));
+}
+
+inline size_t CollectionData::memoryUsage() const {
+  size_t total = 0;
+  for (VariantSlot* s = _head; s; s = s->next()) {
+    total += sizeof(VariantSlot) + s->data()->memoryUsage();
+    if (s->ownsKey())
+      total += strlen(s->key()) + 1;
+  }
+  return total;
+}
+
+inline size_t CollectionData::nesting() const {
+  size_t maxChildNesting = 0;
+  for (VariantSlot* s = _head; s; s = s->next()) {
+    size_t childNesting = s->data()->nesting();
+    if (childNesting > maxChildNesting)
+      maxChildNesting = childNesting;
+  }
+  return maxChildNesting + 1;
+}
+
+inline size_t CollectionData::size() const {
+  return slotSize(_head);
+}
+
+template <typename T>
+inline void movePointer(T*& p, ptrdiff_t offset) {
+  if (!p)
+    return;
+  p = reinterpret_cast<T*>(
+      reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset));
+  ARDUINOJSON_ASSERT(isAligned(p));
+}
+
+inline void CollectionData::movePointers(ptrdiff_t stringDistance,
+                                         ptrdiff_t variantDistance) {
+  movePointer(_head, variantDistance);
+  movePointer(_tail, variantDistance);
+  for (VariantSlot* slot = _head; slot; slot = slot->next())
+    slot->movePointers(stringDistance, variantDistance);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Configuration.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,255 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#if __cplusplus >= 201103L
+#define ARDUINOJSON_HAS_LONG_LONG 1
+#define ARDUINOJSON_HAS_NULLPTR 1
+#define ARDUINOJSON_HAS_RVALUE_REFERENCES 1
+#else
+#define ARDUINOJSON_HAS_LONG_LONG 0
+#define ARDUINOJSON_HAS_NULLPTR 0
+#define ARDUINOJSON_HAS_RVALUE_REFERENCES 0
+#endif
+
+#if defined(_MSC_VER) && !ARDUINOJSON_HAS_LONG_LONG
+#define ARDUINOJSON_HAS_INT64 1
+#else
+#define ARDUINOJSON_HAS_INT64 0
+#endif
+
+// Small or big machine?
+#ifndef ARDUINOJSON_EMBEDDED_MODE
+#if defined(ARDUINO)                /* Arduino*/                 \
+    || defined(__IAR_SYSTEMS_ICC__) /* IAR Embedded Workbench */ \
+    || defined(__XC)                /* MPLAB XC compiler */      \
+    || defined(__ARMCC_VERSION)     /* Keil ARM Compiler */      \
+    || defined(__AVR)               /* Atmel AVR8/GNU C Compiler */
+#define ARDUINOJSON_EMBEDDED_MODE 1
+#else
+#define ARDUINOJSON_EMBEDDED_MODE 0
+#endif
+#endif
+
+// Auto enable std::stream if the right headers are here and no conflicting
+// macro is defined
+#if !defined(ARDUINOJSON_ENABLE_STD_STREAM) && defined(__has_include)
+#if __has_include(<istream>) && \
+    __has_include(<ostream>) && \
+    !defined(min) && \
+    !defined(max)
+#define ARDUINOJSON_ENABLE_STD_STREAM 1
+#else
+#define ARDUINOJSON_ENABLE_STD_STREAM 0
+#endif
+#endif
+
+// Auto enable std::string if the right header is here and no conflicting
+// macro is defined
+#if !defined(ARDUINOJSON_ENABLE_STD_STRING) && defined(__has_include)
+#if __has_include(<string>) && !defined(min) && !defined(max)
+#define ARDUINOJSON_ENABLE_STD_STRING 1
+#else
+#define ARDUINOJSON_ENABLE_STD_STRING 0
+#endif
+#endif
+
+#if ARDUINOJSON_EMBEDDED_MODE
+
+// Store floats by default to reduce the memory usage (issue #134)
+#ifndef ARDUINOJSON_USE_DOUBLE
+#define ARDUINOJSON_USE_DOUBLE 0
+#endif
+
+// Store longs by default, because they usually match the size of a float.
+#ifndef ARDUINOJSON_USE_LONG_LONG
+#define ARDUINOJSON_USE_LONG_LONG 0
+#endif
+
+// Embedded systems usually don't have std::string
+#ifndef ARDUINOJSON_ENABLE_STD_STRING
+#define ARDUINOJSON_ENABLE_STD_STRING 0
+#endif
+
+// Embedded systems usually don't have std::stream
+#ifndef ARDUINOJSON_ENABLE_STD_STREAM
+#define ARDUINOJSON_ENABLE_STD_STREAM 0
+#endif
+
+// Limit nesting as the stack is likely to be small
+#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
+#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
+#endif
+
+// Number of bits to store the pointer to next node
+// (saves RAM but limits the number of values in a document)
+#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE
+#if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 2
+// Address space == 16-bit => max 127 values
+#define ARDUINOJSON_SLOT_OFFSET_SIZE 1
+#else
+// Address space > 16-bit => max 32767 values
+#define ARDUINOJSON_SLOT_OFFSET_SIZE 2
+#endif
+#endif
+
+#else  // ARDUINOJSON_EMBEDDED_MODE
+
+// On a computer we have plenty of memory so we can use doubles
+#ifndef ARDUINOJSON_USE_DOUBLE
+#define ARDUINOJSON_USE_DOUBLE 1
+#endif
+
+// Use long long when available
+#ifndef ARDUINOJSON_USE_LONG_LONG
+#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64
+#define ARDUINOJSON_USE_LONG_LONG 1
+#else
+#define ARDUINOJSON_USE_LONG_LONG 0
+#endif
+#endif
+
+// On a computer, we can use std::string
+#ifndef ARDUINOJSON_ENABLE_STD_STRING
+#define ARDUINOJSON_ENABLE_STD_STRING 1
+#endif
+
+// On a computer, we can assume std::stream
+#ifndef ARDUINOJSON_ENABLE_STD_STREAM
+#define ARDUINOJSON_ENABLE_STD_STREAM 1
+#endif
+
+// On a computer, the stack is large so we can increase nesting limit
+#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
+#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
+#endif
+
+// Number of bits to store the pointer to next node
+#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE
+#define ARDUINOJSON_SLOT_OFFSET_SIZE 4
+#endif
+
+#endif  // ARDUINOJSON_EMBEDDED_MODE
+
+#ifdef ARDUINO
+
+#include <Arduino.h>
+
+// Enable support for Arduino's String class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
+#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
+#endif
+
+// Enable support for Arduino's Stream class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
+#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
+#endif
+
+// Enable support for Arduino's Print class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
+#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1
+#endif
+
+#else  // ARDUINO
+
+// Disable support for Arduino's String class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
+#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
+#endif
+
+// Disable support for Arduino's Stream class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
+#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
+#endif
+
+// Disable support for Arduino's Print class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
+#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
+#endif
+
+#endif  // ARDUINO
+
+#ifndef ARDUINOJSON_ENABLE_PROGMEM
+#if defined(PROGMEM) && defined(pgm_read_byte) && defined(pgm_read_dword) && \
+    defined(pgm_read_ptr) && defined(pgm_read_float)
+#define ARDUINOJSON_ENABLE_PROGMEM 1
+#else
+#define ARDUINOJSON_ENABLE_PROGMEM 0
+#endif
+#endif
+
+// Convert unicode escape sequence (\u0123) to UTF-8
+#ifndef ARDUINOJSON_DECODE_UNICODE
+#define ARDUINOJSON_DECODE_UNICODE 1
+#endif
+
+// Ignore comments in input
+#ifndef ARDUINOJSON_ENABLE_COMMENTS
+#define ARDUINOJSON_ENABLE_COMMENTS 0
+#endif
+
+// Support NaN in JSON
+#ifndef ARDUINOJSON_ENABLE_NAN
+#define ARDUINOJSON_ENABLE_NAN 0
+#endif
+
+// Support Infinity in JSON
+#ifndef ARDUINOJSON_ENABLE_INFINITY
+#define ARDUINOJSON_ENABLE_INFINITY 0
+#endif
+
+// Control the exponentiation threshold for big numbers
+// CAUTION: cannot be more that 1e9 !!!!
+#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
+#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
+#endif
+
+// Control the exponentiation threshold for small numbers
+#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
+#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
+#endif
+
+#ifndef ARDUINOJSON_LITTLE_ENDIAN
+#if defined(_MSC_VER) ||                                                      \
+    (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
+    defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64)
+#define ARDUINOJSON_LITTLE_ENDIAN 1
+#else
+#define ARDUINOJSON_LITTLE_ENDIAN 0
+#endif
+#endif
+
+#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
+#if defined(__AVR)
+#define ARDUINOJSON_ENABLE_ALIGNMENT 0
+#else
+#define ARDUINOJSON_ENABLE_ALIGNMENT 1
+#endif
+#endif
+
+#ifndef ARDUINOJSON_TAB
+#define ARDUINOJSON_TAB "  "
+#endif
+
+#ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
+#define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1
+#endif
+
+#ifndef ARDUINOJSON_STRING_BUFFER_SIZE
+#define ARDUINOJSON_STRING_BUFFER_SIZE 32
+#endif
+
+#ifndef ARDUINOJSON_DEBUG
+#ifdef __PLATFORMIO_BUILD_DEBUG__
+#define ARDUINOJSON_DEBUG 1
+#else
+#define ARDUINOJSON_DEBUG 0
+#endif
+#endif
+
+#if ARDUINOJSON_HAS_NULLPTR && defined(nullptr)
+#error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
+// See https://github.com/bblanchon/ArduinoJson/issues/1355
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/DeserializationError.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,125 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/preprocessor.hpp>
+#include <ArduinoJson/Polyfills/static_array.hpp>
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+#include <ostream>
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class DeserializationError {
+  // safe bool idiom
+  typedef void (DeserializationError::*bool_type)() const;
+  void safeBoolHelper() const {}
+
+ public:
+  enum Code {
+    Ok,
+    EmptyInput,
+    IncompleteInput,
+    InvalidInput,
+    NoMemory,
+    NotSupported,
+    TooDeep
+  };
+
+  DeserializationError() {}
+  DeserializationError(Code c) : _code(c) {}
+
+  // Compare with DeserializationError
+  friend bool operator==(const DeserializationError& lhs,
+                         const DeserializationError& rhs) {
+    return lhs._code == rhs._code;
+  }
+  friend bool operator!=(const DeserializationError& lhs,
+                         const DeserializationError& rhs) {
+    return lhs._code != rhs._code;
+  }
+
+  // Compare with Code
+  friend bool operator==(const DeserializationError& lhs, Code rhs) {
+    return lhs._code == rhs;
+  }
+  friend bool operator==(Code lhs, const DeserializationError& rhs) {
+    return lhs == rhs._code;
+  }
+  friend bool operator!=(const DeserializationError& lhs, Code rhs) {
+    return lhs._code != rhs;
+  }
+  friend bool operator!=(Code lhs, const DeserializationError& rhs) {
+    return lhs != rhs._code;
+  }
+
+  // Behaves like a bool
+  operator bool_type() const {
+    return _code != Ok ? &DeserializationError::safeBoolHelper : 0;
+  }
+  friend bool operator==(bool value, const DeserializationError& err) {
+    return static_cast<bool>(err) == value;
+  }
+  friend bool operator==(const DeserializationError& err, bool value) {
+    return static_cast<bool>(err) == value;
+  }
+  friend bool operator!=(bool value, const DeserializationError& err) {
+    return static_cast<bool>(err) != value;
+  }
+  friend bool operator!=(const DeserializationError& err, bool value) {
+    return static_cast<bool>(err) != value;
+  }
+
+  // Returns internal enum, useful for switch statement
+  Code code() const {
+    return _code;
+  }
+
+  const char* c_str() const {
+    static const char* messages[] = {
+        "Ok",       "EmptyInput",   "IncompleteInput", "InvalidInput",
+        "NoMemory", "NotSupported", "TooDeep"};
+    ARDUINOJSON_ASSERT(static_cast<size_t>(_code) <
+                       sizeof(messages) / sizeof(messages[0]));
+    return messages[_code];
+  }
+
+#if ARDUINOJSON_ENABLE_PROGMEM
+  const __FlashStringHelper* f_str() const {
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s0, "Ok");
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s1, "EmptyInput");
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s2, "IncompleteInput");
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s3, "InvalidInput");
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s4, "NoMemory");
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s5, "NotSupported");
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s6, "TooDeep");
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(
+        const char*, messages,
+        ARDUINOJSON_EXPAND7({s0, s1, s2, s3, s4, s5, s6}));
+    return ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages,
+                                         _code);
+  }
+#endif
+
+ private:
+  Code _code;
+};
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+inline std::ostream& operator<<(std::ostream& s,
+                                const DeserializationError& e) {
+  s << e.c_str();
+  return s;
+}
+
+inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
+  s << DeserializationError(c).c_str();
+  return s;
+}
+#endif
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/Filter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,66 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class Filter {
+ public:
+  explicit Filter(VariantConstRef v) : _variant(v) {}
+
+  bool allow() const {
+    return _variant;
+  }
+
+  bool allowArray() const {
+    return _variant == true || _variant.is<ArrayRef>();
+  }
+
+  bool allowObject() const {
+    return _variant == true || _variant.is<ObjectRef>();
+  }
+
+  bool allowValue() const {
+    return _variant == true;
+  }
+
+  template <typename TKey>
+  Filter operator[](const TKey& key) const {
+    if (_variant == true)  // "true" means "allow recursively"
+      return *this;
+    else
+      return Filter(_variant[key] | _variant["*"]);
+  }
+
+ private:
+  VariantConstRef _variant;
+};
+
+struct AllowAllFilter {
+  bool allow() const {
+    return true;
+  }
+
+  bool allowArray() const {
+    return true;
+  }
+
+  bool allowObject() const {
+    return true;
+  }
+
+  bool allowValue() const {
+    return true;
+  }
+
+  template <typename TKey>
+  AllowAllFilter operator[](const TKey&) const {
+    return AllowAllFilter();
+  }
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/NestingLimit.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,29 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class NestingLimit {
+ public:
+  NestingLimit() : _value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
+  explicit NestingLimit(uint8_t n) : _value(n) {}
+
+  NestingLimit decrement() const {
+    ARDUINOJSON_ASSERT(_value > 0);
+    return NestingLimit(static_cast<uint8_t>(_value - 1));
+  }
+
+  bool reached() const {
+    return _value == 0;
+  }
+
+ private:
+  uint8_t _value;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/Reader.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,56 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stdlib.h>  // for size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// The default reader is a simple wrapper for Readers that are not copiable
+template <typename TSource, typename Enable = void>
+struct Reader {
+ public:
+  Reader(TSource& source) : _source(&source) {}
+
+  int read() {
+    return _source->read();
+  }
+
+  size_t readBytes(char* buffer, size_t length) {
+    return _source->readBytes(buffer, length);
+  }
+
+ private:
+  TSource* _source;
+};
+
+template <typename TSource, typename Enable = void>
+struct BoundedReader {
+  // no default implementation because we need to pass the size to the
+  // constructor
+};
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#include <ArduinoJson/Deserialization/Readers/IteratorReader.hpp>
+#include <ArduinoJson/Deserialization/Readers/RamReader.hpp>
+#include <ArduinoJson/Deserialization/Readers/VariantReader.hpp>
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
+#include <ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+#include <ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_PROGMEM
+#include <ArduinoJson/Deserialization/Readers/FlashReader.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+#include <ArduinoJson/Deserialization/Readers/StdStreamReader.hpp>
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,31 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <Arduino.h>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TSource>
+struct Reader<TSource,
+              typename enable_if<is_base_of<Stream, TSource>::value>::type> {
+ public:
+  explicit Reader(Stream& stream) : _stream(&stream) {}
+
+  int read() {
+    // don't use _stream.read() as it ignores the timeout
+    char c;
+    return _stream->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
+  }
+
+  size_t readBytes(char* buffer, size_t length) {
+    return _stream->readBytes(buffer, length);
+  }
+
+ private:
+  Stream* _stream;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,17 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TSource>
+struct Reader<TSource,
+              typename enable_if<is_base_of< ::String, TSource>::value>::type>
+    : BoundedReader<const char*> {
+  explicit Reader(const ::String& s)
+      : BoundedReader<const char*>(s.c_str(), s.length()) {}
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/Readers/FlashReader.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,53 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <>
+struct Reader<const __FlashStringHelper*, void> {
+  const char* _ptr;
+
+ public:
+  explicit Reader(const __FlashStringHelper* ptr)
+      : _ptr(reinterpret_cast<const char*>(ptr)) {}
+
+  int read() {
+    return pgm_read_byte(_ptr++);
+  }
+
+  size_t readBytes(char* buffer, size_t length) {
+    memcpy_P(buffer, _ptr, length);
+    _ptr += length;
+    return length;
+  }
+};
+
+template <>
+struct BoundedReader<const __FlashStringHelper*, void> {
+  const char* _ptr;
+  const char* _end;
+
+ public:
+  explicit BoundedReader(const __FlashStringHelper* ptr, size_t size)
+      : _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
+
+  int read() {
+    if (_ptr < _end)
+      return pgm_read_byte(_ptr++);
+    else
+      return -1;
+  }
+
+  size_t readBytes(char* buffer, size_t length) {
+    size_t available = static_cast<size_t>(_end - _ptr);
+    if (available < length)
+      length = available;
+    memcpy_P(buffer, _ptr, length);
+    _ptr += length;
+    return length;
+  }
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/Readers/IteratorReader.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,43 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TIterator>
+class IteratorReader {
+  TIterator _ptr, _end;
+
+ public:
+  explicit IteratorReader(TIterator begin, TIterator end)
+      : _ptr(begin), _end(end) {}
+
+  int read() {
+    if (_ptr < _end)
+      return static_cast<unsigned char>(*_ptr++);
+    else
+      return -1;
+  }
+
+  size_t readBytes(char* buffer, size_t length) {
+    size_t i = 0;
+    while (i < length && _ptr < _end) buffer[i++] = *_ptr++;
+    return i;
+  }
+};
+
+template <typename T>
+struct void_ {
+  typedef void type;
+};
+
+template <typename TSource>
+struct Reader<TSource, typename void_<typename TSource::const_iterator>::type>
+    : IteratorReader<typename TSource::const_iterator> {
+  explicit Reader(const TSource& source)
+      : IteratorReader<typename TSource::const_iterator>(source.begin(),
+                                                         source.end()) {}
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/Readers/RamReader.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,50 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct IsCharOrVoid {
+  static const bool value =
+      is_same<T, void>::value || is_same<T, char>::value ||
+      is_same<T, unsigned char>::value || is_same<T, signed char>::value;
+};
+
+template <typename T>
+struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
+
+template <typename TSource>
+struct Reader<TSource*,
+              typename enable_if<IsCharOrVoid<TSource>::value>::type> {
+  const char* _ptr;
+
+ public:
+  explicit Reader(const void* ptr)
+      : _ptr(ptr ? reinterpret_cast<const char*>(ptr) : "") {}
+
+  int read() {
+    return static_cast<unsigned char>(*_ptr++);
+  }
+
+  size_t readBytes(char* buffer, size_t length) {
+    for (size_t i = 0; i < length; i++) buffer[i] = *_ptr++;
+    return length;
+  }
+};
+
+template <typename TSource>
+struct BoundedReader<TSource*,
+                     typename enable_if<IsCharOrVoid<TSource>::value>::type>
+    : public IteratorReader<const char*> {
+ public:
+  explicit BoundedReader(const void* ptr, size_t len)
+      : IteratorReader<const char*>(reinterpret_cast<const char*>(ptr),
+                                    reinterpret_cast<const char*>(ptr) + len) {}
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,29 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <istream>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TSource>
+struct Reader<TSource, typename enable_if<
+                           is_base_of<std::istream, TSource>::value>::type> {
+ public:
+  explicit Reader(std::istream& stream) : _stream(&stream) {}
+
+  int read() {
+    return _stream->get();
+  }
+
+  size_t readBytes(char* buffer, size_t length) {
+    _stream->read(buffer, static_cast<std::streamsize>(length));
+    return static_cast<size_t>(_stream->gcount());
+  }
+
+ private:
+  std::istream* _stream;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/Readers/VariantReader.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,34 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Object/MemberProxy.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TArray>
+struct Reader<ElementProxy<TArray>, void> : Reader<char*, void> {
+  explicit Reader(const ElementProxy<TArray>& x)
+      : Reader<char*, void>(x.template as<const char*>()) {}
+};
+
+template <typename TObject, typename TStringRef>
+struct Reader<MemberProxy<TObject, TStringRef>, void> : Reader<char*, void> {
+  explicit Reader(const MemberProxy<TObject, TStringRef>& x)
+      : Reader<char*, void>(x.template as<const char*>()) {}
+};
+
+template <>
+struct Reader<VariantRef, void> : Reader<char*, void> {
+  explicit Reader(VariantRef x) : Reader<char*, void>(x.as<const char*>()) {}
+};
+
+template <>
+struct Reader<VariantConstRef, void> : Reader<char*, void> {
+  explicit Reader(VariantConstRef x)
+      : Reader<char*, void>(x.as<const char*>()) {}
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Deserialization/deserialize.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,71 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Deserialization/DeserializationError.hpp>
+#include <ArduinoJson/Deserialization/Filter.hpp>
+#include <ArduinoJson/Deserialization/NestingLimit.hpp>
+#include <ArduinoJson/Deserialization/Reader.hpp>
+#include <ArduinoJson/StringStorage/StringStorage.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <template <typename, typename> class TDeserializer, typename TReader,
+          typename TWriter>
+TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
+                                                 TReader reader,
+                                                 TWriter writer) {
+  return TDeserializer<TReader, TWriter>(pool, reader, writer);
+}
+
+// deserialize(JsonDocument&, const std::string&, NestingLimit, Filter);
+// deserialize(JsonDocument&, const String&, NestingLimit, Filter);
+// deserialize(JsonDocument&, char*, NestingLimit, Filter);
+// deserialize(JsonDocument&, const char*, NestingLimit, Filter);
+// deserialize(JsonDocument&, const __FlashStringHelper*, NestingLimit, Filter);
+template <template <typename, typename> class TDeserializer, typename TString,
+          typename TFilter>
+typename enable_if<!is_array<TString>::value, DeserializationError>::type
+deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit,
+            TFilter filter) {
+  Reader<TString> reader(input);
+  doc.clear();
+  return makeDeserializer<TDeserializer>(
+             doc.memoryPool(), reader,
+             makeStringStorage(input, doc.memoryPool()))
+      .parse(doc.data(), filter, nestingLimit);
+}
+//
+// deserialize(JsonDocument&, char*, size_t, NestingLimit, Filter);
+// deserialize(JsonDocument&, const char*, size_t, NestingLimit, Filter);
+// deserialize(JsonDocument&, const __FlashStringHelper*, size_t, NL, Filter);
+template <template <typename, typename> class TDeserializer, typename TChar,
+          typename TFilter>
+DeserializationError deserialize(JsonDocument &doc, TChar *input,
+                                 size_t inputSize, NestingLimit nestingLimit,
+                                 TFilter filter) {
+  BoundedReader<TChar *> reader(input, inputSize);
+  doc.clear();
+  return makeDeserializer<TDeserializer>(
+             doc.memoryPool(), reader,
+             makeStringStorage(input, doc.memoryPool()))
+      .parse(doc.data(), filter, nestingLimit);
+}
+//
+// deserialize(JsonDocument&, std::istream&, NestingLimit, Filter);
+// deserialize(JsonDocument&, Stream&, NestingLimit, Filter);
+template <template <typename, typename> class TDeserializer, typename TStream,
+          typename TFilter>
+DeserializationError deserialize(JsonDocument &doc, TStream &input,
+                                 NestingLimit nestingLimit, TFilter filter) {
+  Reader<TStream> reader(input);
+  doc.clear();
+  return makeDeserializer<TDeserializer>(
+             doc.memoryPool(), reader,
+             makeStringStorage(input, doc.memoryPool()))
+      .parse(doc.data(), filter, nestingLimit);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Document/BasicJsonDocument.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,164 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Document/JsonDocument.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Helper to implement the "base-from-member" idiom
+// (we need to store the allocator before constructing JsonDocument)
+template <typename TAllocator>
+class AllocatorOwner {
+ public:
+  AllocatorOwner() {}
+  AllocatorOwner(const AllocatorOwner& src) : _allocator(src._allocator) {}
+  AllocatorOwner(TAllocator a) : _allocator(a) {}
+
+  void* allocate(size_t size) {
+    return _allocator.allocate(size);
+  }
+
+  void deallocate(void* ptr) {
+    if (ptr)
+      _allocator.deallocate(ptr);
+  }
+
+  void* reallocate(void* ptr, size_t new_size) {
+    return _allocator.reallocate(ptr, new_size);
+  }
+
+  TAllocator& allocator() {
+    return _allocator;
+  }
+
+ private:
+  TAllocator _allocator;
+};
+
+template <typename TAllocator>
+class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
+ public:
+  explicit BasicJsonDocument(size_t capa, TAllocator alloc = TAllocator())
+      : AllocatorOwner<TAllocator>(alloc), JsonDocument(allocPool(capa)) {}
+
+  // Copy-constructor
+  BasicJsonDocument(const BasicJsonDocument& src)
+      : AllocatorOwner<TAllocator>(src), JsonDocument() {
+    copyAssignFrom(src);
+  }
+
+  // Move-constructor
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+  BasicJsonDocument(BasicJsonDocument&& src) : AllocatorOwner<TAllocator>(src) {
+    moveAssignFrom(src);
+  }
+#endif
+
+  BasicJsonDocument(const JsonDocument& src) {
+    copyAssignFrom(src);
+  }
+
+  // Construct from variant, array, or object
+  template <typename T>
+  BasicJsonDocument(
+      const T& src,
+      typename enable_if<
+          is_same<T, VariantRef>::value || is_same<T, VariantConstRef>::value ||
+          is_same<T, ArrayRef>::value || is_same<T, ArrayConstRef>::value ||
+          is_same<T, ObjectRef>::value ||
+          is_same<T, ObjectConstRef>::value>::type* = 0)
+      : JsonDocument(allocPool(src.memoryUsage())) {
+    set(src);
+  }
+
+  // disambiguate
+  BasicJsonDocument(VariantRef src)
+      : JsonDocument(allocPool(src.memoryUsage())) {
+    set(src);
+  }
+
+  ~BasicJsonDocument() {
+    freePool();
+  }
+
+  BasicJsonDocument& operator=(const BasicJsonDocument& src) {
+    copyAssignFrom(src);
+    return *this;
+  }
+
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+  BasicJsonDocument& operator=(BasicJsonDocument&& src) {
+    moveAssignFrom(src);
+    return *this;
+  }
+#endif
+
+  template <typename T>
+  BasicJsonDocument& operator=(const T& src) {
+    reallocPoolIfTooSmall(src.memoryUsage());
+    set(src);
+    return *this;
+  }
+
+  void shrinkToFit() {
+    ptrdiff_t bytes_reclaimed = _pool.squash();
+    if (bytes_reclaimed == 0)
+      return;
+
+    void* old_ptr = _pool.buffer();
+    void* new_ptr = this->reallocate(old_ptr, _pool.capacity());
+
+    ptrdiff_t ptr_offset =
+        static_cast<char*>(new_ptr) - static_cast<char*>(old_ptr);
+
+    _pool.movePointers(ptr_offset);
+    _data.movePointers(ptr_offset, ptr_offset - bytes_reclaimed);
+  }
+
+  bool garbageCollect() {
+    // make a temporary clone and move assign
+    BasicJsonDocument tmp(*this);
+    if (!tmp.capacity())
+      return false;
+    tmp.set(*this);
+    moveAssignFrom(tmp);
+    return true;
+  }
+
+  using AllocatorOwner<TAllocator>::allocator;
+
+ private:
+  MemoryPool allocPool(size_t requiredSize) {
+    size_t capa = addPadding(requiredSize);
+    return MemoryPool(reinterpret_cast<char*>(this->allocate(capa)), capa);
+  }
+
+  void reallocPoolIfTooSmall(size_t requiredSize) {
+    if (requiredSize <= capacity())
+      return;
+    freePool();
+    replacePool(allocPool(addPadding(requiredSize)));
+  }
+
+  void freePool() {
+    this->deallocate(memoryPool().buffer());
+  }
+
+  void copyAssignFrom(const JsonDocument& src) {
+    reallocPoolIfTooSmall(src.capacity());
+    set(src);
+  }
+
+  void moveAssignFrom(BasicJsonDocument& src) {
+    freePool();
+    _data = src._data;
+    _pool = src._pool;
+    src._data.setNull();
+    src._pool = MemoryPool(0, 0);
+  }
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Document/DynamicJsonDocument.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,29 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Document/BasicJsonDocument.hpp>
+
+#include <stdlib.h>  // malloc, free
+
+namespace ARDUINOJSON_NAMESPACE {
+
+struct DefaultAllocator {
+  void* allocate(size_t size) {
+    return malloc(size);
+  }
+
+  void deallocate(void* ptr) {
+    free(ptr);
+  }
+
+  void* reallocate(void* ptr, size_t new_size) {
+    return realloc(ptr, new_size);
+  }
+};
+
+typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Document/JsonDocument.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,335 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ElementProxy.hpp>
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/Object/MemberProxy.hpp>
+#include <ArduinoJson/Object/ObjectRef.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+#include <ArduinoJson/Variant/VariantTo.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class JsonDocument : public Visitable {
+ public:
+  template <typename TVisitor>
+  typename TVisitor::result_type accept(TVisitor& visitor) const {
+    return getVariant().accept(visitor);
+  }
+
+  template <typename T>
+  typename VariantAs<T>::type as() {
+    return getVariant().template as<T>();
+  }
+
+  template <typename T>
+  typename VariantConstAs<T>::type as() const {
+    return getVariant().template as<T>();
+  }
+
+  void clear() {
+    _pool.clear();
+    _data.setNull();
+  }
+
+  template <typename T>
+  bool is() const {
+    return getVariant().template is<T>();
+  }
+
+  bool isNull() const {
+    return getVariant().isNull();
+  }
+
+  size_t memoryUsage() const {
+    return _pool.size();
+  }
+
+  bool overflowed() const {
+    return _pool.overflowed();
+  }
+
+  size_t nesting() const {
+    return _data.nesting();
+  }
+
+  size_t capacity() const {
+    return _pool.capacity();
+  }
+
+  size_t size() const {
+    return _data.size();
+  }
+
+  bool set(const JsonDocument& src) {
+    return to<VariantRef>().set(src.as<VariantRef>());
+  }
+
+  template <typename T>
+  typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set(
+      const T& src) {
+    return to<VariantRef>().set(src);
+  }
+
+  template <typename T>
+  typename VariantTo<T>::type to() {
+    clear();
+    return getVariant().template to<T>();
+  }
+
+  // for internal use only
+  MemoryPool& memoryPool() {
+    return _pool;
+  }
+
+  // for internal use only
+  VariantData& data() {
+    return _data;
+  }
+
+  ArrayRef createNestedArray() {
+    return addElement().to<ArrayRef>();
+  }
+
+  // createNestedArray(char*)
+  // createNestedArray(const char*)
+  // createNestedArray(const __FlashStringHelper*)
+  template <typename TChar>
+  ArrayRef createNestedArray(TChar* key) {
+    return getOrAddMember(key).template to<ArrayRef>();
+  }
+
+  // createNestedArray(const std::string&)
+  // createNestedArray(const String&)
+  template <typename TString>
+  ArrayRef createNestedArray(const TString& key) {
+    return getOrAddMember(key).template to<ArrayRef>();
+  }
+
+  ObjectRef createNestedObject() {
+    return addElement().to<ObjectRef>();
+  }
+
+  // createNestedObject(char*)
+  // createNestedObject(const char*)
+  // createNestedObject(const __FlashStringHelper*)
+  template <typename TChar>
+  ObjectRef createNestedObject(TChar* key) {
+    return getOrAddMember(key).template to<ObjectRef>();
+  }
+
+  // createNestedObject(const std::string&)
+  // createNestedObject(const String&)
+  template <typename TString>
+  ObjectRef createNestedObject(const TString& key) {
+    return getOrAddMember(key).template to<ObjectRef>();
+  }
+
+  // containsKey(char*) const
+  // containsKey(const char*) const
+  // containsKey(const __FlashStringHelper*) const
+  template <typename TChar>
+  bool containsKey(TChar* key) const {
+    return !getMember(key).isUndefined();
+  }
+
+  // containsKey(const std::string&) const
+  // containsKey(const String&) const
+  template <typename TString>
+  bool containsKey(const TString& key) const {
+    return !getMember(key).isUndefined();
+  }
+
+  // operator[](const std::string&)
+  // operator[](const String&)
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value,
+                                  MemberProxy<JsonDocument&, TString> >::type
+  operator[](const TString& key) {
+    return MemberProxy<JsonDocument&, TString>(*this, key);
+  }
+
+  // operator[](char*)
+  // operator[](const char*)
+  // operator[](const __FlashStringHelper*)
+  template <typename TChar>
+  FORCE_INLINE typename enable_if<IsString<TChar*>::value,
+                                  MemberProxy<JsonDocument&, TChar*> >::type
+  operator[](TChar* key) {
+    return MemberProxy<JsonDocument&, TChar*>(*this, key);
+  }
+
+  // operator[](const std::string&) const
+  // operator[](const String&) const
+  template <typename TString>
+  FORCE_INLINE
+      typename enable_if<IsString<TString>::value, VariantConstRef>::type
+      operator[](const TString& key) const {
+    return getMember(key);
+  }
+
+  // operator[](char*) const
+  // operator[](const char*) const
+  // operator[](const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE
+      typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
+      operator[](TChar* key) const {
+    return getMember(key);
+  }
+
+  FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
+    return ElementProxy<JsonDocument&>(*this, index);
+  }
+
+  FORCE_INLINE VariantConstRef operator[](size_t index) const {
+    return getElement(index);
+  }
+
+  FORCE_INLINE VariantRef getElement(size_t index) {
+    return VariantRef(&_pool, _data.getElement(index));
+  }
+
+  FORCE_INLINE VariantConstRef getElement(size_t index) const {
+    return VariantConstRef(_data.getElement(index));
+  }
+
+  FORCE_INLINE VariantRef getOrAddElement(size_t index) {
+    return VariantRef(&_pool, _data.getOrAddElement(index, &_pool));
+  }
+
+  // JsonVariantConst getMember(char*) const
+  // JsonVariantConst getMember(const char*) const
+  // JsonVariantConst getMember(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantConstRef getMember(TChar* key) const {
+    return VariantConstRef(_data.getMember(adaptString(key)));
+  }
+
+  // JsonVariantConst getMember(const std::string&) const
+  // JsonVariantConst getMember(const String&) const
+  template <typename TString>
+  FORCE_INLINE
+      typename enable_if<IsString<TString>::value, VariantConstRef>::type
+      getMember(const TString& key) const {
+    return VariantConstRef(_data.getMember(adaptString(key)));
+  }
+
+  // JsonVariant getMember(char*)
+  // JsonVariant getMember(const char*)
+  // JsonVariant getMember(const __FlashStringHelper*)
+  template <typename TChar>
+  FORCE_INLINE VariantRef getMember(TChar* key) {
+    return VariantRef(&_pool, _data.getMember(adaptString(key)));
+  }
+
+  // JsonVariant getMember(const std::string&)
+  // JsonVariant getMember(const String&)
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
+  getMember(const TString& key) {
+    return VariantRef(&_pool, _data.getMember(adaptString(key)));
+  }
+
+  // getOrAddMember(char*)
+  // getOrAddMember(const char*)
+  // getOrAddMember(const __FlashStringHelper*)
+  template <typename TChar>
+  FORCE_INLINE VariantRef getOrAddMember(TChar* key) {
+    return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
+  }
+
+  // getOrAddMember(const std::string&)
+  // getOrAddMember(const String&)
+  template <typename TString>
+  FORCE_INLINE VariantRef getOrAddMember(const TString& key) {
+    return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
+  }
+
+  FORCE_INLINE VariantRef addElement() {
+    return VariantRef(&_pool, _data.addElement(&_pool));
+  }
+
+  template <typename TValue>
+  FORCE_INLINE bool add(const TValue& value) {
+    return addElement().set(value);
+  }
+
+  // add(char*) const
+  // add(const char*) const
+  // add(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE bool add(TChar* value) {
+    return addElement().set(value);
+  }
+
+  FORCE_INLINE void remove(size_t index) {
+    _data.remove(index);
+  }
+  // remove(char*)
+  // remove(const char*)
+  // remove(const __FlashStringHelper*)
+  template <typename TChar>
+  FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
+      TChar* key) {
+    _data.remove(adaptString(key));
+  }
+  // remove(const std::string&)
+  // remove(const String&)
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
+      const TString& key) {
+    _data.remove(adaptString(key));
+  }
+
+  FORCE_INLINE operator VariantConstRef() const {
+    return VariantConstRef(&_data);
+  }
+
+  bool operator==(VariantConstRef rhs) const {
+    return getVariant() == rhs;
+  }
+
+  bool operator!=(VariantConstRef rhs) const {
+    return getVariant() != rhs;
+  }
+
+ protected:
+  JsonDocument() : _pool(0, 0) {
+    _data.setNull();
+  }
+
+  JsonDocument(MemoryPool pool) : _pool(pool) {
+    _data.setNull();
+  }
+
+  JsonDocument(char* buf, size_t capa) : _pool(buf, capa) {
+    _data.setNull();
+  }
+
+  ~JsonDocument() {}
+
+  void replacePool(MemoryPool pool) {
+    _pool = pool;
+  }
+
+  VariantRef getVariant() {
+    return VariantRef(&_pool, &_data);
+  }
+
+  VariantConstRef getVariant() const {
+    return VariantConstRef(&_data);
+  }
+
+  MemoryPool _pool;
+  VariantData _data;
+
+ private:
+  JsonDocument(const JsonDocument&);
+  JsonDocument& operator=(const JsonDocument&);
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Document/StaticJsonDocument.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,56 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Document/JsonDocument.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <size_t desiredCapacity>
+class StaticJsonDocument : public JsonDocument {
+  static const size_t _capacity =
+      AddPadding<Max<1, desiredCapacity>::value>::value;
+
+ public:
+  StaticJsonDocument() : JsonDocument(_buffer, _capacity) {}
+
+  StaticJsonDocument(const StaticJsonDocument& src)
+      : JsonDocument(_buffer, _capacity) {
+    set(src);
+  }
+
+  template <typename T>
+  StaticJsonDocument(const T& src,
+                     typename enable_if<IsVisitable<T>::value>::type* = 0)
+      : JsonDocument(_buffer, _capacity) {
+    set(src);
+  }
+
+  // disambiguate
+  StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, _capacity) {
+    set(src);
+  }
+
+  StaticJsonDocument operator=(const StaticJsonDocument& src) {
+    set(src);
+    return *this;
+  }
+
+  template <typename T>
+  StaticJsonDocument operator=(const T& src) {
+    set(src);
+    return *this;
+  }
+
+  void garbageCollect() {
+    StaticJsonDocument tmp(*this);
+    set(tmp);
+  }
+
+ private:
+  char _buffer[_capacity];
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Json/EscapeSequence.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,39 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class EscapeSequence {
+ public:
+  // Optimized for code size on a 8-bit AVR
+  static char escapeChar(char c) {
+    const char *p = escapeTable(true);
+    while (p[0] && p[1] != c) {
+      p += 2;
+    }
+    return p[0];
+  }
+
+  // Optimized for code size on a 8-bit AVR
+  static char unescapeChar(char c) {
+    const char *p = escapeTable(false);
+    for (;;) {
+      if (p[0] == '\0')
+        return 0;
+      if (p[0] == c)
+        return p[1];
+      p += 2;
+    }
+  }
+
+ private:
+  static const char *escapeTable(bool excludeSolidus) {
+    return &"//\"\"\\\\b\bf\fn\nr\rt\t"[excludeSolidus ? 2 : 0];
+  }
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Json/JsonDeserializer.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,741 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Deserialization/deserialize.hpp>
+#include <ArduinoJson/Json/EscapeSequence.hpp>
+#include <ArduinoJson/Json/Latch.hpp>
+#include <ArduinoJson/Json/Utf16.hpp>
+#include <ArduinoJson/Json/Utf8.hpp>
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/Numbers/parseNumber.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TReader, typename TStringStorage>
+class JsonDeserializer {
+ public:
+  JsonDeserializer(MemoryPool &pool, TReader reader,
+                   TStringStorage stringStorage)
+      : _stringStorage(stringStorage),
+        _foundSomething(false),
+        _latch(reader),
+        _pool(&pool),
+        _error(DeserializationError::Ok) {}
+
+  template <typename TFilter>
+  DeserializationError parse(VariantData &variant, TFilter filter,
+                             NestingLimit nestingLimit) {
+    parseVariant(variant, filter, nestingLimit);
+
+    if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
+      // We don't detect trailing characters earlier, so we need to check now
+      return DeserializationError::InvalidInput;
+    }
+
+    return _error;
+  }
+
+ private:
+  char current() {
+    return _latch.current();
+  }
+
+  void move() {
+    _latch.clear();
+  }
+
+  bool eat(char charToSkip) {
+    if (current() != charToSkip)
+      return false;
+    move();
+    return true;
+  }
+
+  template <typename TFilter>
+  bool parseVariant(VariantData &variant, TFilter filter,
+                    NestingLimit nestingLimit) {
+    if (!skipSpacesAndComments())
+      return false;
+
+    switch (current()) {
+      case '[':
+        if (filter.allowArray())
+          return parseArray(variant.toArray(), filter, nestingLimit);
+        else
+          return skipArray(nestingLimit);
+
+      case '{':
+        if (filter.allowObject())
+          return parseObject(variant.toObject(), filter, nestingLimit);
+        else
+          return skipObject(nestingLimit);
+
+      case '\"':
+      case '\'':
+        if (filter.allowValue())
+          return parseStringValue(variant);
+        else
+          return skipString();
+
+      default:
+        if (filter.allowValue())
+          return parseNumericValue(variant);
+        else
+          return skipNumericValue();
+    }
+  }
+
+  bool skipVariant(NestingLimit nestingLimit) {
+    if (!skipSpacesAndComments())
+      return false;
+
+    switch (current()) {
+      case '[':
+        return skipArray(nestingLimit);
+
+      case '{':
+        return skipObject(nestingLimit);
+
+      case '\"':
+      case '\'':
+        return skipString();
+
+      default:
+        return skipNumericValue();
+    }
+  }
+
+  template <typename TFilter>
+  bool parseArray(CollectionData &array, TFilter filter,
+                  NestingLimit nestingLimit) {
+    if (nestingLimit.reached()) {
+      _error = DeserializationError::TooDeep;
+      return false;
+    }
+
+    // Skip opening braket
+    ARDUINOJSON_ASSERT(current() == '[');
+    move();
+
+    // Skip spaces
+    if (!skipSpacesAndComments())
+      return false;
+
+    // Empty array?
+    if (eat(']'))
+      return true;
+
+    TFilter memberFilter = filter[0UL];
+
+    // Read each value
+    for (;;) {
+      if (memberFilter.allow()) {
+        // Allocate slot in array
+        VariantData *value = array.addElement(_pool);
+        if (!value) {
+          _error = DeserializationError::NoMemory;
+          return false;
+        }
+
+        // 1 - Parse value
+        if (!parseVariant(*value, memberFilter, nestingLimit.decrement()))
+          return false;
+      } else {
+        if (!skipVariant(nestingLimit.decrement()))
+          return false;
+      }
+
+      // 2 - Skip spaces
+      if (!skipSpacesAndComments())
+        return false;
+
+      // 3 - More values?
+      if (eat(']'))
+        return true;
+      if (!eat(',')) {
+        _error = DeserializationError::InvalidInput;
+        return false;
+      }
+    }
+  }
+
+  bool skipArray(NestingLimit nestingLimit) {
+    if (nestingLimit.reached()) {
+      _error = DeserializationError::TooDeep;
+      return false;
+    }
+
+    // Skip opening braket
+    ARDUINOJSON_ASSERT(current() == '[');
+    move();
+
+    // Read each value
+    for (;;) {
+      // 1 - Skip value
+      if (!skipVariant(nestingLimit.decrement()))
+        return false;
+
+      // 2 - Skip spaces
+      if (!skipSpacesAndComments())
+        return false;
+
+      // 3 - More values?
+      if (eat(']'))
+        return true;
+      if (!eat(',')) {
+        _error = DeserializationError::InvalidInput;
+        return false;
+      }
+    }
+  }
+
+  template <typename TFilter>
+  bool parseObject(CollectionData &object, TFilter filter,
+                   NestingLimit nestingLimit) {
+    if (nestingLimit.reached()) {
+      _error = DeserializationError::TooDeep;
+      return false;
+    }
+
+    // Skip opening brace
+    ARDUINOJSON_ASSERT(current() == '{');
+    move();
+
+    // Skip spaces
+    if (!skipSpacesAndComments())
+      return false;
+
+    // Empty object?
+    if (eat('}'))
+      return true;
+
+    // Read each key value pair
+    for (;;) {
+      // Parse key
+      if (!parseKey())
+        return false;
+
+      // Skip spaces
+      if (!skipSpacesAndComments())
+        return false;
+
+      // Colon
+      if (!eat(':')) {
+        _error = DeserializationError::InvalidInput;
+        return false;
+      }
+
+      const char *key = _stringStorage.c_str();
+
+      TFilter memberFilter = filter[key];
+
+      if (memberFilter.allow()) {
+        VariantData *variant = object.getMember(adaptString(key));
+        if (!variant) {
+          // Save key in memory pool.
+          // This MUST be done before adding the slot.
+          key = _stringStorage.save();
+
+          // Allocate slot in object
+          VariantSlot *slot = object.addSlot(_pool);
+          if (!slot) {
+            _error = DeserializationError::NoMemory;
+            return false;
+          }
+
+          slot->setKey(key, typename TStringStorage::storage_policy());
+
+          variant = slot->data();
+        }
+
+        // Parse value
+        if (!parseVariant(*variant, memberFilter, nestingLimit.decrement()))
+          return false;
+      } else {
+        if (!skipVariant(nestingLimit.decrement()))
+          return false;
+      }
+
+      // Skip spaces
+      if (!skipSpacesAndComments())
+        return false;
+
+      // More keys/values?
+      if (eat('}'))
+        return true;
+      if (!eat(',')) {
+        _error = DeserializationError::InvalidInput;
+        return false;
+      }
+
+      // Skip spaces
+      if (!skipSpacesAndComments())
+        return false;
+    }
+  }
+
+  bool skipObject(NestingLimit nestingLimit) {
+    if (nestingLimit.reached()) {
+      _error = DeserializationError::TooDeep;
+      return false;
+    }
+
+    // Skip opening brace
+    ARDUINOJSON_ASSERT(current() == '{');
+    move();
+
+    // Skip spaces
+    if (!skipSpacesAndComments())
+      return false;
+
+    // Empty object?
+    if (eat('}'))
+      return true;
+
+    // Read each key value pair
+    for (;;) {
+      // Skip key
+      if (!skipVariant(nestingLimit.decrement()))
+        return false;
+
+      // Skip spaces
+      if (!skipSpacesAndComments())
+        return false;
+
+      // Colon
+      if (!eat(':')) {
+        _error = DeserializationError::InvalidInput;
+        return false;
+      }
+
+      // Skip value
+      if (!skipVariant(nestingLimit.decrement()))
+        return false;
+
+      // Skip spaces
+      if (!skipSpacesAndComments())
+        return false;
+
+      // More keys/values?
+      if (eat('}'))
+        return true;
+      if (!eat(',')) {
+        _error = DeserializationError::InvalidInput;
+        return false;
+      }
+    }
+  }
+
+  bool parseKey() {
+    _stringStorage.startString();
+    if (isQuote(current())) {
+      return parseQuotedString();
+    } else {
+      return parseNonQuotedString();
+    }
+  }
+
+  bool parseStringValue(VariantData &variant) {
+    _stringStorage.startString();
+    if (!parseQuotedString())
+      return false;
+    const char *value = _stringStorage.save();
+    variant.setStringPointer(value, typename TStringStorage::storage_policy());
+    return true;
+  }
+
+  bool parseQuotedString() {
+#if ARDUINOJSON_DECODE_UNICODE
+    Utf16::Codepoint codepoint;
+#endif
+    const char stopChar = current();
+
+    move();
+    for (;;) {
+      char c = current();
+      move();
+      if (c == stopChar)
+        break;
+
+      if (c == '\0') {
+        _error = DeserializationError::IncompleteInput;
+        return false;
+      }
+
+      if (c == '\\') {
+        c = current();
+
+        if (c == '\0') {
+          _error = DeserializationError::IncompleteInput;
+          return false;
+        }
+
+        if (c == 'u') {
+#if ARDUINOJSON_DECODE_UNICODE
+          move();
+          uint16_t codeunit;
+          if (!parseHex4(codeunit))
+            return false;
+          if (codepoint.append(codeunit))
+            Utf8::encodeCodepoint(codepoint.value(), _stringStorage);
+          continue;
+#else
+          _error = DeserializationError::NotSupported;
+          return false;
+#endif
+        }
+
+        // replace char
+        c = EscapeSequence::unescapeChar(c);
+        if (c == '\0') {
+          _error = DeserializationError::InvalidInput;
+          return false;
+        }
+        move();
+      }
+
+      _stringStorage.append(c);
+    }
+
+    _stringStorage.append('\0');
+
+    if (!_stringStorage.isValid()) {
+      _error = DeserializationError::NoMemory;
+      return false;
+    }
+
+    return true;
+  }
+
+  bool parseNonQuotedString() {
+    char c = current();
+    ARDUINOJSON_ASSERT(c);
+
+    if (canBeInNonQuotedString(c)) {  // no quotes
+      do {
+        move();
+        _stringStorage.append(c);
+        c = current();
+      } while (canBeInNonQuotedString(c));
+    } else {
+      _error = DeserializationError::InvalidInput;
+      return false;
+    }
+
+    _stringStorage.append('\0');
+
+    if (!_stringStorage.isValid()) {
+      _error = DeserializationError::NoMemory;
+      return false;
+    }
+
+    return true;
+  }
+
+  bool skipString() {
+    const char stopChar = current();
+
+    move();
+    for (;;) {
+      char c = current();
+      move();
+      if (c == stopChar)
+        break;
+      if (c == '\0') {
+        _error = DeserializationError::IncompleteInput;
+        return false;
+      }
+      if (c == '\\') {
+        if (current() != '\0')
+          move();
+      }
+    }
+
+    return true;
+  }
+
+  bool parseNumericValue(VariantData &result) {
+    uint8_t n = 0;
+
+    char c = current();
+    while (canBeInNonQuotedString(c) && n < 63) {
+      move();
+      _buffer[n++] = c;
+      c = current();
+    }
+    _buffer[n] = 0;
+
+    c = _buffer[0];
+    if (c == 't') {  // true
+      result.setBoolean(true);
+      if (n != 4) {
+        _error = DeserializationError::IncompleteInput;
+        return false;
+      }
+      return true;
+    }
+    if (c == 'f') {  // false
+      result.setBoolean(false);
+      if (n != 5) {
+        _error = DeserializationError::IncompleteInput;
+        return false;
+      }
+      return true;
+    }
+    if (c == 'n') {  // null
+      // the variant is already null
+      if (n != 4) {
+        _error = DeserializationError::IncompleteInput;
+        return false;
+      }
+      return true;
+    }
+
+    if (!parseNumber(_buffer, result)) {
+      _error = DeserializationError::InvalidInput;
+      return false;
+    }
+
+    return true;
+  }
+
+  bool skipNumericValue() {
+    char c = current();
+    while (canBeInNonQuotedString(c)) {
+      move();
+      c = current();
+    }
+    return true;
+  }
+
+  bool parseHex4(uint16_t &result) {
+    result = 0;
+    for (uint8_t i = 0; i < 4; ++i) {
+      char digit = current();
+      if (!digit) {
+        _error = DeserializationError::IncompleteInput;
+        return false;
+      }
+      uint8_t value = decodeHex(digit);
+      if (value > 0x0F) {
+        _error = DeserializationError::InvalidInput;
+        return false;
+      }
+      result = uint16_t((result << 4) | value);
+      move();
+    }
+    return true;
+  }
+
+  static inline bool isBetween(char c, char min, char max) {
+    return min <= c && c <= max;
+  }
+
+  static inline bool canBeInNonQuotedString(char c) {
+    return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
+           isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
+  }
+
+  static inline bool isQuote(char c) {
+    return c == '\'' || c == '\"';
+  }
+
+  static inline uint8_t decodeHex(char c) {
+    if (c < 'A')
+      return uint8_t(c - '0');
+    c = char(c & ~0x20);  // uppercase
+    return uint8_t(c - 'A' + 10);
+  }
+
+  bool skipSpacesAndComments() {
+    for (;;) {
+      switch (current()) {
+        // end of string
+        case '\0':
+          _error = _foundSomething ? DeserializationError::IncompleteInput
+                                   : DeserializationError::EmptyInput;
+          return false;
+
+        // spaces
+        case ' ':
+        case '\t':
+        case '\r':
+        case '\n':
+          move();
+          continue;
+
+#if ARDUINOJSON_ENABLE_COMMENTS
+        // comments
+        case '/':
+          move();  // skip '/'
+          switch (current()) {
+            // block comment
+            case '*': {
+              move();  // skip '*'
+              bool wasStar = false;
+              for (;;) {
+                char c = current();
+                if (c == '\0') {
+                  _error = DeserializationError::IncompleteInput;
+                  return false;
+                }
+                if (c == '/' && wasStar) {
+                  move();
+                  break;
+                }
+                wasStar = c == '*';
+                move();
+              }
+              break;
+            }
+
+            // trailing comment
+            case '/':
+              // no need to skip "//"
+              for (;;) {
+                move();
+                char c = current();
+                if (c == '\0') {
+                  _error = DeserializationError::IncompleteInput;
+                  return false;
+                }
+                if (c == '\n')
+                  break;
+              }
+              break;
+
+            // not a comment, just a '/'
+            default:
+              _error = DeserializationError::InvalidInput;
+              return false;
+          }
+          break;
+#endif
+
+        default:
+          _foundSomething = true;
+          return true;
+      }
+    }
+  }
+
+  TStringStorage _stringStorage;
+  bool _foundSomething;
+  Latch<TReader> _latch;
+  MemoryPool *_pool;
+  char _buffer[64];  // using a member instead of a local variable because it
+                     // ended in the recursive path after compiler inlined the
+                     // code
+  DeserializationError _error;
+};
+
+//
+// deserializeJson(JsonDocument&, const std::string&, ...)
+//
+// ... = NestingLimit
+template <typename TString>
+DeserializationError deserializeJson(
+    JsonDocument &doc, const TString &input,
+    NestingLimit nestingLimit = NestingLimit()) {
+  return deserialize<JsonDeserializer>(doc, input, nestingLimit,
+                                       AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TString>
+DeserializationError deserializeJson(
+    JsonDocument &doc, const TString &input, Filter filter,
+    NestingLimit nestingLimit = NestingLimit()) {
+  return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TString>
+DeserializationError deserializeJson(JsonDocument &doc, const TString &input,
+                                     NestingLimit nestingLimit, Filter filter) {
+  return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeJson(JsonDocument&, std::istream&, ...)
+//
+// ... = NestingLimit
+template <typename TStream>
+DeserializationError deserializeJson(
+    JsonDocument &doc, TStream &input,
+    NestingLimit nestingLimit = NestingLimit()) {
+  return deserialize<JsonDeserializer>(doc, input, nestingLimit,
+                                       AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TStream>
+DeserializationError deserializeJson(
+    JsonDocument &doc, TStream &input, Filter filter,
+    NestingLimit nestingLimit = NestingLimit()) {
+  return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TStream>
+DeserializationError deserializeJson(JsonDocument &doc, TStream &input,
+                                     NestingLimit nestingLimit, Filter filter) {
+  return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeJson(JsonDocument&, char*, ...)
+//
+// ... = NestingLimit
+template <typename TChar>
+DeserializationError deserializeJson(
+    JsonDocument &doc, TChar *input,
+    NestingLimit nestingLimit = NestingLimit()) {
+  return deserialize<JsonDeserializer>(doc, input, nestingLimit,
+                                       AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TChar>
+DeserializationError deserializeJson(
+    JsonDocument &doc, TChar *input, Filter filter,
+    NestingLimit nestingLimit = NestingLimit()) {
+  return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TChar>
+DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
+                                     NestingLimit nestingLimit, Filter filter) {
+  return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeJson(JsonDocument&, char*, size_t, ...)
+//
+// ... = NestingLimit
+template <typename TChar>
+DeserializationError deserializeJson(
+    JsonDocument &doc, TChar *input, size_t inputSize,
+    NestingLimit nestingLimit = NestingLimit()) {
+  return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
+                                       AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TChar>
+DeserializationError deserializeJson(
+    JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
+    NestingLimit nestingLimit = NestingLimit()) {
+  return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
+                                       filter);
+}
+// ... = NestingLimit, Filter
+template <typename TChar>
+DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
+                                     size_t inputSize,
+                                     NestingLimit nestingLimit, Filter filter) {
+  return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
+                                       filter);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Json/JsonSerializer.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,135 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Json/TextFormatter.hpp>
+#include <ArduinoJson/Misc/Visitable.hpp>
+#include <ArduinoJson/Serialization/measure.hpp>
+#include <ArduinoJson/Serialization/serialize.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class JsonSerializer : public Visitor<size_t> {
+ public:
+  JsonSerializer(TWriter writer) : _formatter(writer) {}
+
+  FORCE_INLINE size_t visitArray(const CollectionData &array) {
+    write('[');
+
+    VariantSlot *slot = array.head();
+
+    while (slot != 0) {
+      slot->data()->accept(*this);
+
+      slot = slot->next();
+      if (slot == 0)
+        break;
+
+      write(',');
+    }
+
+    write(']');
+    return bytesWritten();
+  }
+
+  size_t visitObject(const CollectionData &object) {
+    write('{');
+
+    VariantSlot *slot = object.head();
+
+    while (slot != 0) {
+      _formatter.writeString(slot->key());
+      write(':');
+      slot->data()->accept(*this);
+
+      slot = slot->next();
+      if (slot == 0)
+        break;
+
+      write(',');
+    }
+
+    write('}');
+    return bytesWritten();
+  }
+
+  size_t visitFloat(Float value) {
+    _formatter.writeFloat(value);
+    return bytesWritten();
+  }
+
+  size_t visitString(const char *value) {
+    _formatter.writeString(value);
+    return bytesWritten();
+  }
+
+  size_t visitRawJson(const char *data, size_t n) {
+    _formatter.writeRaw(data, n);
+    return bytesWritten();
+  }
+
+  size_t visitNegativeInteger(UInt value) {
+    _formatter.writeNegativeInteger(value);
+    return bytesWritten();
+  }
+
+  size_t visitPositiveInteger(UInt value) {
+    _formatter.writePositiveInteger(value);
+    return bytesWritten();
+  }
+
+  size_t visitBoolean(bool value) {
+    _formatter.writeBoolean(value);
+    return bytesWritten();
+  }
+
+  size_t visitNull() {
+    _formatter.writeRaw("null");
+    return bytesWritten();
+  }
+
+ protected:
+  size_t bytesWritten() const {
+    return _formatter.bytesWritten();
+  }
+
+  void write(char c) {
+    _formatter.writeRaw(c);
+  }
+
+  void write(const char *s) {
+    _formatter.writeRaw(s);
+  }
+
+ private:
+  TextFormatter<TWriter> _formatter;
+};
+
+template <typename TSource, typename TDestination>
+size_t serializeJson(const TSource &source, TDestination &destination) {
+  return serialize<JsonSerializer>(source, destination);
+}
+
+template <typename TSource>
+size_t serializeJson(const TSource &source, void *buffer, size_t bufferSize) {
+  return serialize<JsonSerializer>(source, buffer, bufferSize);
+}
+
+template <typename TSource>
+size_t measureJson(const TSource &source) {
+  return measure<JsonSerializer>(source);
+}
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+template <typename T>
+inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type
+operator<<(std::ostream &os, const T &source) {
+  serializeJson(source, os);
+  return os;
+}
+#endif
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Json/Latch.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,55 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/assert.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TReader>
+class Latch {
+ public:
+  Latch(TReader reader) : _reader(reader), _loaded(false) {
+#if ARDUINOJSON_DEBUG
+    _ended = false;
+#endif
+  }
+
+  void clear() {
+    _loaded = false;
+  }
+
+  int last() const {
+    return _current;
+  }
+
+  FORCE_INLINE char current() {
+    if (!_loaded) {
+      load();
+    }
+    return _current;
+  }
+
+ private:
+  void load() {
+    ARDUINOJSON_ASSERT(!_ended);
+    int c = _reader.read();
+#if ARDUINOJSON_DEBUG
+    if (c <= 0)
+      _ended = true;
+#endif
+    _current = static_cast<char>(c > 0 ? c : 0);
+    _loaded = true;
+  }
+
+  TReader _reader;
+  char _current;
+  bool _loaded;
+#if ARDUINOJSON_DEBUG
+  bool _ended;
+#endif
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Json/PrettyJsonSerializer.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,89 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Json/JsonSerializer.hpp>
+#include <ArduinoJson/Serialization/measure.hpp>
+#include <ArduinoJson/Serialization/serialize.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class PrettyJsonSerializer : public JsonSerializer<TWriter> {
+  typedef JsonSerializer<TWriter> base;
+
+ public:
+  PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
+
+  size_t visitArray(const CollectionData &array) {
+    VariantSlot *slot = array.head();
+    if (slot) {
+      base::write("[\r\n");
+      _nesting++;
+      while (slot != 0) {
+        indent();
+        slot->data()->accept(*this);
+
+        slot = slot->next();
+        base::write(slot ? ",\r\n" : "\r\n");
+      }
+      _nesting--;
+      indent();
+      base::write("]");
+    } else {
+      base::write("[]");
+    }
+    return this->bytesWritten();
+  }
+
+  size_t visitObject(const CollectionData &object) {
+    VariantSlot *slot = object.head();
+    if (slot) {
+      base::write("{\r\n");
+      _nesting++;
+      while (slot != 0) {
+        indent();
+        base::visitString(slot->key());
+        base::write(": ");
+        slot->data()->accept(*this);
+
+        slot = slot->next();
+        base::write(slot ? ",\r\n" : "\r\n");
+      }
+      _nesting--;
+      indent();
+      base::write("}");
+    } else {
+      base::write("{}");
+    }
+    return this->bytesWritten();
+  }
+
+ private:
+  void indent() {
+    for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB);
+  }
+
+  uint8_t _nesting;
+};
+
+template <typename TSource, typename TDestination>
+size_t serializeJsonPretty(const TSource &source, TDestination &destination) {
+  return serialize<PrettyJsonSerializer>(source, destination);
+}
+
+template <typename TSource>
+size_t serializeJsonPretty(const TSource &source, void *buffer,
+                           size_t bufferSize) {
+  return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
+}
+
+template <typename TSource>
+size_t measureJsonPretty(const TSource &source) {
+  return measure<PrettyJsonSerializer>(source);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Json/TextFormatter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,159 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stdint.h>
+#include <string.h>  // for strlen
+
+#include <ArduinoJson/Json/EscapeSequence.hpp>
+#include <ArduinoJson/Numbers/FloatParts.hpp>
+#include <ArduinoJson/Numbers/Integer.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Serialization/CountingDecorator.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class TextFormatter {
+ public:
+  explicit TextFormatter(TWriter writer) : _writer(writer) {}
+
+  // Returns the number of bytes sent to the TWriter implementation.
+  size_t bytesWritten() const {
+    return _writer.count();
+  }
+
+  void writeBoolean(bool value) {
+    if (value)
+      writeRaw("true");
+    else
+      writeRaw("false");
+  }
+
+  void writeString(const char *value) {
+    ARDUINOJSON_ASSERT(value != NULL);
+    writeRaw('\"');
+    while (*value) writeChar(*value++);
+    writeRaw('\"');
+  }
+
+  void writeChar(char c) {
+    char specialChar = EscapeSequence::escapeChar(c);
+    if (specialChar) {
+      writeRaw('\\');
+      writeRaw(specialChar);
+    } else {
+      writeRaw(c);
+    }
+  }
+
+  template <typename T>
+  void writeFloat(T value) {
+    if (isnan(value))
+      return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
+
+#if ARDUINOJSON_ENABLE_INFINITY
+    if (value < 0.0) {
+      writeRaw('-');
+      value = -value;
+    }
+
+    if (isinf(value))
+      return writeRaw("Infinity");
+#else
+    if (isinf(value))
+      return writeRaw("null");
+
+    if (value < 0.0) {
+      writeRaw('-');
+      value = -value;
+    }
+#endif
+
+    FloatParts<T> parts(value);
+
+    writePositiveInteger(parts.integral);
+    if (parts.decimalPlaces)
+      writeDecimals(parts.decimal, parts.decimalPlaces);
+
+    if (parts.exponent < 0) {
+      writeRaw("e-");
+      writePositiveInteger(-parts.exponent);
+    }
+
+    if (parts.exponent > 0) {
+      writeRaw('e');
+      writePositiveInteger(parts.exponent);
+    }
+  }
+
+  void writeNegativeInteger(UInt value) {
+    writeRaw('-');
+    writePositiveInteger(value);
+  }
+
+  template <typename T>
+  void writePositiveInteger(T value) {
+    char buffer[22];
+    char *end = buffer + sizeof(buffer);
+    char *begin = end;
+
+    // write the string in reverse order
+    do {
+      *--begin = char(value % 10 + '0');
+      value = T(value / 10);
+    } while (value);
+
+    // and dump it in the right order
+    writeRaw(begin, end);
+  }
+
+  void writeDecimals(uint32_t value, int8_t width) {
+    // buffer should be big enough for all digits and the dot
+    char buffer[16];
+    char *end = buffer + sizeof(buffer);
+    char *begin = end;
+
+    // write the string in reverse order
+    while (width--) {
+      *--begin = char(value % 10 + '0');
+      value /= 10;
+    }
+    *--begin = '.';
+
+    // and dump it in the right order
+    writeRaw(begin, end);
+  }
+
+  void writeRaw(const char *s) {
+    _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
+  }
+
+  void writeRaw(const char *s, size_t n) {
+    _writer.write(reinterpret_cast<const uint8_t *>(s), n);
+  }
+
+  void writeRaw(const char *begin, const char *end) {
+    _writer.write(reinterpret_cast<const uint8_t *>(begin),
+                  static_cast<size_t>(end - begin));
+  }
+
+  template <size_t N>
+  void writeRaw(const char (&s)[N]) {
+    _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
+  }
+  void writeRaw(char c) {
+    _writer.write(static_cast<uint8_t>(c));
+  }
+
+ protected:
+  CountingDecorator<TWriter> _writer;
+  size_t _length;
+
+ private:
+  TextFormatter &operator=(const TextFormatter &);  // cannot be assigned
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Json/Utf16.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,67 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stdint.h>  // uint16_t, uint32_t
+
+// The high surrogate may be uninitialized if the pair is invalid,
+// we choose to ignore the problem to reduce the size of the code
+// Garbage in => Garbage out
+#if defined(__GNUC__)
+#if __GNUC__ >= 7
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+namespace Utf16 {
+inline bool isHighSurrogate(uint16_t codeunit) {
+  return codeunit >= 0xD800 && codeunit < 0xDC00;
+}
+
+inline bool isLowSurrogate(uint16_t codeunit) {
+  return codeunit >= 0xDC00 && codeunit < 0xE000;
+}
+
+class Codepoint {
+ public:
+  Codepoint() : _highSurrogate(0) {}
+
+  bool append(uint16_t codeunit) {
+    if (isHighSurrogate(codeunit)) {
+      _highSurrogate = codeunit & 0x3FF;
+      return false;
+    }
+
+    if (isLowSurrogate(codeunit)) {
+      _codepoint =
+          uint32_t(0x10000 + ((_highSurrogate << 10) | (codeunit & 0x3FF)));
+      return true;
+    }
+
+    _codepoint = codeunit;
+    return true;
+  }
+
+  uint32_t value() const {
+    return _codepoint;
+  }
+
+ private:
+  uint16_t _highSurrogate;
+  uint32_t _codepoint;
+};
+}  // namespace Utf16
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#if defined(__GNUC__)
+#if __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Json/Utf8.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,46 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+namespace Utf8 {
+template <typename TStringBuilder>
+inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) {
+  // this function was optimize for code size on AVR
+
+  // a buffer to store the string in reverse
+  char buf[5];
+  char* p = buf;
+
+  *(p++) = 0;
+  if (codepoint32 < 0x80) {
+    *(p++) = char((codepoint32));
+  } else {
+    *(p++) = char((codepoint32 | 0x80) & 0xBF);
+    uint16_t codepoint16 = uint16_t(codepoint32 >> 6);
+    if (codepoint16 < 0x20) {  // 0x800
+      *(p++) = char(codepoint16 | 0xC0);
+    } else {
+      *(p++) = char((codepoint16 | 0x80) & 0xBF);
+      codepoint16 = uint16_t(codepoint16 >> 6);
+      if (codepoint16 < 0x10) {  // 0x10000
+        *(p++) = char(codepoint16 | 0xE0);
+      } else {
+        *(p++) = char((codepoint16 | 0x80) & 0xBF);
+        codepoint16 = uint16_t(codepoint16 >> 6);
+        *(p++) = char(codepoint16 | 0xF0);
+      }
+    }
+  }
+
+  while (*(--p)) {
+    str.append(*p);
+  }
+}
+}  // namespace Utf8
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Memory/Alignment.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,60 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stddef.h>  // size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#if ARDUINOJSON_ENABLE_ALIGNMENT
+
+inline bool isAligned(size_t value) {
+  const size_t mask = sizeof(void *) - 1;
+  size_t addr = value;
+  return (addr & mask) == 0;
+}
+
+inline size_t addPadding(size_t bytes) {
+  const size_t mask = sizeof(void *) - 1;
+  return (bytes + mask) & ~mask;
+}
+
+template <size_t bytes>
+struct AddPadding {
+  static const size_t mask = sizeof(void *) - 1;
+  static const size_t value = (bytes + mask) & ~mask;
+};
+
+#else
+
+inline bool isAligned(size_t) {
+  return true;
+}
+
+inline size_t addPadding(size_t bytes) {
+  return bytes;
+}
+
+template <size_t bytes>
+struct AddPadding {
+  static const size_t value = bytes;
+};
+
+#endif
+
+template <typename T>
+inline bool isAligned(T *ptr) {
+  return isAligned(reinterpret_cast<size_t>(ptr));
+}
+
+template <typename T>
+inline T *addPadding(T *p) {
+  size_t address = addPadding(reinterpret_cast<size_t>(p));
+  return reinterpret_cast<T *>(address);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Memory/MemoryPool.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,212 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Memory/Alignment.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/mpl/max.hpp>
+#include <ArduinoJson/Variant/VariantSlot.hpp>
+
+#include <string.h>  // memmove
+
+#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// _begin                                   _end
+// v                                           v
+// +-------------+--------------+--------------+
+// | strings...  |   (free)     |  ...variants |
+// +-------------+--------------+--------------+
+//               ^              ^
+//             _left          _right
+
+class MemoryPool {
+ public:
+  MemoryPool(char* buf, size_t capa)
+      : _begin(buf),
+        _left(buf),
+        _right(buf ? buf + capa : 0),
+        _end(buf ? buf + capa : 0),
+        _overflowed(false) {
+    ARDUINOJSON_ASSERT(isAligned(_begin));
+    ARDUINOJSON_ASSERT(isAligned(_right));
+    ARDUINOJSON_ASSERT(isAligned(_end));
+  }
+
+  void* buffer() {
+    return _begin;
+  }
+
+  // Gets the capacity of the memoryPool in bytes
+  size_t capacity() const {
+    return size_t(_end - _begin);
+  }
+
+  size_t size() const {
+    return size_t(_left - _begin + _end - _right);
+  }
+
+  bool overflowed() const {
+    return _overflowed;
+  }
+
+  VariantSlot* allocVariant() {
+    return allocRight<VariantSlot>();
+  }
+
+  template <typename TAdaptedString>
+  const char* saveString(const TAdaptedString& str) {
+    if (str.isNull())
+      return 0;
+
+#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
+    const char* existingCopy = findString(str.begin());
+    if (existingCopy)
+      return existingCopy;
+#endif
+
+    size_t n = str.size();
+
+    char* newCopy = allocString(n + 1);
+    if (newCopy) {
+      str.copyTo(newCopy, n);
+      newCopy[n] = 0;  // force null-terminator
+    }
+    return newCopy;
+  }
+
+  void getFreeZone(char** zoneStart, size_t* zoneSize) const {
+    *zoneStart = _left;
+    *zoneSize = size_t(_right - _left);
+  }
+
+  const char* saveStringFromFreeZone(size_t len) {
+#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
+    const char* dup = findString(_left);
+    if (dup)
+      return dup;
+#endif
+
+    const char* str = _left;
+    _left += len;
+    checkInvariants();
+    return str;
+  }
+
+  void markAsOverflowed() {
+    _overflowed = true;
+  }
+
+  void clear() {
+    _left = _begin;
+    _right = _end;
+    _overflowed = false;
+  }
+
+  bool canAlloc(size_t bytes) const {
+    return _left + bytes <= _right;
+  }
+
+  bool owns(void* p) const {
+    return _begin <= p && p < _end;
+  }
+
+  // Workaround for missing placement new
+  void* operator new(size_t, void* p) {
+    return p;
+  }
+
+  // Squash the free space between strings and variants
+  //
+  // _begin                    _end
+  // v                            v
+  // +-------------+--------------+
+  // | strings...  |  ...variants |
+  // +-------------+--------------+
+  //               ^
+  //          _left _right
+  //
+  // This funcion is called before a realloc.
+  ptrdiff_t squash() {
+    char* new_right = addPadding(_left);
+    if (new_right >= _right)
+      return 0;
+
+    size_t right_size = static_cast<size_t>(_end - _right);
+    memmove(new_right, _right, right_size);
+
+    ptrdiff_t bytes_reclaimed = _right - new_right;
+    _right = new_right;
+    _end = new_right + right_size;
+    return bytes_reclaimed;
+  }
+
+  // Move all pointers together
+  // This funcion is called after a realloc.
+  void movePointers(ptrdiff_t offset) {
+    _begin += offset;
+    _left += offset;
+    _right += offset;
+    _end += offset;
+  }
+
+ private:
+  void checkInvariants() {
+    ARDUINOJSON_ASSERT(_begin <= _left);
+    ARDUINOJSON_ASSERT(_left <= _right);
+    ARDUINOJSON_ASSERT(_right <= _end);
+    ARDUINOJSON_ASSERT(isAligned(_right));
+  }
+
+#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
+  template <typename TIterator>
+  const char* findString(TIterator str) {
+    for (char* next = _begin; next < _left; ++next) {
+      char* begin = next;
+
+      // try to match
+      for (TIterator it = str; *it == *next; ++it) {
+        if (*next++ == 0)
+          return begin;
+      }
+
+      // jump to next terminator
+      while (*next) ++next;
+    }
+    return 0;
+  }
+#endif
+
+  char* allocString(size_t n) {
+    if (!canAlloc(n)) {
+      _overflowed = true;
+      return 0;
+    }
+    char* s = _left;
+    _left += n;
+    checkInvariants();
+    return s;
+  }
+
+  template <typename T>
+  T* allocRight() {
+    return reinterpret_cast<T*>(allocRight(sizeof(T)));
+  }
+
+  void* allocRight(size_t bytes) {
+    if (!canAlloc(bytes)) {
+      _overflowed = true;
+      return 0;
+    }
+    _right -= bytes;
+    return _right;
+  }
+
+  char *_begin, *_left, *_right, *_end;
+  bool _overflowed;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Misc/SerializedValue.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,68 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/StringAdapters.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A special type of data that can be used to insert pregenerated JSON portions.
+template <typename T>
+class SerializedValue {
+ public:
+  explicit SerializedValue(T str) : _str(str) {}
+  operator T() const {
+    return _str;
+  }
+
+  const char* data() const {
+    return _str.c_str();
+  }
+
+  size_t size() const {
+    // CAUTION: the old Arduino String doesn't have size()
+    return _str.length();
+  }
+
+ private:
+  T _str;
+};
+
+template <typename TChar>
+class SerializedValue<TChar*> {
+ public:
+  explicit SerializedValue(TChar* p, size_t n) : _data(p), _size(n) {}
+  operator TChar*() const {
+    return _data;
+  }
+
+  TChar* data() const {
+    return _data;
+  }
+
+  size_t size() const {
+    return _size;
+  }
+
+ private:
+  TChar* _data;
+  size_t _size;
+};
+
+template <typename T>
+inline SerializedValue<T> serialized(T str) {
+  return SerializedValue<T>(str);
+}
+
+template <typename TChar>
+inline SerializedValue<TChar*> serialized(TChar* p) {
+  return SerializedValue<TChar*>(p, adaptString(p).size());
+}
+
+template <typename TChar>
+inline SerializedValue<TChar*> serialized(TChar* p, size_t n) {
+  return SerializedValue<TChar*>(p, n);
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Misc/Visitable.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,26 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TResult>
+struct Visitor {
+  typedef TResult result_type;
+};
+
+struct Visitable {
+  // template<Visitor>
+  // void accept(Visitor&) const;
+};
+
+template <typename T>
+struct IsVisitable : is_base_of<Visitable, T> {};
+
+template <typename T>
+struct IsVisitable<T&> : IsVisitable<T> {};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,637 @@
+// ArduinoJson - 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;
+  }
+
+  bool notSupported() {
+    _error = DeserializationError::NotSupported;
+    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
+        if (allowValue)
+          return notSupported();
+        else
+          return skipString<uint8_t>();
+
+      case 0xc5:  // bin 16
+        if (allowValue)
+          return notSupported();
+        else
+          return skipString<uint16_t>();
+
+      case 0xc6:  // bin 32
+        if (allowValue)
+          return notSupported();
+        else
+          return skipString<uint32_t>();
+
+      case 0xc7:  // ext 8
+        if (allowValue)
+          return notSupported();
+        else
+          return skipExt<uint8_t>();
+
+      case 0xc8:  // ext 16
+        if (allowValue)
+          return notSupported();
+        else
+          return skipExt<uint16_t>();
+
+      case 0xc9:  // ext 32
+        if (allowValue)
+          return notSupported();
+        else
+          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 (allowValue)
+#if ARDUINOJSON_USE_LONG_LONG
+          return readInteger<uint64_t>(variant);
+#else
+          return notSupported();
+#endif
+        else
+          return skipBytes(8);
+
+      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 (allowValue)
+#if ARDUINOJSON_USE_LONG_LONG
+          return readInteger<int64_t>(variant);
+#else
+          return notSupported();
+#endif
+        else
+          return skipBytes(8);
+
+      case 0xd4:  // fixext 1
+        if (allowValue)
+          return notSupported();
+        else
+          return skipBytes(2);
+
+      case 0xd5:  // fixext 2
+        if (allowValue)
+          return notSupported();
+        else
+          return skipBytes(3);
+
+      case 0xd6:  // fixext 4
+        if (allowValue)
+          return notSupported();
+        else
+          return skipBytes(5);
+
+      case 0xd7:  // fixext 8
+        if (allowValue)
+          return notSupported();
+        else
+          return skipBytes(9);
+
+      case 0xd8:  // fixext 16
+        if (allowValue)
+          return notSupported();
+        else
+          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 notSupported();
+    }
+  }
+
+  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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,203 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/MsgPack/endianess.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Serialization/CountingDecorator.hpp>
+#include <ArduinoJson/Serialization/measure.hpp>
+#include <ArduinoJson/Serialization/serialize.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class MsgPackSerializer : public Visitor<size_t> {
+ public:
+  MsgPackSerializer(TWriter writer) : _writer(writer) {}
+
+  template <typename T>
+  typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) {
+    writeByte(0xCA);
+    writeInteger(value32);
+    return bytesWritten();
+  }
+
+  template <typename T>
+  ARDUINOJSON_NO_SANITIZE("float-cast-overflow")
+  typename enable_if<sizeof(T) == 8, size_t>::type visitFloat(T value64) {
+    float value32 = float(value64);
+    if (value32 == value64) {
+      writeByte(0xCA);
+      writeInteger(value32);
+    } else {
+      writeByte(0xCB);
+      writeInteger(value64);
+    }
+    return bytesWritten();
+  }
+
+  size_t visitArray(const CollectionData& array) {
+    size_t n = array.size();
+    if (n < 0x10) {
+      writeByte(uint8_t(0x90 + array.size()));
+    } else if (n < 0x10000) {
+      writeByte(0xDC);
+      writeInteger(uint16_t(n));
+    } else {
+      writeByte(0xDD);
+      writeInteger(uint32_t(n));
+    }
+    for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
+      slot->data()->accept(*this);
+    }
+    return bytesWritten();
+  }
+
+  size_t visitObject(const CollectionData& object) {
+    size_t n = object.size();
+    if (n < 0x10) {
+      writeByte(uint8_t(0x80 + n));
+    } else if (n < 0x10000) {
+      writeByte(0xDE);
+      writeInteger(uint16_t(n));
+    } else {
+      writeByte(0xDF);
+      writeInteger(uint32_t(n));
+    }
+    for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
+      visitString(slot->key());
+      slot->data()->accept(*this);
+    }
+    return bytesWritten();
+  }
+
+  size_t visitString(const char* value) {
+    ARDUINOJSON_ASSERT(value != NULL);
+
+    size_t n = strlen(value);
+
+    if (n < 0x20) {
+      writeByte(uint8_t(0xA0 + n));
+    } else if (n < 0x100) {
+      writeByte(0xD9);
+      writeInteger(uint8_t(n));
+    } else if (n < 0x10000) {
+      writeByte(0xDA);
+      writeInteger(uint16_t(n));
+    } else {
+      writeByte(0xDB);
+      writeInteger(uint32_t(n));
+    }
+    writeBytes(reinterpret_cast<const uint8_t*>(value), n);
+    return bytesWritten();
+  }
+
+  size_t visitRawJson(const char* data, size_t size) {
+    writeBytes(reinterpret_cast<const uint8_t*>(data), size);
+    return bytesWritten();
+  }
+
+  size_t visitNegativeInteger(UInt value) {
+    UInt negated = UInt(~value + 1);
+    if (value <= 0x20) {
+      writeInteger(int8_t(negated));
+    } else if (value <= 0x80) {
+      writeByte(0xD0);
+      writeInteger(int8_t(negated));
+    } else if (value <= 0x8000) {
+      writeByte(0xD1);
+      writeInteger(int16_t(negated));
+    } else if (value <= 0x80000000) {
+      writeByte(0xD2);
+      writeInteger(int32_t(negated));
+    }
+#if ARDUINOJSON_USE_LONG_LONG
+    else {
+      writeByte(0xD3);
+      writeInteger(int64_t(negated));
+    }
+#endif
+    return bytesWritten();
+  }
+
+  size_t visitPositiveInteger(UInt value) {
+    if (value <= 0x7F) {
+      writeInteger(uint8_t(value));
+    } else if (value <= 0xFF) {
+      writeByte(0xCC);
+      writeInteger(uint8_t(value));
+    } else if (value <= 0xFFFF) {
+      writeByte(0xCD);
+      writeInteger(uint16_t(value));
+    }
+#if ARDUINOJSON_USE_LONG_LONG
+    else if (value <= 0xFFFFFFFF)
+#else
+    else
+#endif
+    {
+      writeByte(0xCE);
+      writeInteger(uint32_t(value));
+    }
+#if ARDUINOJSON_USE_LONG_LONG
+    else {
+      writeByte(0xCF);
+      writeInteger(uint64_t(value));
+    }
+#endif
+    return bytesWritten();
+  }
+
+  size_t visitBoolean(bool value) {
+    writeByte(value ? 0xC3 : 0xC2);
+    return bytesWritten();
+  }
+
+  size_t visitNull() {
+    writeByte(0xC0);
+    return bytesWritten();
+  }
+
+ private:
+  size_t bytesWritten() const {
+    return _writer.count();
+  }
+
+  void writeByte(uint8_t c) {
+    _writer.write(c);
+  }
+
+  void writeBytes(const uint8_t* p, size_t n) {
+    _writer.write(p, n);
+  }
+
+  template <typename T>
+  void writeInteger(T value) {
+    fixEndianess(value);
+    writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+  }
+
+  CountingDecorator<TWriter> _writer;
+};
+
+template <typename TSource, typename TDestination>
+inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
+  return serialize<MsgPackSerializer>(source, output);
+}
+
+template <typename TSource>
+inline size_t serializeMsgPack(const TSource& source, void* output,
+                               size_t size) {
+  return serialize<MsgPackSerializer>(source, output, size);
+}
+
+template <typename TSource>
+inline size_t measureMsgPack(const TSource& source) {
+  return measure<MsgPackSerializer>(source);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/MsgPack/endianess.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,41 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Polyfills/utility.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#if ARDUINOJSON_LITTLE_ENDIAN
+inline void fixEndianess(uint8_t *p, integral_constant<size_t, 8>) {
+  swap(p[0], p[7]);
+  swap(p[1], p[6]);
+  swap(p[2], p[5]);
+  swap(p[3], p[4]);
+}
+
+inline void fixEndianess(uint8_t *p, integral_constant<size_t, 4>) {
+  swap(p[0], p[3]);
+  swap(p[1], p[2]);
+}
+
+inline void fixEndianess(uint8_t *p, integral_constant<size_t, 2>) {
+  swap(p[0], p[1]);
+}
+
+inline void fixEndianess(uint8_t *, integral_constant<size_t, 1>) {}
+
+template <typename T>
+inline void fixEndianess(T &value) {
+  fixEndianess(reinterpret_cast<uint8_t *>(&value),
+               integral_constant<size_t, sizeof(T)>());
+}
+#else
+template <typename T>
+inline void fixEndianess(T &) {}
+#endif
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/MsgPack/ieee754.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,18 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {
+  f[0] = uint8_t((d[0] & 0xC0) | (d[0] << 3 & 0x3f) | (d[1] >> 5));
+  f[1] = uint8_t((d[1] << 3) | (d[2] >> 5));
+  f[2] = uint8_t((d[2] << 3) | (d[3] >> 5));
+  f[3] = uint8_t((d[3] << 3) | (d[4] >> 5));
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Namespace.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,26 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Polyfills/preprocessor.hpp>
+#include <ArduinoJson/version.hpp>
+
+#ifndef ARDUINOJSON_NAMESPACE
+
+#define ARDUINOJSON_NAMESPACE                                                  \
+  ARDUINOJSON_CONCAT4(                                                         \
+      ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR,              \
+                          ARDUINOJSON_VERSION_MINOR,                           \
+                          ARDUINOJSON_VERSION_REVISION),                       \
+      _,                                                                       \
+      ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM,                        \
+                            ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \
+                            ARDUINOJSON_ENABLE_STRING_DEDUPLICATION),          \
+      ARDUINOJSON_HEX_DIGIT(                                                   \
+          ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY,                 \
+          ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE))
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Numbers/Float.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,17 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#if ARDUINOJSON_USE_DOUBLE
+typedef double Float;
+#else
+typedef float Float;
+#endif
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Numbers/FloatParts.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,87 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Numbers/FloatTraits.hpp>
+#include <ArduinoJson/Polyfills/math.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TFloat>
+struct FloatParts {
+  uint32_t integral;
+  uint32_t decimal;
+  int16_t exponent;
+  int8_t decimalPlaces;
+
+  FloatParts(TFloat value) {
+    uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000;
+    decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6;
+
+    exponent = normalize(value);
+
+    integral = uint32_t(value);
+    // reduce number of decimal places by the number of integral places
+    for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) {
+      maxDecimalPart /= 10;
+      decimalPlaces--;
+    }
+
+    TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart);
+
+    decimal = uint32_t(remainder);
+    remainder = remainder - TFloat(decimal);
+
+    // rounding:
+    // increment by 1 if remainder >= 0.5
+    decimal += uint32_t(remainder * 2);
+    if (decimal >= maxDecimalPart) {
+      decimal = 0;
+      integral++;
+      if (exponent && integral >= 10) {
+        exponent++;
+        integral = 1;
+      }
+    }
+
+    // remove trailing zeros
+    while (decimal % 10 == 0 && decimalPlaces > 0) {
+      decimal /= 10;
+      decimalPlaces--;
+    }
+  }
+
+  static int16_t normalize(TFloat& value) {
+    typedef FloatTraits<TFloat> traits;
+    int16_t powersOf10 = 0;
+
+    int8_t index = sizeof(TFloat) == 8 ? 8 : 5;
+    int bit = 1 << index;
+
+    if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
+      for (; index >= 0; index--) {
+        if (value >= traits::positiveBinaryPowerOfTen(index)) {
+          value *= traits::negativeBinaryPowerOfTen(index);
+          powersOf10 = int16_t(powersOf10 + bit);
+        }
+        bit >>= 1;
+      }
+    }
+
+    if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
+      for (; index >= 0; index--) {
+        if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) {
+          value *= traits::positiveBinaryPowerOfTen(index);
+          powersOf10 = int16_t(powersOf10 - bit);
+        }
+        bit >>= 1;
+      }
+    }
+
+    return powersOf10;
+  }
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Numbers/FloatTraits.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,201 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stddef.h>  // for size_t
+#include <stdint.h>
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Polyfills/alias_cast.hpp>
+#include <ArduinoJson/Polyfills/math.hpp>
+#include <ArduinoJson/Polyfills/preprocessor.hpp>
+#include <ArduinoJson/Polyfills/static_array.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T, size_t = sizeof(T)>
+struct FloatTraits {};
+
+template <typename T>
+struct FloatTraits<T, 8 /*64bits*/> {
+  typedef uint64_t mantissa_type;
+  static const short mantissa_bits = 52;
+  static const mantissa_type mantissa_max =
+      (mantissa_type(1) << mantissa_bits) - 1;
+
+  typedef int16_t exponent_type;
+  static const exponent_type exponent_max = 308;
+
+  template <typename TExponent>
+  static T make_float(T m, TExponent e) {
+    if (e > 0) {
+      for (uint8_t index = 0; e != 0; index++) {
+        if (e & 1)
+          m *= positiveBinaryPowerOfTen(index);
+        e >>= 1;
+      }
+    } else {
+      e = TExponent(-e);
+      for (uint8_t index = 0; e != 0; index++) {
+        if (e & 1)
+          m *= negativeBinaryPowerOfTen(index);
+        e >>= 1;
+      }
+    }
+    return m;
+  }
+
+  static T positiveBinaryPowerOfTen(int index) {
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(  //
+        uint32_t, factors,
+        ARDUINOJSON_EXPAND18({
+            0x40240000, 0x00000000,  // 1e1
+            0x40590000, 0x00000000,  // 1e2
+            0x40C38800, 0x00000000,  // 1e4
+            0x4197D784, 0x00000000,  // 1e8
+            0x4341C379, 0x37E08000,  // 1e16
+            0x4693B8B5, 0xB5056E17,  // 1e32
+            0x4D384F03, 0xE93FF9F5,  // 1e64
+            0x5A827748, 0xF9301D32,  // 1e128
+            0x75154FDD, 0x7F73BF3C   // 1e256
+        }));
+    return forge(
+        ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
+        ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
+  }
+
+  static T negativeBinaryPowerOfTen(int index) {
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(  //
+        uint32_t, factors,
+        ARDUINOJSON_EXPAND18({
+            0x3FB99999, 0x9999999A,  // 1e-1
+            0x3F847AE1, 0x47AE147B,  // 1e-2
+            0x3F1A36E2, 0xEB1C432D,  // 1e-4
+            0x3E45798E, 0xE2308C3A,  // 1e-8
+            0x3C9CD2B2, 0x97D889BC,  // 1e-16
+            0x3949F623, 0xD5A8A733,  // 1e-32
+            0x32A50FFD, 0x44F4A73D,  // 1e-64
+            0x255BBA08, 0xCF8C979D,  // 1e-128
+            0x0AC80628, 0x64AC6F43   // 1e-256
+        }));
+    return forge(
+        ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
+        ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
+  }
+
+  static T negativeBinaryPowerOfTenPlusOne(int index) {
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(  //
+        uint32_t, factors,
+        ARDUINOJSON_EXPAND18({
+            0x3FF00000, 0x00000000,  // 1e0
+            0x3FB99999, 0x9999999A,  // 1e-1
+            0x3F50624D, 0xD2F1A9FC,  // 1e-3
+            0x3E7AD7F2, 0x9ABCAF48,  // 1e-7
+            0x3CD203AF, 0x9EE75616,  // 1e-15
+            0x398039D6, 0x65896880,  // 1e-31
+            0x32DA53FC, 0x9631D10D,  // 1e-63
+            0x25915445, 0x81B7DEC2,  // 1e-127
+            0x0AFE07B2, 0x7DD78B14   // 1e-255
+        }));
+    return forge(
+        ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
+        ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
+  }
+
+  static T nan() {
+    return forge(0x7ff80000, 0x00000000);
+  }
+
+  static T inf() {
+    return forge(0x7ff00000, 0x00000000);
+  }
+
+  static T highest() {
+    return forge(0x7FEFFFFF, 0xFFFFFFFF);
+  }
+
+  static T lowest() {
+    return forge(0xFFEFFFFF, 0xFFFFFFFF);
+  }
+
+  // constructs a double floating point values from its binary representation
+  // we use this function to workaround platforms with single precision literals
+  // (for example, when -fsingle-precision-constant is passed to GCC)
+  static T forge(uint32_t msb, uint32_t lsb) {
+    return alias_cast<T>((uint64_t(msb) << 32) | lsb);
+  }
+};
+
+template <typename T>
+struct FloatTraits<T, 4 /*32bits*/> {
+  typedef uint32_t mantissa_type;
+  static const short mantissa_bits = 23;
+  static const mantissa_type mantissa_max =
+      (mantissa_type(1) << mantissa_bits) - 1;
+
+  typedef int8_t exponent_type;
+  static const exponent_type exponent_max = 38;
+
+  template <typename TExponent>
+  static T make_float(T m, TExponent e) {
+    if (e > 0) {
+      for (uint8_t index = 0; e != 0; index++) {
+        if (e & 1)
+          m *= positiveBinaryPowerOfTen(index);
+        e >>= 1;
+      }
+    } else {
+      e = -e;
+      for (uint8_t index = 0; e != 0; index++) {
+        if (e & 1)
+          m *= negativeBinaryPowerOfTen(index);
+        e >>= 1;
+      }
+    }
+    return m;
+  }
+
+  static T positiveBinaryPowerOfTen(int index) {
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(
+        T, factors,
+        ARDUINOJSON_EXPAND6({1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}));
+    return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
+  }
+
+  static T negativeBinaryPowerOfTen(int index) {
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(
+        T, factors,
+        ARDUINOJSON_EXPAND6({1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}));
+    return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
+  }
+
+  static T negativeBinaryPowerOfTenPlusOne(int index) {
+    ARDUINOJSON_DEFINE_STATIC_ARRAY(
+        T, factors,
+        ARDUINOJSON_EXPAND6({1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}));
+    return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
+  }
+
+  static T forge(uint32_t bits) {
+    return alias_cast<T>(bits);
+  }
+
+  static T nan() {
+    return forge(0x7fc00000);
+  }
+
+  static T inf() {
+    return forge(0x7f800000);
+  }
+
+  static T highest() {
+    return forge(0x7f7fffff);
+  }
+
+  static T lowest() {
+    return forge(0xFf7fffff);
+  }
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Numbers/Integer.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,32 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stdint.h>  // int64_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#if ARDUINOJSON_USE_LONG_LONG
+typedef int64_t Integer;
+typedef uint64_t UInt;
+#else
+typedef long Integer;
+typedef unsigned long UInt;
+#endif
+
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG
+#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T)                  \
+  static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer),     \
+                "To use 64-bit integers with ArduinoJson, you must set " \
+                "ARDUINOJSON_USE_LONG_LONG to 1. See "                   \
+                "https://arduinojson.org/v6/api/config/use_long_long/");
+#else
+#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Numbers/arithmeticCompare.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,121 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Numbers/Integer.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+enum CompareResult {
+  COMPARE_RESULT_DIFFER = 0,
+  COMPARE_RESULT_EQUAL = 1,
+  COMPARE_RESULT_GREATER = 2,
+  COMPARE_RESULT_LESS = 4,
+
+  COMPARE_RESULT_GREATER_OR_EQUAL = 3,
+  COMPARE_RESULT_LESS_OR_EQUAL = 5
+};
+
+template <typename T>
+CompareResult arithmeticCompare(const T &lhs, const T &rhs) {
+  if (lhs < rhs)
+    return COMPARE_RESULT_LESS;
+  else if (lhs > rhs)
+    return COMPARE_RESULT_GREATER;
+  else
+    return COMPARE_RESULT_EQUAL;
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+    const T1 &lhs, const T2 &rhs,
+    typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+                           sizeof(T1) < sizeof(T2),
+                       int  // Using int instead of void to avoid C2572 on
+                            // Visual Studio 2012, 2013, and 2015
+                       >::type * = 0) {
+  return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+    const T1 &lhs, const T2 &rhs,
+    typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+                       sizeof(T2) < sizeof(T1)>::type * = 0) {
+  return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+    const T1 &lhs, const T2 &rhs,
+    typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+                       is_signed<T1>::value == is_signed<T2>::value &&
+                       sizeof(T2) == sizeof(T1)>::type * = 0) {
+  return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+    const T1 &lhs, const T2 &rhs,
+    typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+                       is_unsigned<T1>::value && is_signed<T2>::value &&
+                       sizeof(T2) == sizeof(T1)>::type * = 0) {
+  if (rhs < 0)
+    return COMPARE_RESULT_GREATER;
+  return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+    const T1 &lhs, const T2 &rhs,
+    typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+                       is_signed<T1>::value && is_unsigned<T2>::value &&
+                       sizeof(T2) == sizeof(T1)>::type * = 0) {
+  if (lhs < 0)
+    return COMPARE_RESULT_LESS;
+  return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+    const T1 &lhs, const T2 &rhs,
+    typename enable_if<is_floating_point<T1>::value ||
+                       is_floating_point<T2>::value>::type * = 0) {
+  return arithmeticCompare<double>(static_cast<double>(lhs),
+                                   static_cast<double>(rhs));
+}
+
+template <typename T2>
+CompareResult arithmeticCompareNegateLeft(
+    UInt, const T2 &, typename enable_if<is_unsigned<T2>::value>::type * = 0) {
+  return COMPARE_RESULT_LESS;
+}
+
+template <typename T2>
+CompareResult arithmeticCompareNegateLeft(
+    UInt lhs, const T2 &rhs,
+    typename enable_if<is_signed<T2>::value>::type * = 0) {
+  if (rhs > 0)
+    return COMPARE_RESULT_LESS;
+  return arithmeticCompare(-rhs, static_cast<T2>(lhs));
+}
+
+template <typename T1>
+CompareResult arithmeticCompareNegateRight(
+    const T1 &, UInt, typename enable_if<is_unsigned<T1>::value>::type * = 0) {
+  return COMPARE_RESULT_GREATER;
+}
+
+template <typename T1>
+CompareResult arithmeticCompareNegateRight(
+    const T1 &lhs, UInt rhs,
+    typename enable_if<is_signed<T1>::value>::type * = 0) {
+  if (lhs > 0)
+    return COMPARE_RESULT_GREATER;
+  return arithmeticCompare(static_cast<T1>(rhs), -lhs);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Numbers/convertNumber.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,105 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+#elif defined(__GNUC__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#pragma GCC diagnostic push
+#endif
+#pragma GCC diagnostic ignored "-Wconversion"
+#endif
+
+#include <ArduinoJson/Numbers/Float.hpp>
+#include <ArduinoJson/Numbers/FloatTraits.hpp>
+#include <ArduinoJson/Numbers/Integer.hpp>
+#include <ArduinoJson/Polyfills/limits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TOut>::value && sizeof(TOut) <= sizeof(TIn),
+                   bool>::type
+canStorePositiveInteger(TIn value) {
+  return value <= TIn(numeric_limits<TOut>::highest());
+}
+
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TOut>::value && sizeof(TIn) < sizeof(TOut),
+                   bool>::type
+canStorePositiveInteger(TIn) {
+  return true;
+}
+
+template <typename TOut, typename TIn>
+typename enable_if<is_floating_point<TOut>::value, bool>::type
+canStorePositiveInteger(TIn) {
+  return true;
+}
+
+template <typename TOut, typename TIn>
+typename enable_if<is_floating_point<TOut>::value, bool>::type
+canStoreNegativeInteger(TIn) {
+  return true;
+}
+
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
+                       sizeof(TOut) <= sizeof(TIn),
+                   bool>::type
+canStoreNegativeInteger(TIn value) {
+  return value <= TIn(numeric_limits<TOut>::highest()) + 1;
+}
+
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
+                       sizeof(TIn) < sizeof(TOut),
+                   bool>::type
+canStoreNegativeInteger(TIn) {
+  return true;
+}
+
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value,
+                   bool>::type
+canStoreNegativeInteger(TIn) {
+  return false;
+}
+
+template <typename TOut, typename TIn>
+TOut convertPositiveInteger(TIn value) {
+  return canStorePositiveInteger<TOut>(value) ? TOut(value) : 0;
+}
+
+template <typename TOut, typename TIn>
+TOut convertNegativeInteger(TIn value) {
+  return canStoreNegativeInteger<TOut>(value) ? TOut(~value + 1) : 0;
+}
+
+template <typename TOut, typename TIn>
+typename enable_if<is_floating_point<TOut>::value, TOut>::type convertFloat(
+    TIn value) {
+  return TOut(value);
+}
+
+template <typename TOut, typename TIn>
+typename enable_if<!is_floating_point<TOut>::value, TOut>::type convertFloat(
+    TIn value) {
+  return value >= numeric_limits<TOut>::lowest() &&
+                 value <= numeric_limits<TOut>::highest()
+             ? TOut(value)
+             : 0;
+}
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#pragma GCC diagnostic pop
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Numbers/parseNumber.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,147 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Numbers/FloatTraits.hpp>
+#include <ArduinoJson/Numbers/convertNumber.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/ctype.hpp>
+#include <ArduinoJson/Polyfills/math.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantAs.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename A, typename B>
+struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
+
+inline bool parseNumber(const char* s, VariantData& result) {
+  typedef FloatTraits<Float> traits;
+  typedef choose_largest<traits::mantissa_type, UInt>::type mantissa_t;
+  typedef traits::exponent_type exponent_t;
+
+  ARDUINOJSON_ASSERT(s != 0);
+
+  bool is_negative = false;
+  switch (*s) {
+    case '-':
+      is_negative = true;
+      s++;
+      break;
+    case '+':
+      s++;
+      break;
+  }
+
+#if ARDUINOJSON_ENABLE_NAN
+  if (*s == 'n' || *s == 'N') {
+    result.setFloat(traits::nan());
+    return true;
+  }
+#endif
+
+#if ARDUINOJSON_ENABLE_INFINITY
+  if (*s == 'i' || *s == 'I') {
+    result.setFloat(is_negative ? -traits::inf() : traits::inf());
+    return true;
+  }
+#endif
+
+  if (!isdigit(*s) && *s != '.')
+    return false;
+
+  mantissa_t mantissa = 0;
+  exponent_t exponent_offset = 0;
+  const mantissa_t maxUint = UInt(-1);
+
+  while (isdigit(*s)) {
+    uint8_t digit = uint8_t(*s - '0');
+    if (mantissa > maxUint / 10)
+      break;
+    mantissa *= 10;
+    if (mantissa > maxUint - digit)
+      break;
+    mantissa += digit;
+    s++;
+  }
+
+  if (*s == '\0') {
+    if (is_negative)
+      result.setNegativeInteger(UInt(mantissa));
+    else
+      result.setPositiveInteger(UInt(mantissa));
+    return true;
+  }
+
+  // avoid mantissa overflow
+  while (mantissa > traits::mantissa_max) {
+    mantissa /= 10;
+    exponent_offset++;
+  }
+
+  // remaing digits can't fit in the mantissa
+  while (isdigit(*s)) {
+    exponent_offset++;
+    s++;
+  }
+
+  if (*s == '.') {
+    s++;
+    while (isdigit(*s)) {
+      if (mantissa < traits::mantissa_max / 10) {
+        mantissa = mantissa * 10 + uint8_t(*s - '0');
+        exponent_offset--;
+      }
+      s++;
+    }
+  }
+
+  int exponent = 0;
+  if (*s == 'e' || *s == 'E') {
+    s++;
+    bool negative_exponent = false;
+    if (*s == '-') {
+      negative_exponent = true;
+      s++;
+    } else if (*s == '+') {
+      s++;
+    }
+
+    while (isdigit(*s)) {
+      exponent = exponent * 10 + (*s - '0');
+      if (exponent + exponent_offset > traits::exponent_max) {
+        if (negative_exponent)
+          result.setFloat(is_negative ? -0.0f : 0.0f);
+        else
+          result.setFloat(is_negative ? -traits::inf() : traits::inf());
+        return true;
+      }
+      s++;
+    }
+    if (negative_exponent)
+      exponent = -exponent;
+  }
+  exponent += exponent_offset;
+
+  // we should be at the end of the string, otherwise it's an error
+  if (*s != '\0')
+    return false;
+
+  Float final_result =
+      traits::make_float(static_cast<Float>(mantissa), exponent);
+
+  result.setFloat(is_negative ? -final_result : final_result);
+  return true;
+}
+
+template <typename T>
+inline T parseNumber(const char* s) {
+  VariantData value;
+  value.init();  // VariantData is a POD, so it has no constructor
+  parseNumber(s, value);
+  return variantAs<T>(&value);
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Object/MemberProxy.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,190 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantOperators.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+#include <ArduinoJson/Variant/VariantShortcuts.hpp>
+#include <ArduinoJson/Variant/VariantTo.hpp>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4522)
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TObject, typename TStringRef>
+class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
+                    public VariantShortcuts<MemberProxy<TObject, TStringRef> >,
+                    public Visitable,
+                    public VariantTag {
+  typedef MemberProxy<TObject, TStringRef> this_type;
+
+ public:
+  typedef VariantRef variant_type;
+
+  FORCE_INLINE MemberProxy(TObject variant, TStringRef key)
+      : _object(variant), _key(key) {}
+
+  FORCE_INLINE MemberProxy(const MemberProxy &src)
+      : _object(src._object), _key(src._key) {}
+
+  FORCE_INLINE operator VariantConstRef() const {
+    return getUpstreamMember();
+  }
+
+  FORCE_INLINE this_type &operator=(const this_type &src) {
+    getOrAddUpstreamMember().set(src);
+    return *this;
+  }
+
+  template <typename TValue>
+  FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
+  operator=(const TValue &src) {
+    getOrAddUpstreamMember().set(src);
+    return *this;
+  }
+
+  // operator=(char*)
+  // operator=(const char*)
+  // operator=(const __FlashStringHelper*)
+  template <typename TChar>
+  FORCE_INLINE this_type &operator=(TChar *src) {
+    getOrAddUpstreamMember().set(src);
+    return *this;
+  }
+
+  FORCE_INLINE void clear() const {
+    getUpstreamMember().clear();
+  }
+
+  FORCE_INLINE bool isNull() const {
+    return getUpstreamMember().isNull();
+  }
+
+  template <typename TValue>
+  FORCE_INLINE typename VariantAs<TValue>::type as() const {
+    return getUpstreamMember().template as<TValue>();
+  }
+
+  template <typename T>
+  FORCE_INLINE operator T() const {
+    return getUpstreamMember();
+  }
+
+  template <typename TValue>
+  FORCE_INLINE bool is() const {
+    return getUpstreamMember().template is<TValue>();
+  }
+
+  FORCE_INLINE size_t size() const {
+    return getUpstreamMember().size();
+  }
+
+  FORCE_INLINE void remove(size_t index) const {
+    getUpstreamMember().remove(index);
+  }
+  // remove(char*) const
+  // remove(const char*) const
+  // remove(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
+      TChar *key) const {
+    getUpstreamMember().remove(key);
+  }
+  // remove(const std::string&) const
+  // remove(const String&) const
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
+      const TString &key) const {
+    getUpstreamMember().remove(key);
+  }
+
+  template <typename TValue>
+  FORCE_INLINE typename VariantTo<TValue>::type to() {
+    return getOrAddUpstreamMember().template to<TValue>();
+  }
+
+  template <typename TValue>
+  FORCE_INLINE bool set(const TValue &value) {
+    return getOrAddUpstreamMember().set(value);
+  }
+
+  // set(char*) const
+  // set(const char*) const
+  // set(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE bool set(TChar *value) {
+    return getOrAddUpstreamMember().set(value);
+  }
+
+  template <typename TVisitor>
+  typename TVisitor::result_type accept(TVisitor &visitor) const {
+    return getUpstreamMember().accept(visitor);
+  }
+
+  FORCE_INLINE VariantRef addElement() const {
+    return getOrAddUpstreamMember().addElement();
+  }
+
+  FORCE_INLINE VariantRef getElement(size_t index) const {
+    return getUpstreamMember().getElement(index);
+  }
+
+  FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
+    return getOrAddUpstreamMember().getOrAddElement(index);
+  }
+
+  // getMember(char*) const
+  // getMember(const char*) const
+  // getMember(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef getMember(TChar *key) const {
+    return getUpstreamMember().getMember(key);
+  }
+
+  // getMember(const std::string&) const
+  // getMember(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef getMember(const TString &key) const {
+    return getUpstreamMember().getMember(key);
+  }
+
+  // getOrAddMember(char*) const
+  // getOrAddMember(const char*) const
+  // getOrAddMember(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef getOrAddMember(TChar *key) const {
+    return getOrAddUpstreamMember().getOrAddMember(key);
+  }
+
+  // getOrAddMember(const std::string&) const
+  // getOrAddMember(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef getOrAddMember(const TString &key) const {
+    return getOrAddUpstreamMember().getOrAddMember(key);
+  }
+
+ private:
+  FORCE_INLINE VariantRef getUpstreamMember() const {
+    return _object.getMember(_key);
+  }
+
+  FORCE_INLINE VariantRef getOrAddUpstreamMember() const {
+    return _object.getOrAddMember(_key);
+  }
+
+  TObject _object;
+  TStringRef _key;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Object/ObjectFunctions.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,51 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Collection/CollectionData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TVisitor>
+typename TVisitor::result_type objectAccept(const CollectionData *obj,
+                                            TVisitor &visitor) {
+  if (obj)
+    return visitor.visitObject(*obj);
+  else
+    return visitor.visitNull();
+}
+
+inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
+  if (lhs == rhs)
+    return true;
+  if (!lhs || !rhs)
+    return false;
+  return lhs->equalsObject(*rhs);
+}
+
+template <typename TAdaptedString>
+inline VariantData *objectGetMember(const CollectionData *obj,
+                                    TAdaptedString key) {
+  if (!obj)
+    return 0;
+  return obj->getMember(key);
+}
+
+template <typename TAdaptedString>
+void objectRemove(CollectionData *obj, TAdaptedString key) {
+  if (!obj)
+    return;
+  obj->removeMember(key);
+}
+
+template <typename TAdaptedString>
+inline VariantData *objectGetOrAddMember(CollectionData *obj,
+                                         TAdaptedString key, MemoryPool *pool) {
+  if (!obj)
+    return 0;
+
+  return obj->getOrAddMember(key, pool);
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Object/ObjectImpl.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,69 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayRef.hpp>
+#include <ArduinoJson/Object/ObjectRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TObject>
+template <typename TString>
+inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
+    const TString& key) const {
+  return impl()->getOrAddMember(key).template to<ArrayRef>();
+}
+
+template <typename TObject>
+template <typename TChar>
+inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(TChar* key) const {
+  return impl()->getOrAddMember(key).template to<ArrayRef>();
+}
+
+template <typename TObject>
+template <typename TString>
+inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
+    const TString& key) const {
+  return impl()->getOrAddMember(key).template to<ObjectRef>();
+}
+
+template <typename TObject>
+template <typename TChar>
+inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
+    TChar* key) const {
+  return impl()->getOrAddMember(key).template to<ObjectRef>();
+}
+
+template <typename TObject>
+template <typename TString>
+inline typename enable_if<IsString<TString>::value, bool>::type
+ObjectShortcuts<TObject>::containsKey(const TString& key) const {
+  return !impl()->getMember(key).isUndefined();
+}
+
+template <typename TObject>
+template <typename TChar>
+inline typename enable_if<IsString<TChar*>::value, bool>::type
+ObjectShortcuts<TObject>::containsKey(TChar* key) const {
+  return !impl()->getMember(key).isUndefined();
+}
+
+template <typename TObject>
+template <typename TString>
+inline typename enable_if<IsString<TString*>::value,
+                          MemberProxy<TObject, TString*> >::type
+    ObjectShortcuts<TObject>::operator[](TString* key) const {
+  return MemberProxy<TObject, TString*>(*impl(), key);
+}
+
+template <typename TObject>
+template <typename TString>
+inline typename enable_if<IsString<TString>::value,
+                          MemberProxy<TObject, TString> >::type
+    ObjectShortcuts<TObject>::operator[](const TString& key) const {
+  return MemberProxy<TObject, TString>(*impl(), key);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Object/ObjectIterator.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,123 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Object/Pair.hpp>
+#include <ArduinoJson/Variant/SlotFunctions.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class PairPtr {
+ public:
+  PairPtr(MemoryPool *pool, VariantSlot *slot) : _pair(pool, slot) {}
+
+  const Pair *operator->() const {
+    return &_pair;
+  }
+
+  const Pair &operator*() const {
+    return _pair;
+  }
+
+ private:
+  Pair _pair;
+};
+
+class ObjectIterator {
+ public:
+  ObjectIterator() : _slot(0) {}
+
+  explicit ObjectIterator(MemoryPool *pool, VariantSlot *slot)
+      : _pool(pool), _slot(slot) {}
+
+  Pair operator*() const {
+    return Pair(_pool, _slot);
+  }
+  PairPtr operator->() {
+    return PairPtr(_pool, _slot);
+  }
+
+  bool operator==(const ObjectIterator &other) const {
+    return _slot == other._slot;
+  }
+
+  bool operator!=(const ObjectIterator &other) const {
+    return _slot != other._slot;
+  }
+
+  ObjectIterator &operator++() {
+    _slot = _slot->next();
+    return *this;
+  }
+
+  ObjectIterator &operator+=(size_t distance) {
+    _slot = _slot->next(distance);
+    return *this;
+  }
+
+  VariantSlot *internal() {
+    return _slot;
+  }
+
+ private:
+  MemoryPool *_pool;
+  VariantSlot *_slot;
+};
+
+class PairConstPtr {
+ public:
+  PairConstPtr(const VariantSlot *slot) : _pair(slot) {}
+
+  const PairConst *operator->() const {
+    return &_pair;
+  }
+
+  const PairConst &operator*() const {
+    return _pair;
+  }
+
+ private:
+  PairConst _pair;
+};
+
+class ObjectConstIterator {
+ public:
+  ObjectConstIterator() : _slot(0) {}
+
+  explicit ObjectConstIterator(const VariantSlot *slot) : _slot(slot) {}
+
+  PairConst operator*() const {
+    return PairConst(_slot);
+  }
+  PairConstPtr operator->() {
+    return PairConstPtr(_slot);
+  }
+
+  bool operator==(const ObjectConstIterator &other) const {
+    return _slot == other._slot;
+  }
+
+  bool operator!=(const ObjectConstIterator &other) const {
+    return _slot != other._slot;
+  }
+
+  ObjectConstIterator &operator++() {
+    _slot = _slot->next();
+    return *this;
+  }
+
+  ObjectConstIterator &operator+=(size_t distance) {
+    _slot = _slot->next(distance);
+    return *this;
+  }
+
+  const VariantSlot *internal() {
+    return _slot;
+  }
+
+ private:
+  const VariantSlot *_slot;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Object/ObjectRef.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,239 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Object/ObjectFunctions.hpp>
+#include <ArduinoJson/Object/ObjectIterator.hpp>
+
+// Returns the size (in bytes) of an object with n elements.
+// Can be very handy to determine the size of a StaticMemoryPool.
+#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
+  ((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TData>
+class ObjectRefBase {
+ public:
+  operator VariantConstRef() const {
+    const void* data = _data;  // prevent warning cast-align
+    return VariantConstRef(reinterpret_cast<const VariantData*>(data));
+  }
+
+  template <typename TVisitor>
+  typename TVisitor::result_type accept(TVisitor& visitor) const {
+    return objectAccept(_data, visitor);
+  }
+
+  FORCE_INLINE bool isNull() const {
+    return _data == 0;
+  }
+
+  FORCE_INLINE operator bool() const {
+    return _data != 0;
+  }
+
+  FORCE_INLINE size_t memoryUsage() const {
+    return _data ? _data->memoryUsage() : 0;
+  }
+
+  FORCE_INLINE size_t nesting() const {
+    return _data ? _data->nesting() : 0;
+  }
+
+  FORCE_INLINE size_t size() const {
+    return _data ? _data->size() : 0;
+  }
+
+ protected:
+  ObjectRefBase(TData* data) : _data(data) {}
+  TData* _data;
+};
+
+class ObjectConstRef : public ObjectRefBase<const CollectionData>,
+                       public Visitable {
+  friend class ObjectRef;
+  typedef ObjectRefBase<const CollectionData> base_type;
+
+ public:
+  typedef ObjectConstIterator iterator;
+
+  ObjectConstRef() : base_type(0) {}
+  ObjectConstRef(const CollectionData* data) : base_type(data) {}
+
+  FORCE_INLINE iterator begin() const {
+    if (!_data)
+      return iterator();
+    return iterator(_data->head());
+  }
+
+  FORCE_INLINE iterator end() const {
+    return iterator();
+  }
+
+  // containsKey(const std::string&) const
+  // containsKey(const String&) const
+  template <typename TString>
+  FORCE_INLINE bool containsKey(const TString& key) const {
+    return !getMember(key).isUndefined();
+  }
+
+  // containsKey(char*) const
+  // containsKey(const char*) const
+  // containsKey(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE bool containsKey(TChar* key) const {
+    return !getMember(key).isUndefined();
+  }
+
+  // getMember(const std::string&) const
+  // getMember(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantConstRef getMember(const TString& key) const {
+    return get_impl(adaptString(key));
+  }
+
+  // getMember(char*) const
+  // getMember(const char*) const
+  // getMember(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantConstRef getMember(TChar* key) const {
+    return get_impl(adaptString(key));
+  }
+
+  // operator[](const std::string&) const
+  // operator[](const String&) const
+  template <typename TString>
+  FORCE_INLINE
+      typename enable_if<IsString<TString>::value, VariantConstRef>::type
+      operator[](const TString& key) const {
+    return get_impl(adaptString(key));
+  }
+
+  // operator[](char*) const
+  // operator[](const char*) const
+  // operator[](const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE
+      typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
+      operator[](TChar* key) const {
+    return get_impl(adaptString(key));
+  }
+
+  FORCE_INLINE bool operator==(ObjectConstRef rhs) const {
+    return objectEquals(_data, rhs._data);
+  }
+
+ private:
+  template <typename TAdaptedString>
+  FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const {
+    return VariantConstRef(objectGetMember(_data, key));
+  }
+};
+
+class ObjectRef : public ObjectRefBase<CollectionData>,
+                  public ObjectShortcuts<ObjectRef>,
+                  public Visitable {
+  typedef ObjectRefBase<CollectionData> base_type;
+
+ public:
+  typedef ObjectIterator iterator;
+
+  FORCE_INLINE ObjectRef() : base_type(0), _pool(0) {}
+  FORCE_INLINE ObjectRef(MemoryPool* buf, CollectionData* data)
+      : base_type(data), _pool(buf) {}
+
+  operator VariantRef() const {
+    void* data = _data;  // prevent warning cast-align
+    return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
+  }
+
+  operator ObjectConstRef() const {
+    return ObjectConstRef(_data);
+  }
+
+  FORCE_INLINE iterator begin() const {
+    if (!_data)
+      return iterator();
+    return iterator(_pool, _data->head());
+  }
+
+  FORCE_INLINE iterator end() const {
+    return iterator();
+  }
+
+  void clear() const {
+    if (!_data)
+      return;
+    _data->clear();
+  }
+
+  FORCE_INLINE bool set(ObjectConstRef src) {
+    if (!_data || !src._data)
+      return false;
+    return _data->copyFrom(*src._data, _pool);
+  }
+
+  // getMember(const std::string&) const
+  // getMember(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef getMember(const TString& key) const {
+    return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
+  }
+
+  // getMember(char*) const
+  // getMember(const char*) const
+  // getMember(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef getMember(TChar* key) const {
+    return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
+  }
+
+  // getOrAddMember(const std::string&) const
+  // getOrAddMember(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef getOrAddMember(const TString& key) const {
+    return VariantRef(_pool,
+                      objectGetOrAddMember(_data, adaptString(key), _pool));
+  }
+
+  // getOrAddMember(char*) const
+  // getOrAddMember(const char*) const
+  // getOrAddMember(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef getOrAddMember(TChar* key) const {
+    return VariantRef(_pool,
+                      objectGetOrAddMember(_data, adaptString(key), _pool));
+  }
+
+  FORCE_INLINE bool operator==(ObjectRef rhs) const {
+    return objectEquals(_data, rhs._data);
+  }
+
+  FORCE_INLINE void remove(iterator it) const {
+    if (!_data)
+      return;
+    _data->removeSlot(it.internal());
+  }
+
+  // remove(const std::string&) const
+  // remove(const String&) const
+  template <typename TString>
+  FORCE_INLINE void remove(const TString& key) const {
+    objectRemove(_data, adaptString(key));
+  }
+
+  // remove(char*) const
+  // remove(const char*) const
+  // remove(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE void remove(TChar* key) const {
+    objectRemove(_data, adaptString(key));
+  }
+
+ private:
+  MemoryPool* _pool;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Object/ObjectShortcuts.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,73 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Strings/StringAdapters.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+template <typename TParent, typename TStringRef>
+class MemberProxy;
+
+template <typename TObject>
+class ObjectShortcuts {
+ public:
+  // containsKey(const std::string&) const
+  // containsKey(const String&) const
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
+  containsKey(const TString &key) const;
+
+  // containsKey(char*) const
+  // containsKey(const char*) const
+  // containsKey(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE typename enable_if<IsString<TChar *>::value, bool>::type
+  containsKey(TChar *key) const;
+
+  // operator[](const std::string&) const
+  // operator[](const String&) const
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value,
+                                  MemberProxy<TObject, TString> >::type
+  operator[](const TString &key) const;
+
+  // operator[](char*) const
+  // operator[](const char*) const
+  // operator[](const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE typename enable_if<IsString<TChar *>::value,
+                                  MemberProxy<TObject, TChar *> >::type
+  operator[](TChar *key) const;
+
+  // createNestedArray(const std::string&) const
+  // createNestedArray(const String&) const
+  template <typename TString>
+  FORCE_INLINE ArrayRef createNestedArray(const TString &key) const;
+
+  // createNestedArray(char*) const
+  // createNestedArray(const char*) const
+  // createNestedArray(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE ArrayRef createNestedArray(TChar *key) const;
+
+  // createNestedObject(const std::string&) const
+  // createNestedObject(const String&) const
+  template <typename TString>
+  ObjectRef createNestedObject(const TString &key) const;
+
+  // createNestedObject(char*) const
+  // createNestedObject(const char*) const
+  // createNestedObject(const __FlashStringHelper*) const
+  template <typename TChar>
+  ObjectRef createNestedObject(TChar *key) const;
+
+ private:
+  const TObject *impl() const {
+    return static_cast<const TObject *>(this);
+  }
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Object/Pair.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,55 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/String.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+// A key value pair for CollectionData.
+class Pair {
+ public:
+  Pair(MemoryPool* pool, VariantSlot* slot) {
+    if (slot) {
+      _key = String(slot->key(), !slot->ownsKey());
+      _value = VariantRef(pool, slot->data());
+    }
+  }
+
+  String key() const {
+    return _key;
+  }
+
+  VariantRef value() const {
+    return _value;
+  }
+
+ private:
+  String _key;
+  VariantRef _value;
+};
+
+class PairConst {
+ public:
+  PairConst(const VariantSlot* slot) {
+    if (slot) {
+      _key = String(slot->key(), !slot->ownsKey());
+      _value = VariantConstRef(slot->data());
+    }
+  }
+
+  String key() const {
+    return _key;
+  }
+
+  VariantConstRef value() const {
+    return _value;
+  }
+
+ private:
+  String _key;
+  VariantConstRef _value;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/alias_cast.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,29 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stdint.h>
+#include <stdlib.h>  // for size_t
+
+#include <ArduinoJson/Configuration.hpp>
+#include "math.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T, typename F>
+struct alias_cast_t {
+  union {
+    F raw;
+    T data;
+  };
+};
+
+template <typename T, typename F>
+T alias_cast(F raw_data) {
+  alias_cast_t<T, F> ac;
+  ac.raw = raw_data;
+  return ac.data;
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/assert.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,14 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+
+#if ARDUINOJSON_DEBUG
+#include <assert.h>
+#define ARDUINOJSON_ASSERT(X) assert(X)
+#else
+#define ARDUINOJSON_ASSERT(X) ((void)0)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/attributes.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,45 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#ifdef _MSC_VER  // Visual Studio
+
+#define FORCE_INLINE  // __forceinline causes C4714 when returning std::string
+#define NO_INLINE __declspec(noinline)
+#define DEPRECATED(msg) __declspec(deprecated(msg))
+
+#elif defined(__GNUC__)  // GCC or Clang
+
+#define FORCE_INLINE __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#define DEPRECATED(msg) __attribute__((deprecated(msg)))
+#else
+#define DEPRECATED(msg) __attribute__((deprecated))
+#endif
+
+#else  // Other compilers
+
+#define FORCE_INLINE
+#define NO_INLINE
+#define DEPRECATED(msg)
+
+#endif
+
+#if __cplusplus >= 201103L
+#define NOEXCEPT noexcept
+#else
+#define NOEXCEPT throw()
+#endif
+
+#if defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+#define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check)))
+#else
+#define ARDUINOJSON_NO_SANITIZE(check)
+#endif
+#else
+#define ARDUINOJSON_NO_SANITIZE(check)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/ctype.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,20 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#ifndef isdigit
+inline bool isdigit(char c) {
+  return '0' <= c && c <= '9';
+}
+#endif
+
+inline bool issign(char c) {
+  return '-' == c || c == '+';
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/integer.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,30 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stdint.h>  // int8_t, int16_t
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <int Bits>
+struct int_t;
+
+template <>
+struct int_t<8> {
+  typedef int8_t type;
+};
+
+template <>
+struct int_t<16> {
+  typedef int16_t type;
+};
+
+template <>
+struct int_t<32> {
+  typedef int32_t type;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/limits.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,45 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "type_traits.hpp"
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4310)
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Differs from standard because we can't use the symbols "min" and "max"
+template <typename T, typename Enable = void>
+struct numeric_limits;
+
+template <typename T>
+struct numeric_limits<T, typename enable_if<is_unsigned<T>::value>::type> {
+  static T lowest() {
+    return 0;
+  }
+  static T highest() {
+    return T(-1);
+  }
+};
+
+template <typename T>
+struct numeric_limits<
+    T, typename enable_if<is_integral<T>::value && is_signed<T>::value>::type> {
+  static T lowest() {
+    return T(T(1) << (sizeof(T) * 8 - 1));
+  }
+  static T highest() {
+    return T(~lowest());
+  }
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/math.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,27 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Some libraries #define isnan() and isinf() so we need to check before
+// using this name
+
+#ifndef isnan
+template <typename T>
+bool isnan(T x) {
+  return x != x;
+}
+#endif
+
+#ifndef isinf
+template <typename T>
+bool isinf(T x) {
+  return x != 0.0 && x * 2 == x;
+}
+#endif
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/mpl/max.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,26 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stddef.h>  // for size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that returns the highest value
+template <size_t X, size_t Y, bool MaxIsX = (X > Y)>
+struct Max {};
+
+template <size_t X, size_t Y>
+struct Max<X, Y, true> {
+  static const size_t value = X;
+};
+
+template <size_t X, size_t Y>
+struct Max<X, Y, false> {
+  static const size_t value = Y;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/pgmspace.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,79 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+// Wraps a const char* so that the our functions are picked only if the
+// originals are missing
+struct pgm_p {
+  pgm_p(const char* p) : address(p) {}
+  const char* address;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#ifndef strlen_P
+inline size_t strlen_P(ARDUINOJSON_NAMESPACE::pgm_p s) {
+  const char* p = s.address;
+  ARDUINOJSON_ASSERT(p != NULL);
+  while (pgm_read_byte(p)) p++;
+  return size_t(p - s.address);
+}
+#endif
+
+#ifndef strncmp_P
+inline int strncmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b, size_t n) {
+  const char* s1 = a;
+  const char* s2 = b.address;
+  ARDUINOJSON_ASSERT(s1 != NULL);
+  ARDUINOJSON_ASSERT(s2 != NULL);
+  while (n-- > 0) {
+    char c1 = *s1++;
+    char c2 = static_cast<char>(pgm_read_byte(s2++));
+    if (c1 < c2)
+      return -1;
+    if (c1 > c2)
+      return 1;
+    if (c1 == 0 /* and c2 as well */)
+      return 0;
+  }
+  return 0;
+}
+#endif
+
+#ifndef strcmp_P
+inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) {
+  const char* s1 = a;
+  const char* s2 = b.address;
+  ARDUINOJSON_ASSERT(s1 != NULL);
+  ARDUINOJSON_ASSERT(s2 != NULL);
+  for (;;) {
+    char c1 = *s1++;
+    char c2 = static_cast<char>(pgm_read_byte(s2++));
+    if (c1 < c2)
+      return -1;
+    if (c1 > c2)
+      return 1;
+    if (c1 == 0 /* and c2 as well */)
+      return 0;
+  }
+}
+#endif
+
+#ifndef memcpy_P
+inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) {
+  uint8_t* d = reinterpret_cast<uint8_t*>(dst);
+  const char* s = src.address;
+  ARDUINOJSON_ASSERT(d != NULL);
+  ARDUINOJSON_ASSERT(s != NULL);
+  while (n-- > 0) {
+    *d++ = pgm_read_byte(s++);
+  }
+  return dst;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,32 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+typename enable_if<is_pointer<T>::value, T>::type pgm_read(const void* p) {
+  return reinterpret_cast<T>(pgm_read_ptr(p));
+}
+
+template <typename T>
+typename enable_if<is_floating_point<T>::value &&
+                       sizeof(T) == sizeof(float),  // on AVR sizeof(double) ==
+                                                    // sizeof(float)
+                   T>::type
+pgm_read(const void* p) {
+  return pgm_read_float(p);
+}
+
+template <typename T>
+typename enable_if<is_same<T, uint32_t>::value, T>::type pgm_read(
+    const void* p) {
+  return pgm_read_dword(p);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/preprocessor.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,36 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#define ARDUINOJSON_EXPAND6(a, b, c, d, e, f) a, b, c, d, e, f
+#define ARDUINOJSON_EXPAND7(a, b, c, d, e, f, g) a, b, c, d, e, f, g
+#define ARDUINOJSON_EXPAND9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i
+#define ARDUINOJSON_EXPAND18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, \
+                             q, r)                                           \
+  a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r
+
+#define ARDUINOJSON_CONCAT_(A, B) A##B
+#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B)
+#define ARDUINOJSON_CONCAT4(A, B, C, D) \
+  ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
+
+#define ARDUINOJSON_HEX_DIGIT_0000() 0
+#define ARDUINOJSON_HEX_DIGIT_0001() 1
+#define ARDUINOJSON_HEX_DIGIT_0010() 2
+#define ARDUINOJSON_HEX_DIGIT_0011() 3
+#define ARDUINOJSON_HEX_DIGIT_0100() 4
+#define ARDUINOJSON_HEX_DIGIT_0101() 5
+#define ARDUINOJSON_HEX_DIGIT_0110() 6
+#define ARDUINOJSON_HEX_DIGIT_0111() 7
+#define ARDUINOJSON_HEX_DIGIT_1000() 8
+#define ARDUINOJSON_HEX_DIGIT_1001() 9
+#define ARDUINOJSON_HEX_DIGIT_1010() A
+#define ARDUINOJSON_HEX_DIGIT_1011() B
+#define ARDUINOJSON_HEX_DIGIT_1100() C
+#define ARDUINOJSON_HEX_DIGIT_1101() D
+#define ARDUINOJSON_HEX_DIGIT_1110() E
+#define ARDUINOJSON_HEX_DIGIT_1111() F
+#define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D()
+#define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/safe_strcmp.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,32 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stdint.h>  // int8_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+inline int safe_strcmp(const char* a, const char* b) {
+  if (a == b)
+    return 0;
+  if (!a)
+    return -1;
+  if (!b)
+    return 1;
+  return strcmp(a, b);
+}
+
+inline int safe_strncmp(const char* a, const char* b, size_t n) {
+  if (a == b)
+    return 0;
+  if (!a)
+    return -1;
+  if (!b)
+    return 1;
+  return strncmp(a, b, n);
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/static_array.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,34 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+
+#if ARDUINOJSON_ENABLE_PROGMEM
+
+#include <ArduinoJson/Polyfills/pgmspace_generic.hpp>
+
+#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY
+#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \
+  static type const name[] PROGMEM = value;
+#endif
+
+#ifndef ARDUINOJSON_READ_STATIC_ARRAY
+#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \
+  pgm_read<type>(name + index)
+#endif
+
+#else  // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0
+
+#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY
+#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \
+  static type const name[] = value;
+#endif
+
+#ifndef ARDUINOJSON_READ_STATIC_ARRAY
+#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index]
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,24 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "type_traits/conditional.hpp"
+#include "type_traits/enable_if.hpp"
+#include "type_traits/integral_constant.hpp"
+#include "type_traits/is_array.hpp"
+#include "type_traits/is_base_of.hpp"
+#include "type_traits/is_class.hpp"
+#include "type_traits/is_const.hpp"
+#include "type_traits/is_convertible.hpp"
+#include "type_traits/is_enum.hpp"
+#include "type_traits/is_floating_point.hpp"
+#include "type_traits/is_integral.hpp"
+#include "type_traits/is_pointer.hpp"
+#include "type_traits/is_same.hpp"
+#include "type_traits/is_signed.hpp"
+#include "type_traits/is_unsigned.hpp"
+#include "type_traits/make_unsigned.hpp"
+#include "type_traits/remove_const.hpp"
+#include "type_traits/remove_reference.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/conditional.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,20 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <bool Condition, class TrueType, class FalseType>
+struct conditional {
+  typedef TrueType type;
+};
+
+template <class TrueType, class FalseType>
+struct conditional<false, TrueType, FalseType> {
+  typedef FalseType type;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/declval.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,14 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+T declval();
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/enable_if.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,19 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that return the type T if Condition is true.
+template <bool Condition, typename T = void>
+struct enable_if {};
+
+template <typename T>
+struct enable_if<true, T> {
+  typedef T type;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/integral_constant.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,19 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T, T v>
+struct integral_constant {
+  static const T value = v;
+};
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_array.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,21 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stddef.h>  // size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct is_array : false_type {};
+
+template <typename T>
+struct is_array<T[]> : true_type {};
+
+template <typename T, size_t N>
+struct is_array<T[N]> : true_type {};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,26 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that returns true if Derived inherits from TBase is an
+// integral type.
+template <typename TBase, typename TDerived>
+class is_base_of {
+ protected:  // <- to avoid GCC's "all member functions in class are private"
+  typedef char Yes[1];
+  typedef char No[2];
+
+  static Yes &probe(const TBase *);
+  static No &probe(...);
+
+ public:
+  static const bool value =
+      sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes);
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_class.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,26 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "declval.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct is_class {
+ protected:  // <- to avoid GCC's "all member functions in class are private"
+  typedef char Yes[1];
+  typedef char No[2];
+
+  template <typename U>
+  static Yes &probe(void (U::*)(void));
+  template <typename>
+  static No &probe(...);
+
+ public:
+  static const bool value = sizeof(probe<T>(0)) == sizeof(Yes);
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_const.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,17 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that return the type T without the const modifier
+template <typename T>
+struct is_const : false_type {};
+
+template <typename T>
+struct is_const<const T> : true_type {};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_convertible.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,47 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "declval.hpp"
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// conversion from 'T' to 'To', possible loss of data
+#pragma warning(disable : 4244)
+#endif
+
+// clang-format off
+#ifdef __ICCARM__
+// Suppress IAR Compiler Warning[Pa093]: implicit conversion from floating point to integer
+#pragma diag_suppress=Pa093
+#endif
+// clang-format on
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename From, typename To>
+struct is_convertible {
+ protected:  // <- to avoid GCC's "all member functions in class are private"
+  typedef char Yes[1];
+  typedef char No[2];
+
+  static Yes &probe(To);
+  static No &probe(...);
+
+ public:
+  static const bool value = sizeof(probe(declval<From>())) == sizeof(Yes);
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// clang-format off
+#ifdef __ICCARM__
+#pragma diag_default=Pa093
+#endif
+// clang-format on
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_enum.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,22 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "is_class.hpp"
+#include "is_convertible.hpp"
+#include "is_floating_point.hpp"
+#include "is_integral.hpp"
+#include "is_same.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct is_enum {
+  static const bool value = is_convertible<T, int>::value &&
+                            !is_class<T>::value && !is_integral<T>::value &&
+                            !is_floating_point<T>::value;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,19 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename>
+struct is_floating_point : false_type {};
+
+template <>
+struct is_floating_point<float> : true_type {};
+
+template <>
+struct is_floating_point<double> : true_type {};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_integral.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,33 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include "is_same.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that returns true if T is an integral type.
+template <typename T>
+struct is_integral {
+  static const bool value =
+      is_same<T, signed char>::value || is_same<T, unsigned char>::value ||
+      is_same<T, signed short>::value || is_same<T, unsigned short>::value ||
+      is_same<T, signed int>::value || is_same<T, unsigned int>::value ||
+      is_same<T, signed long>::value || is_same<T, unsigned long>::value ||
+#if ARDUINOJSON_HAS_LONG_LONG
+      is_same<T, signed long long>::value ||
+      is_same<T, unsigned long long>::value ||
+#endif
+#if ARDUINOJSON_HAS_INT64
+      is_same<T, signed __int64>::value ||
+      is_same<T, unsigned __int64>::value ||
+#endif
+      is_same<T, char>::value || is_same<T, bool>::value;
+};
+
+template <typename T>
+struct is_integral<const T> : is_integral<T> {};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_pointer.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,16 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct is_pointer : false_type {};
+
+template <typename T>
+struct is_pointer<T*> : true_type {};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_same.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,17 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that returns true if types T and U are the same.
+template <typename T, typename U>
+struct is_same : false_type {};
+
+template <typename T>
+struct is_same<T, T> : true_type {};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_signed.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,43 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename>
+struct is_signed : false_type {};
+
+template <>
+struct is_signed<char> : true_type {};
+
+template <>
+struct is_signed<signed char> : true_type {};
+
+template <>
+struct is_signed<signed short> : true_type {};
+
+template <>
+struct is_signed<signed int> : true_type {};
+
+template <>
+struct is_signed<signed long> : true_type {};
+
+template <>
+struct is_signed<float> : true_type {};
+
+template <>
+struct is_signed<double> : true_type {};
+
+#if ARDUINOJSON_HAS_LONG_LONG
+template <>
+struct is_signed<signed long long> : true_type {};
+#endif
+
+#if ARDUINOJSON_HAS_INT64
+template <>
+struct is_signed<signed __int64> : true_type {};
+#endif
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,37 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename>
+struct is_unsigned : false_type {};
+
+template <>
+struct is_unsigned<bool> : true_type {};
+
+template <>
+struct is_unsigned<unsigned char> : true_type {};
+
+template <>
+struct is_unsigned<unsigned short> : true_type {};
+
+template <>
+struct is_unsigned<unsigned int> : true_type {};
+
+template <>
+struct is_unsigned<unsigned long> : true_type {};
+
+#if ARDUINOJSON_HAS_INT64
+template <>
+struct is_unsigned<unsigned __int64> : true_type {};
+#endif
+
+#if ARDUINOJSON_HAS_LONG_LONG
+template <>
+struct is_unsigned<unsigned long long> : true_type {};
+#endif
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,49 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "type_identity.hpp"
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct make_unsigned;
+
+template <>
+struct make_unsigned<char> : type_identity<unsigned char> {};
+
+template <>
+struct make_unsigned<signed char> : type_identity<unsigned char> {};
+template <>
+struct make_unsigned<unsigned char> : type_identity<unsigned char> {};
+
+template <>
+struct make_unsigned<signed short> : type_identity<unsigned short> {};
+template <>
+struct make_unsigned<unsigned short> : type_identity<unsigned short> {};
+
+template <>
+struct make_unsigned<signed int> : type_identity<unsigned int> {};
+template <>
+struct make_unsigned<unsigned int> : type_identity<unsigned int> {};
+
+template <>
+struct make_unsigned<signed long> : type_identity<unsigned long> {};
+template <>
+struct make_unsigned<unsigned long> : type_identity<unsigned long> {};
+
+#if ARDUINOJSON_HAS_LONG_LONG
+template <>
+struct make_unsigned<signed long long> : type_identity<unsigned long long> {};
+template <>
+struct make_unsigned<unsigned long long> : type_identity<unsigned long long> {};
+#endif
+
+#if ARDUINOJSON_HAS_INT64
+template <>
+struct make_unsigned<signed __int64> : type_identity<unsigned __int64> {};
+template <>
+struct make_unsigned<unsigned __int64> : type_identity<unsigned __int64> {};
+#endif
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/remove_const.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,20 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that return the type T without the const modifier
+template <typename T>
+struct remove_const {
+  typedef T type;
+};
+template <typename T>
+struct remove_const<const T> {
+  typedef T type;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/remove_reference.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,20 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that return the type T without the reference modifier.
+template <typename T>
+struct remove_reference {
+  typedef T type;
+};
+template <typename T>
+struct remove_reference<T&> {
+  typedef T type;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/type_traits/type_identity.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,15 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct type_identity {
+  typedef T type;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Polyfills/utility.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,28 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "type_traits.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+template <typename T>
+inline void swap(T& a, T& b) {
+  T t(a);
+  a = b;
+  b = t;
+}
+
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+template <typename T>
+typename remove_reference<T>::type&& move(T&& t) {
+  return static_cast<typename remove_reference<T>::type&&>(t);
+}
+#else
+template <typename T>
+T& move(T& t) {
+  return t;
+}
+#endif
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/CountingDecorator.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,33 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class CountingDecorator {
+ public:
+  explicit CountingDecorator(TWriter& writer) : _writer(writer), _count(0) {}
+
+  void write(uint8_t c) {
+    _count += _writer.write(c);
+  }
+
+  void write(const uint8_t* s, size_t n) {
+    _count += _writer.write(s, n);
+  }
+
+  size_t count() const {
+    return _count;
+  }
+
+ private:
+  TWriter _writer;
+  size_t _count;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/Writer.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,47 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// The default writer is a simple wrapper for Writers that are not copiable
+template <typename TDestination, typename Enable = void>
+class Writer {
+ public:
+  explicit Writer(TDestination& dest) : _dest(&dest) {}
+
+  size_t write(uint8_t c) {
+    return _dest->write(c);
+  }
+
+  size_t write(const uint8_t* s, size_t n) {
+    return _dest->write(s, n);
+  }
+
+ private:
+  TDestination* _dest;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#include <ArduinoJson/Serialization/Writers/StaticStringWriter.hpp>
+
+#if ARDUINOJSON_ENABLE_STD_STRING
+#include <ArduinoJson/Serialization/Writers/StdStringWriter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+#include <ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+#include <ArduinoJson/Serialization/Writers/StdStreamWriter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
+#include <ArduinoJson/Serialization/Writers/PrintWriter.hpp>
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,52 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <Arduino.h>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <>
+class Writer< ::String, void> {
+  static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
+
+ public:
+  explicit Writer(::String &str) : _destination(&str) {
+    _size = 0;
+  }
+
+  ~Writer() {
+    flush();
+  }
+
+  size_t write(uint8_t c) {
+    ARDUINOJSON_ASSERT(_size < bufferCapacity);
+    _buffer[_size++] = static_cast<char>(c);
+    if (_size + 1 >= bufferCapacity)
+      flush();
+    return 1;
+  }
+
+  size_t write(const uint8_t *s, size_t n) {
+    for (size_t i = 0; i < n; i++) {
+      write(s[i]);
+    }
+    return n;
+  }
+
+ private:
+  void flush() {
+    ARDUINOJSON_ASSERT(_size < bufferCapacity);
+    _buffer[_size] = 0;
+    *_destination += _buffer;
+    _size = 0;
+  }
+
+  ::String *_destination;
+  char _buffer[bufferCapacity];
+  size_t _size;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/Writers/DummyWriter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,21 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class DummyWriter {
+ public:
+  size_t write(uint8_t) {
+    return 1;
+  }
+
+  size_t write(const uint8_t*, size_t n) {
+    return n;
+  }
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/Writers/PrintWriter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,28 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TDestination>
+class Writer<
+    TDestination,
+    typename enable_if<is_base_of< ::Print, TDestination>::value>::type> {
+ public:
+  explicit Writer(::Print& print) : _print(&print) {}
+
+  size_t write(uint8_t c) {
+    return _print->write(c);
+  }
+
+  size_t write(const uint8_t* s, size_t n) {
+    return _print->write(s, n);
+  }
+
+ private:
+  ::Print* _print;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,40 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A Print implementation that allows to write in a char[]
+class StaticStringWriter {
+ public:
+  StaticStringWriter(char *buf, size_t size) : end(buf + size - 1), p(buf) {
+    *p = '\0';
+  }
+
+  size_t write(uint8_t c) {
+    if (p >= end)
+      return 0;
+    *p++ = static_cast<char>(c);
+    *p = '\0';
+    return 1;
+  }
+
+  size_t write(const uint8_t *s, size_t n) {
+    char *begin = p;
+    while (p < end && n > 0) {
+      *p++ = static_cast<char>(*s++);
+      n--;
+    }
+    *p = '\0';
+    return size_t(p - begin);
+  }
+
+ private:
+  char *end;
+  char *p;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,32 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ostream>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TDestination>
+class Writer<
+    TDestination,
+    typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
+ public:
+  explicit Writer(std::ostream& os) : _os(&os) {}
+
+  size_t write(uint8_t c) {
+    _os->put(static_cast<char>(c));
+    return 1;
+  }
+
+  size_t write(const uint8_t* s, size_t n) {
+    _os->write(reinterpret_cast<const char*>(s),
+               static_cast<std::streamsize>(n));
+    return n;
+  }
+
+ private:
+  std::ostream* _os;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/Writers/StdStringWriter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,40 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+#include <string>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <class T>
+struct is_std_string : false_type {};
+
+template <class TCharTraits, class TAllocator>
+struct is_std_string<std::basic_string<char, TCharTraits, TAllocator> >
+    : true_type {};
+
+template <typename TDestination>
+class Writer<TDestination,
+             typename enable_if<is_std_string<TDestination>::value>::type> {
+ public:
+  Writer(TDestination &str) : _str(&str) {}
+
+  size_t write(uint8_t c) {
+    _str->operator+=(static_cast<char>(c));
+    return 1;
+  }
+
+  size_t write(const uint8_t *s, size_t n) {
+    _str->append(reinterpret_cast<const char *>(s), n);
+    return n;
+  }
+
+ private:
+  TDestination *_str;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/measure.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,18 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Serialization/Writers/DummyWriter.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <template <typename> class TSerializer, typename TSource>
+size_t measure(const TSource &source) {
+  DummyWriter dp;
+  TSerializer<DummyWriter> serializer(dp);
+  return source.accept(serializer);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Serialization/serialize.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,43 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Serialization/Writer.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <template <typename> class TSerializer, typename TSource,
+          typename TWriter>
+size_t doSerialize(const TSource &source, TWriter writer) {
+  TSerializer<TWriter> serializer(writer);
+  return source.accept(serializer);
+}
+
+template <template <typename> class TSerializer, typename TSource,
+          typename TDestination>
+size_t serialize(const TSource &source, TDestination &destination) {
+  Writer<TDestination> writer(destination);
+  return doSerialize<TSerializer>(source, writer);
+}
+
+template <template <typename> class TSerializer, typename TSource>
+size_t serialize(const TSource &source, void *buffer, size_t bufferSize) {
+  StaticStringWriter writer(reinterpret_cast<char *>(buffer), bufferSize);
+  return doSerialize<TSerializer>(source, writer);
+}
+
+template <template <typename> class TSerializer, typename TSource,
+          typename TChar, size_t N>
+#if defined _MSC_VER && _MSC_VER < 1900
+typename enable_if<sizeof(remove_reference<TChar>::type) == 1, size_t>::type
+#else
+typename enable_if<sizeof(TChar) == 1, size_t>::type
+#endif
+serialize(const TSource &source, TChar (&buffer)[N]) {
+  StaticStringWriter writer(reinterpret_cast<char *>(buffer), N);
+  return doSerialize<TSerializer>(source, writer);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/StringStorage/StringCopier.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,62 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class StringCopier {
+ public:
+  StringCopier(MemoryPool& pool) : _pool(&pool) {}
+
+  void startString() {
+    _pool->getFreeZone(&_ptr, &_capacity);
+    _size = 0;
+  }
+
+  const char* save() {
+    ARDUINOJSON_ASSERT(_ptr);
+    return _pool->saveStringFromFreeZone(_size);
+  }
+
+  void append(const char* s) {
+    while (*s) append(*s++);
+  }
+
+  void append(const char* s, size_t n) {
+    while (n-- > 0) append(*s++);
+  }
+
+  void append(char c) {
+    if (!_ptr)
+      return;
+
+    if (_size >= _capacity) {
+      _ptr = 0;
+      _pool->markAsOverflowed();
+      return;
+    }
+
+    _ptr[_size++] = c;
+  }
+
+  bool isValid() {
+    return _ptr != 0;
+  }
+
+  const char* c_str() {
+    return _ptr;
+  }
+
+  typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+  MemoryPool* _pool;
+  char* _ptr;
+  size_t _size;
+  size_t _capacity;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/StringStorage/StringMover.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,42 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class StringMover {
+ public:
+  StringMover(char* ptr) : _writePtr(ptr) {}
+
+  void startString() {
+    _startPtr = _writePtr;
+  }
+
+  const char* save() const {
+    return _startPtr;
+  }
+
+  void append(char c) {
+    *_writePtr++ = c;
+  }
+
+  bool isValid() const {
+    return true;
+  }
+
+  const char* c_str() const {
+    return _startPtr;
+  }
+
+  typedef storage_policies::store_by_address storage_policy;
+
+ private:
+  char* _writePtr;
+  char* _startPtr;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/StringStorage/StringStorage.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,23 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/StringStorage/StringCopier.hpp>
+#include <ArduinoJson/StringStorage/StringMover.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TInput>
+StringCopier makeStringStorage(TInput&, MemoryPool& pool) {
+  return StringCopier(pool);
+}
+
+template <typename TChar>
+StringMover makeStringStorage(
+    TChar* input, MemoryPool&,
+    typename enable_if<!is_const<TChar>::value>::type* = 0) {
+  return StringMover(reinterpret_cast<char*>(input));
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/ArduinoStringAdapter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,62 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <Arduino.h>
+
+#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class ArduinoStringAdapter {
+ public:
+  ArduinoStringAdapter(const ::String& str) : _str(&str) {}
+
+  void copyTo(char* p, size_t n) const {
+    memcpy(p, _str->c_str(), n);
+  }
+
+  bool isNull() const {
+    // Arduino's String::c_str() can return NULL
+    return !_str->c_str();
+  }
+
+  int compare(const char* other) const {
+    // Arduino's String::c_str() can return NULL
+    const char* me = _str->c_str();
+    return safe_strcmp(me, other);
+  }
+
+  bool equals(const char* expected) const {
+    return compare(expected) == 0;
+  }
+
+  size_t size() const {
+    return _str->length();
+  }
+
+  const char* begin() const {
+    return _str->c_str();
+  }
+
+  typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+  const ::String* _str;
+};
+
+template <>
+struct IsString< ::String> : true_type {};
+
+template <>
+struct IsString< ::StringSumHelper> : true_type {};
+
+inline ArduinoStringAdapter adaptString(const ::String& str) {
+  return ArduinoStringAdapter(str);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/ConstRamStringAdapter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,62 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stddef.h>  // size_t
+#include <string.h>  // strcmp
+
+#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class ConstRamStringAdapter {
+ public:
+  ConstRamStringAdapter(const char* str = 0) : _str(str) {}
+
+  int compare(const char* other) const {
+    return safe_strcmp(_str, other);
+  }
+
+  bool equals(const char* expected) const {
+    return compare(expected) == 0;
+  }
+
+  bool isNull() const {
+    return !_str;
+  }
+
+  size_t size() const {
+    if (!_str)
+      return 0;
+    return strlen(_str);
+  }
+
+  const char* data() const {
+    return _str;
+  }
+
+  const char* begin() const {
+    return _str;
+  }
+
+  typedef storage_policies::store_by_address storage_policy;
+
+ protected:
+  const char* _str;
+};
+
+template <>
+struct IsString<const char*> : true_type {};
+
+template <int N>
+struct IsString<const char[N]> : true_type {};
+
+inline ConstRamStringAdapter adaptString(const char* str) {
+  return ConstRamStringAdapter(str);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/FlashStringAdapter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,62 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/pgmspace.hpp>
+#include <ArduinoJson/Strings/FlashStringIterator.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class FlashStringAdapter {
+ public:
+  FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {}
+
+  int compare(const char* other) const {
+    if (!other && !_str)
+      return 0;
+    if (!_str)
+      return -1;
+    if (!other)
+      return 1;
+    return -strcmp_P(other, reinterpret_cast<const char*>(_str));
+  }
+
+  bool equals(const char* expected) const {
+    return compare(expected) == 0;
+  }
+
+  bool isNull() const {
+    return !_str;
+  }
+
+  void copyTo(char* p, size_t n) const {
+    memcpy_P(p, reinterpret_cast<const char*>(_str), n);
+  }
+
+  size_t size() const {
+    if (!_str)
+      return 0;
+    return strlen_P(reinterpret_cast<const char*>(_str));
+  }
+
+  FlashStringIterator begin() const {
+    return FlashStringIterator(_str);
+  }
+
+  typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+  const __FlashStringHelper* _str;
+};
+
+inline FlashStringAdapter adaptString(const __FlashStringHelper* str) {
+  return FlashStringAdapter(str);
+}
+
+template <>
+struct IsString<const __FlashStringHelper*> : true_type {};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/FlashStringIterator.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,44 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class FlashStringIterator {
+ public:
+  explicit FlashStringIterator(const __FlashStringHelper* ptr)
+      : _ptr(reinterpret_cast<const char*>(ptr)) {}
+
+  explicit FlashStringIterator(const char* ptr) : _ptr(ptr) {}
+
+  FlashStringIterator operator+(ptrdiff_t d) const {
+    return FlashStringIterator(_ptr + d);
+  }
+
+  ptrdiff_t operator-(FlashStringIterator other) const {
+    return _ptr - other._ptr;
+  }
+
+  FlashStringIterator operator++(int) {
+    return FlashStringIterator(_ptr++);
+  }
+
+  FlashStringIterator operator++() {
+    return FlashStringIterator(++_ptr);
+  }
+
+  bool operator!=(FlashStringIterator other) const {
+    return _ptr != other._ptr;
+  }
+
+  char operator*() const {
+    return char(pgm_read_byte(_ptr));
+  }
+
+ private:
+  const char* _ptr;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/IsString.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,18 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+template <typename>
+struct IsString : false_type {};
+
+template <typename T>
+struct IsString<const T> : IsString<T> {};
+
+template <typename T>
+struct IsString<T&> : IsString<T> {};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/IsWriteableString.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,37 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+#include <Arduino.h>
+#endif
+
+#if ARDUINOJSON_ENABLE_STD_STRING
+#include <string>
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename>
+struct IsWriteableString : false_type {};
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+
+template <>
+struct IsWriteableString< ::String> : true_type {};
+
+#endif
+
+#if ARDUINOJSON_ENABLE_STD_STRING
+
+template <typename TCharTraits, typename TAllocator>
+struct IsWriteableString<std::basic_string<char, TCharTraits, TAllocator> >
+    : true_type {};
+
+#endif
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/RamStringAdapter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,43 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class RamStringAdapter : public ConstRamStringAdapter {
+ public:
+  RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
+
+  void copyTo(char* p, size_t n) const {
+    memcpy(p, _str, n);
+  }
+
+  typedef ARDUINOJSON_NAMESPACE::storage_policies::store_by_copy storage_policy;
+};
+
+template <typename TChar>
+inline RamStringAdapter adaptString(const TChar* str) {
+  return RamStringAdapter(reinterpret_cast<const char*>(str));
+}
+
+inline RamStringAdapter adaptString(char* str) {
+  return RamStringAdapter(str);
+}
+
+template <typename TChar>
+struct IsString<TChar*> {
+  static const bool value = sizeof(TChar) == 1;
+};
+
+template <>
+struct IsString<void*> {
+  static const bool value = false;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/SizedFlashStringAdapter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,60 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Strings/FlashStringIterator.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class SizedFlashStringAdapter {
+ public:
+  SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz)
+      : _str(str), _size(sz) {}
+
+  int compare(const char* other) const {
+    if (!other && !_str)
+      return 0;
+    if (!_str)
+      return -1;
+    if (!other)
+      return 1;
+    return -strncmp_P(other, reinterpret_cast<const char*>(_str), _size);
+  }
+
+  bool equals(const char* expected) const {
+    return compare(expected) == 0;
+  }
+
+  bool isNull() const {
+    return !_str;
+  }
+
+  void copyTo(char* p, size_t n) const {
+    memcpy_P(p, reinterpret_cast<const char*>(_str), n);
+  }
+
+  size_t size() const {
+    return _size;
+  }
+
+  FlashStringIterator begin() const {
+    return FlashStringIterator(_str);
+  }
+
+  typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+  const __FlashStringHelper* _str;
+  size_t _size;
+};
+
+inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str,
+                                           size_t sz) {
+  return SizedFlashStringAdapter(str, sz);
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/SizedRamStringAdapter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,55 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+#include <string.h>  // strcmp
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class SizedRamStringAdapter {
+ public:
+  SizedRamStringAdapter(const char* str, size_t n) : _str(str), _size(n) {}
+
+  int compare(const char* other) const {
+    return safe_strncmp(_str, other, _size);
+  }
+
+  bool equals(const char* expected) const {
+    return compare(expected) == 0;
+  }
+
+  bool isNull() const {
+    return !_str;
+  }
+
+  void copyTo(char* p, size_t n) const {
+    memcpy(p, _str, n);
+  }
+
+  size_t size() const {
+    return _size;
+  }
+
+  const char* begin() const {
+    return _str;
+  }
+
+  typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+  const char* _str;
+  size_t _size;
+};
+
+template <typename TChar>
+inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) {
+  return SizedRamStringAdapter(reinterpret_cast<const char*>(str), size);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/StdStringAdapter.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,65 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+#include <string>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TString>
+class StdStringAdapter {
+ public:
+  StdStringAdapter(const TString& str) : _str(&str) {}
+
+  void copyTo(char* p, size_t n) const {
+    memcpy(p, _str->c_str(), n);
+  }
+
+  bool isNull() const {
+    return false;
+  }
+
+  int compare(const char* other) const {
+    if (!other)
+      return 1;
+    return _str->compare(other);
+  }
+
+  bool equals(const char* expected) const {
+    if (!expected)
+      return false;
+    return *_str == expected;
+  }
+
+  size_t size() const {
+    return _str->size();
+  }
+
+  const char* begin() const {
+    return _str->c_str();
+  }
+
+  typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+  const TString* _str;
+};
+
+template <typename TCharTraits, typename TAllocator>
+struct IsString<std::basic_string<char, TCharTraits, TAllocator> > : true_type {
+};
+
+template <typename TCharTraits, typename TAllocator>
+inline StdStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >
+adaptString(const std::basic_string<char, TCharTraits, TAllocator>& str) {
+  return StdStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >(
+      str);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/StoragePolicy.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,15 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+namespace storage_policies {
+struct store_by_address {};
+struct store_by_copy {};
+struct decide_at_runtime {};
+}  // namespace storage_policies
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/String.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,77 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class String {
+ public:
+  String() : _data(0), _isStatic(true) {}
+  String(const char* data, bool isStaticData = true)
+      : _data(data), _isStatic(isStaticData) {}
+
+  const char* c_str() const {
+    return _data;
+  }
+
+  bool isNull() const {
+    return !_data;
+  }
+
+  bool isStatic() const {
+    return _isStatic;
+  }
+
+  friend bool operator==(String lhs, String rhs) {
+    if (lhs._data == rhs._data)
+      return true;
+    if (!lhs._data)
+      return false;
+    if (!rhs._data)
+      return false;
+    return strcmp(lhs._data, rhs._data) == 0;
+  }
+
+  friend bool operator!=(String lhs, String rhs) {
+    if (lhs._data == rhs._data)
+      return false;
+    if (!lhs._data)
+      return true;
+    if (!rhs._data)
+      return true;
+    return strcmp(lhs._data, rhs._data) != 0;
+  }
+
+ private:
+  const char* _data;
+  bool _isStatic;
+};
+
+class StringAdapter : public RamStringAdapter {
+ public:
+  StringAdapter(const String& str)
+      : RamStringAdapter(str.c_str()), _isStatic(str.isStatic()) {}
+
+  bool isStatic() const {
+    return _isStatic;
+  }
+
+  typedef storage_policies::decide_at_runtime storage_policy;
+
+ private:
+  bool _isStatic;
+};
+
+template <>
+struct IsString<String> : true_type {};
+
+inline StringAdapter adaptString(const String& str) {
+  return StringAdapter(str);
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Strings/StringAdapters.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,22 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
+#include <ArduinoJson/Strings/RamStringAdapter.hpp>
+#include <ArduinoJson/Strings/SizedRamStringAdapter.hpp>
+
+#if ARDUINOJSON_ENABLE_STD_STRING
+#include <ArduinoJson/Strings/StdStringAdapter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+#include <ArduinoJson/Strings/ArduinoStringAdapter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_PROGMEM
+#include <ArduinoJson/Strings/FlashStringAdapter.hpp>
+#include <ArduinoJson/Strings/SizedFlashStringAdapter.hpp>
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/SlotFunctions.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,60 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TAdaptedString>
+inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
+  if (!var)
+    return false;
+  return slotSetKey(var, key, pool, typename TAdaptedString::storage_policy());
+}
+
+template <typename TAdaptedString>
+inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
+                       storage_policies::decide_at_runtime) {
+  if (key.isStatic()) {
+    return slotSetKey(var, key, pool, storage_policies::store_by_address());
+  } else {
+    return slotSetKey(var, key, pool, storage_policies::store_by_copy());
+  }
+}
+
+template <typename TAdaptedString>
+inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
+                       storage_policies::store_by_address) {
+  ARDUINOJSON_ASSERT(var);
+  var->setKey(key.data(), storage_policies::store_by_address());
+  return true;
+}
+
+template <typename TAdaptedString>
+inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
+                       storage_policies::store_by_copy) {
+  const char* dup = pool->saveString(key);
+  if (!dup)
+    return false;
+  ARDUINOJSON_ASSERT(var);
+  var->setKey(dup, storage_policies::store_by_copy());
+  return true;
+}
+
+inline size_t slotSize(const VariantSlot* var) {
+  size_t n = 0;
+  while (var) {
+    n++;
+    var = var->next();
+  }
+  return n;
+}
+
+inline VariantData* slotData(VariantSlot* slot) {
+  return reinterpret_cast<VariantData*>(slot);
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantAs.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,113 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/IsWriteableString.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class ArrayRef;
+class ArrayConstRef;
+class ObjectRef;
+class ObjectConstRef;
+class VariantRef;
+class VariantConstRef;
+
+// A metafunction that returns the type of the value returned by
+// VariantRef::as<T>()
+template <typename T>
+struct VariantAs {
+  typedef T type;
+};
+
+template <>
+struct VariantAs<char*> {
+  typedef const char* type;
+};
+
+// A metafunction that returns the type of the value returned by
+// VariantRef::as<T>()
+template <typename T>
+struct VariantConstAs {
+  typedef typename VariantAs<T>::type type;
+};
+
+template <>
+struct VariantConstAs<VariantRef> {
+  typedef VariantConstRef type;
+};
+
+template <>
+struct VariantConstAs<ObjectRef> {
+  typedef ObjectConstRef type;
+};
+
+template <>
+struct VariantConstAs<ArrayRef> {
+  typedef ArrayConstRef type;
+};
+
+// ---
+
+template <typename T>
+inline typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
+                          T>::type
+variantAs(const VariantData* data) {
+  ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
+  return data != 0 ? data->asIntegral<T>() : T(0);
+}
+
+template <typename T>
+inline typename enable_if<is_enum<T>::value, T>::type variantAs(
+    const VariantData* data) {
+  return data != 0 ? static_cast<T>(data->asIntegral<int>()) : T();
+}
+
+template <typename T>
+inline typename enable_if<is_same<T, bool>::value, T>::type variantAs(
+    const VariantData* data) {
+  return data != 0 ? data->asBoolean() : false;
+}
+
+template <typename T>
+inline typename enable_if<is_floating_point<T>::value, T>::type variantAs(
+    const VariantData* data) {
+  return data != 0 ? data->asFloat<T>() : T(0);
+}
+
+template <typename T>
+inline typename enable_if<is_same<T, const char*>::value ||
+                              is_same<T, char*>::value,
+                          const char*>::type
+variantAs(const VariantData* data) {
+  return data != 0 ? data->asString() : 0;
+}
+
+template <typename T>
+T variantAs(VariantData* data, MemoryPool*) {
+  // By default use the read-only conversion.
+  // There are specializations for
+  // - ArrayRef
+  return variantAs<T>(data);
+}
+
+template <typename T>
+inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs(
+    const VariantData* data);
+
+template <typename T>
+inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs(
+    const VariantData* data);
+
+template <typename T>
+inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
+variantAs(const VariantData* data);
+
+template <typename T>
+inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
+    const VariantData* data);
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantAsImpl.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,57 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/IsWriteableString.hpp>
+#include <ArduinoJson/Variant/VariantFunctions.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs(
+    const VariantData* _data) {
+  return ArrayConstRef(variantAsArray(_data));
+}
+
+template <typename T>
+inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs(
+    const VariantData* _data) {
+  return ObjectConstRef(variantAsObject(_data));
+}
+
+template <typename T>
+inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
+variantAs(const VariantData* _data) {
+  return VariantConstRef(_data);
+}
+
+template <typename T>
+inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
+    const VariantData* _data) {
+  const char* cstr = _data != 0 ? _data->asString() : 0;
+  if (cstr)
+    return T(cstr);
+  T s;
+  serializeJson(VariantConstRef(_data), s);
+  return s;
+}
+
+template <>
+inline ArrayRef variantAs<ArrayRef>(VariantData* data, MemoryPool* pool) {
+  return ArrayRef(pool, data != 0 ? data->asArray() : 0);
+}
+
+template <>
+inline ObjectRef variantAs<ObjectRef>(VariantData* data, MemoryPool* pool) {
+  return ObjectRef(pool, data != 0 ? data->asObject() : 0);
+}
+
+template <>
+inline VariantRef variantAs<VariantRef>(VariantData* data, MemoryPool* pool) {
+  return VariantRef(pool, data);
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantCompare.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,257 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Misc/Visitable.hpp>
+#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class CollectionData;
+
+struct ComparerBase : Visitor<CompareResult> {
+  CompareResult visitArray(const CollectionData &) {
+    return COMPARE_RESULT_DIFFER;
+  }
+  CompareResult visitBoolean(bool) {
+    return COMPARE_RESULT_DIFFER;
+  }
+  CompareResult visitFloat(Float) {
+    return COMPARE_RESULT_DIFFER;
+  }
+  CompareResult visitNegativeInteger(UInt) {
+    return COMPARE_RESULT_DIFFER;
+  }
+  CompareResult visitNull() {
+    return COMPARE_RESULT_DIFFER;
+  }
+  CompareResult visitObject(const CollectionData &) {
+    return COMPARE_RESULT_DIFFER;
+  }
+  CompareResult visitPositiveInteger(UInt) {
+    return COMPARE_RESULT_DIFFER;
+  }
+  CompareResult visitRawJson(const char *, size_t) {
+    return COMPARE_RESULT_DIFFER;
+  }
+  CompareResult visitString(const char *) {
+    return COMPARE_RESULT_DIFFER;
+  }
+};
+
+template <typename T, typename Enable = void>
+struct Comparer;
+
+template <typename T>
+struct Comparer<T, typename enable_if<IsString<T>::value>::type>
+    : ComparerBase {
+  T rhs;
+
+  explicit Comparer(T value) : rhs(value) {}
+
+  CompareResult visitString(const char *lhs) {
+    int i = adaptString(rhs).compare(lhs);
+    if (i < 0)
+      return COMPARE_RESULT_GREATER;
+    else if (i > 0)
+      return COMPARE_RESULT_LESS;
+    else
+      return COMPARE_RESULT_EQUAL;
+  }
+
+  CompareResult visitNull() {
+    if (adaptString(rhs).isNull())
+      return COMPARE_RESULT_EQUAL;
+    else
+      return COMPARE_RESULT_DIFFER;
+  }
+};
+
+template <typename T>
+struct Comparer<T, typename enable_if<is_integral<T>::value ||
+                                      is_floating_point<T>::value>::type>
+    : ComparerBase {
+  T rhs;
+
+  explicit Comparer(T value) : rhs(value) {}
+
+  CompareResult visitFloat(Float lhs) {
+    return arithmeticCompare(lhs, rhs);
+  }
+
+  CompareResult visitNegativeInteger(UInt lhs) {
+    return arithmeticCompareNegateLeft(lhs, rhs);
+  }
+
+  CompareResult visitPositiveInteger(UInt lhs) {
+    return arithmeticCompare(lhs, rhs);
+  }
+
+  CompareResult visitBoolean(bool lhs) {
+    return visitPositiveInteger(static_cast<UInt>(lhs));
+  }
+};
+
+struct NullComparer : ComparerBase {
+  CompareResult visitNull() {
+    return COMPARE_RESULT_EQUAL;
+  }
+};
+
+#if ARDUINOJSON_HAS_NULLPTR
+template <>
+struct Comparer<decltype(nullptr), void> : NullComparer {
+  explicit Comparer(decltype(nullptr)) : NullComparer() {}
+};
+#endif
+
+struct ArrayComparer : ComparerBase {
+  const CollectionData *_rhs;
+
+  explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
+
+  CompareResult visitArray(const CollectionData &lhs) {
+    if (lhs.equalsArray(*_rhs))
+      return COMPARE_RESULT_EQUAL;
+    else
+      return COMPARE_RESULT_DIFFER;
+  }
+};
+
+struct NegativeIntegerComparer : ComparerBase {
+  UInt _rhs;
+
+  explicit NegativeIntegerComparer(UInt rhs) : _rhs(rhs) {}
+
+  CompareResult visitFloat(Float lhs) {
+    return arithmeticCompareNegateRight(lhs, _rhs);
+  }
+
+  CompareResult visitNegativeInteger(UInt lhs) {
+    return arithmeticCompare(_rhs, lhs);
+  }
+
+  CompareResult visitPositiveInteger(UInt) {
+    return COMPARE_RESULT_GREATER;
+  }
+
+  CompareResult visitBoolean(bool) {
+    return COMPARE_RESULT_GREATER;
+  }
+};
+
+struct ObjectComparer : ComparerBase {
+  const CollectionData *_rhs;
+
+  explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
+
+  CompareResult visitObject(const CollectionData &lhs) {
+    if (lhs.equalsObject(*_rhs))
+      return COMPARE_RESULT_EQUAL;
+    else
+      return COMPARE_RESULT_DIFFER;
+  }
+};
+
+struct RawComparer : ComparerBase {
+  const char *_rhsData;
+  size_t _rhsSize;
+
+  explicit RawComparer(const char *rhsData, size_t rhsSize)
+      : _rhsData(rhsData), _rhsSize(rhsSize) {}
+
+  CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
+    size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
+    int n = memcmp(lhsData, _rhsData, size);
+    if (n < 0)
+      return COMPARE_RESULT_LESS;
+    else if (n > 0)
+      return COMPARE_RESULT_GREATER;
+    else
+      return COMPARE_RESULT_EQUAL;
+  }
+};
+
+template <typename T>
+struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
+    : ComparerBase {
+  T rhs;
+
+  explicit Comparer(T value) : rhs(value) {}
+
+  CompareResult visitArray(const CollectionData &lhs) {
+    ArrayComparer comparer(lhs);
+    return accept(comparer);
+  }
+
+  CompareResult visitObject(const CollectionData &lhs) {
+    ObjectComparer comparer(lhs);
+    return accept(comparer);
+  }
+
+  CompareResult visitFloat(Float lhs) {
+    Comparer<Float> comparer(lhs);
+    return accept(comparer);
+  }
+
+  CompareResult visitString(const char *lhs) {
+    Comparer<const char *> comparer(lhs);
+    return accept(comparer);
+  }
+
+  CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
+    RawComparer comparer(lhsData, lhsSize);
+    return accept(comparer);
+  }
+
+  CompareResult visitNegativeInteger(UInt lhs) {
+    NegativeIntegerComparer comparer(lhs);
+    return accept(comparer);
+  }
+
+  CompareResult visitPositiveInteger(UInt lhs) {
+    Comparer<UInt> comparer(lhs);
+    return accept(comparer);
+  }
+
+  CompareResult visitBoolean(bool lhs) {
+    Comparer<bool> comparer(lhs);
+    return accept(comparer);
+  }
+
+  CompareResult visitNull() {
+    NullComparer comparer;
+    return accept(comparer);
+  }
+
+ private:
+  template <typename TComparer>
+  CompareResult accept(TComparer &comparer) {
+    CompareResult reversedResult = rhs.accept(comparer);
+    switch (reversedResult) {
+      case COMPARE_RESULT_GREATER:
+        return COMPARE_RESULT_LESS;
+      case COMPARE_RESULT_LESS:
+        return COMPARE_RESULT_GREATER;
+      default:
+        return reversedResult;
+    }
+  }
+};
+
+template <typename T1, typename T2>
+CompareResult compare(const T1 &lhs, const T2 &rhs) {
+  Comparer<T2> comparer(rhs);
+  return lhs.accept(comparer);
+}
+
+inline int variantCompare(const VariantData *a, const VariantData *b) {
+  return compare(VariantConstRef(a), VariantConstRef(b));
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantContent.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,54 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stddef.h>  // size_t
+
+#include <ArduinoJson/Collection/CollectionData.hpp>
+#include <ArduinoJson/Numbers/Float.hpp>
+#include <ArduinoJson/Numbers/Integer.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+//
+enum {
+  VALUE_MASK = 0x7F,
+
+  VALUE_IS_OWNED = 0x01,
+  VALUE_IS_NULL = 0,
+  VALUE_IS_LINKED_RAW = 0x02,
+  VALUE_IS_OWNED_RAW = 0x03,
+  VALUE_IS_LINKED_STRING = 0x04,
+  VALUE_IS_OWNED_STRING = 0x05,
+
+  // CAUTION: no VALUE_IS_OWNED below
+  VALUE_IS_BOOLEAN = 0x06,
+  VALUE_IS_POSITIVE_INTEGER = 0x08,
+  VALUE_IS_NEGATIVE_INTEGER = 0x0A,
+  VALUE_IS_FLOAT = 0x0C,
+
+  COLLECTION_MASK = 0x60,
+  VALUE_IS_OBJECT = 0x20,
+  VALUE_IS_ARRAY = 0x40,
+
+  KEY_IS_OWNED = 0x80
+};
+
+struct RawData {
+  const char *data;
+  size_t size;
+};
+
+union VariantContent {
+  Float asFloat;
+  UInt asInteger;
+  CollectionData asCollection;
+  const char *asString;
+  struct {
+    const char *data;
+    size_t size;
+  } asRaw;
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantData.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,389 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/Misc/SerializedValue.hpp>
+#include <ArduinoJson/Numbers/convertNumber.hpp>
+#include <ArduinoJson/Strings/RamStringAdapter.hpp>
+#include <ArduinoJson/Variant/VariantContent.hpp>
+
+// VariantData can't have a constructor (to be a POD), so we have no way to fix
+// this warning
+#if defined(__GNUC__)
+#if __GNUC__ >= 7
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class VariantData {
+  VariantContent _content;  // must be first to allow cast from array to variant
+  uint8_t _flags;
+
+ public:
+  // Must be a POD!
+  // - no constructor
+  // - no destructor
+  // - no virtual
+  // - no inheritance
+  void init() {
+    _flags = 0;
+  }
+
+  template <typename TVisitor>
+  typename TVisitor::result_type accept(TVisitor &visitor) const {
+    switch (type()) {
+      case VALUE_IS_FLOAT:
+        return visitor.visitFloat(_content.asFloat);
+
+      case VALUE_IS_ARRAY:
+        return visitor.visitArray(_content.asCollection);
+
+      case VALUE_IS_OBJECT:
+        return visitor.visitObject(_content.asCollection);
+
+      case VALUE_IS_LINKED_STRING:
+      case VALUE_IS_OWNED_STRING:
+        return visitor.visitString(_content.asString);
+
+      case VALUE_IS_OWNED_RAW:
+      case VALUE_IS_LINKED_RAW:
+        return visitor.visitRawJson(_content.asRaw.data, _content.asRaw.size);
+
+      case VALUE_IS_NEGATIVE_INTEGER:
+        return visitor.visitNegativeInteger(_content.asInteger);
+
+      case VALUE_IS_POSITIVE_INTEGER:
+        return visitor.visitPositiveInteger(_content.asInteger);
+
+      case VALUE_IS_BOOLEAN:
+        return visitor.visitBoolean(_content.asInteger != 0);
+
+      default:
+        return visitor.visitNull();
+    }
+  }
+
+  template <typename T>
+  T asIntegral() const;
+
+  template <typename T>
+  T asFloat() const;
+
+  const char *asString() const;
+
+  bool asBoolean() const;
+
+  CollectionData *asArray() {
+    return isArray() ? &_content.asCollection : 0;
+  }
+
+  const CollectionData *asArray() const {
+    return const_cast<VariantData *>(this)->asArray();
+  }
+
+  CollectionData *asObject() {
+    return isObject() ? &_content.asCollection : 0;
+  }
+
+  const CollectionData *asObject() const {
+    return const_cast<VariantData *>(this)->asObject();
+  }
+
+  bool copyFrom(const VariantData &src, MemoryPool *pool) {
+    switch (src.type()) {
+      case VALUE_IS_ARRAY:
+        return toArray().copyFrom(src._content.asCollection, pool);
+      case VALUE_IS_OBJECT:
+        return toObject().copyFrom(src._content.asCollection, pool);
+      case VALUE_IS_OWNED_STRING:
+        return setString(RamStringAdapter(src._content.asString), pool);
+      case VALUE_IS_OWNED_RAW:
+        return setOwnedRaw(
+            serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
+      default:
+        setType(src.type());
+        _content = src._content;
+        return true;
+    }
+  }
+
+  bool isArray() const {
+    return (_flags & VALUE_IS_ARRAY) != 0;
+  }
+
+  bool isBoolean() const {
+    return type() == VALUE_IS_BOOLEAN;
+  }
+
+  bool isCollection() const {
+    return (_flags & COLLECTION_MASK) != 0;
+  }
+
+  template <typename T>
+  bool isInteger() const {
+    switch (type()) {
+      case VALUE_IS_POSITIVE_INTEGER:
+        return canStorePositiveInteger<T>(_content.asInteger);
+
+      case VALUE_IS_NEGATIVE_INTEGER:
+        return canStoreNegativeInteger<T>(_content.asInteger);
+
+      default:
+        return false;
+    }
+  }
+
+  bool isFloat() const {
+    return type() == VALUE_IS_FLOAT || type() == VALUE_IS_POSITIVE_INTEGER ||
+           type() == VALUE_IS_NEGATIVE_INTEGER;
+  }
+
+  bool isString() const {
+    return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
+  }
+
+  bool isObject() const {
+    return (_flags & VALUE_IS_OBJECT) != 0;
+  }
+
+  bool isNull() const {
+    return type() == VALUE_IS_NULL;
+  }
+
+  bool isEnclosed() const {
+    return !isFloat();
+  }
+
+  void remove(size_t index) {
+    if (isArray())
+      _content.asCollection.removeElement(index);
+  }
+
+  template <typename TAdaptedString>
+  void remove(TAdaptedString key) {
+    if (isObject())
+      _content.asCollection.removeMember(key);
+  }
+
+  void setBoolean(bool value) {
+    setType(VALUE_IS_BOOLEAN);
+    _content.asInteger = static_cast<UInt>(value);
+  }
+
+  void setFloat(Float value) {
+    setType(VALUE_IS_FLOAT);
+    _content.asFloat = value;
+  }
+
+  void setLinkedRaw(SerializedValue<const char *> value) {
+    if (value.data()) {
+      setType(VALUE_IS_LINKED_RAW);
+      _content.asRaw.data = value.data();
+      _content.asRaw.size = value.size();
+    } else {
+      setType(VALUE_IS_NULL);
+    }
+  }
+
+  template <typename T>
+  bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
+    const char *dup = pool->saveString(adaptString(value.data(), value.size()));
+    if (dup) {
+      setType(VALUE_IS_OWNED_RAW);
+      _content.asRaw.data = dup;
+      _content.asRaw.size = value.size();
+      return true;
+    } else {
+      setType(VALUE_IS_NULL);
+      return false;
+    }
+  }
+
+  template <typename T>
+  typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
+    setUnsignedInteger(value);
+  }
+
+  template <typename T>
+  typename enable_if<is_signed<T>::value>::type setInteger(T value) {
+    setSignedInteger(value);
+  }
+
+  template <typename T>
+  void setSignedInteger(T value) {
+    if (value >= 0) {
+      setPositiveInteger(static_cast<UInt>(value));
+    } else {
+      setNegativeInteger(~static_cast<UInt>(value) + 1);
+    }
+  }
+
+  void setUnsignedInteger(UInt value) {
+    setType(VALUE_IS_POSITIVE_INTEGER);
+    _content.asInteger = static_cast<UInt>(value);
+  }
+
+  void setPositiveInteger(UInt value) {
+    setType(VALUE_IS_POSITIVE_INTEGER);
+    _content.asInteger = value;
+  }
+
+  void setNegativeInteger(UInt value) {
+    setType(VALUE_IS_NEGATIVE_INTEGER);
+    _content.asInteger = value;
+  }
+
+  void setNull() {
+    setType(VALUE_IS_NULL);
+  }
+
+  void setStringPointer(const char *s, storage_policies::store_by_copy) {
+    setType(VALUE_IS_OWNED_STRING);
+    _content.asString = s;
+  }
+
+  void setStringPointer(const char *s, storage_policies::store_by_address) {
+    setType(VALUE_IS_LINKED_STRING);
+    _content.asString = s;
+  }
+
+  template <typename TAdaptedString>
+  bool setString(TAdaptedString value, MemoryPool *pool) {
+    return setString(value, pool, typename TAdaptedString::storage_policy());
+  }
+
+  template <typename TAdaptedString>
+  inline bool setString(TAdaptedString value, MemoryPool *pool,
+                        storage_policies::decide_at_runtime) {
+    if (value.isStatic())
+      return setString(value, pool, storage_policies::store_by_address());
+    else
+      return setString(value, pool, storage_policies::store_by_copy());
+  }
+
+  template <typename TAdaptedString>
+  inline bool setString(TAdaptedString value, MemoryPool *,
+                        storage_policies::store_by_address) {
+    if (value.isNull())
+      setNull();
+    else
+      setStringPointer(value.data(), storage_policies::store_by_address());
+    return true;
+  }
+
+  template <typename TAdaptedString>
+  inline bool setString(TAdaptedString value, MemoryPool *pool,
+                        storage_policies::store_by_copy) {
+    if (value.isNull()) {
+      setNull();
+      return true;
+    }
+    const char *copy = pool->saveString(value);
+    if (!copy) {
+      setNull();
+      return false;
+    }
+    setStringPointer(copy, storage_policies::store_by_copy());
+    return true;
+  }
+
+  CollectionData &toArray() {
+    setType(VALUE_IS_ARRAY);
+    _content.asCollection.clear();
+    return _content.asCollection;
+  }
+
+  CollectionData &toObject() {
+    setType(VALUE_IS_OBJECT);
+    _content.asCollection.clear();
+    return _content.asCollection;
+  }
+
+  size_t memoryUsage() const {
+    switch (type()) {
+      case VALUE_IS_OWNED_STRING:
+        return strlen(_content.asString) + 1;
+      case VALUE_IS_OWNED_RAW:
+        return _content.asRaw.size;
+      case VALUE_IS_OBJECT:
+      case VALUE_IS_ARRAY:
+        return _content.asCollection.memoryUsage();
+      default:
+        return 0;
+    }
+  }
+
+  size_t nesting() const {
+    return isCollection() ? _content.asCollection.nesting() : 0;
+  }
+
+  size_t size() const {
+    return isCollection() ? _content.asCollection.size() : 0;
+  }
+
+  VariantData *addElement(MemoryPool *pool) {
+    if (isNull())
+      toArray();
+    if (!isArray())
+      return 0;
+    return _content.asCollection.addElement(pool);
+  }
+
+  VariantData *getElement(size_t index) const {
+    return isArray() ? _content.asCollection.getElement(index) : 0;
+  }
+
+  VariantData *getOrAddElement(size_t index, MemoryPool *pool) {
+    if (isNull())
+      toArray();
+    if (!isArray())
+      return 0;
+    return _content.asCollection.getOrAddElement(index, pool);
+  }
+
+  template <typename TAdaptedString>
+  VariantData *getMember(TAdaptedString key) const {
+    return isObject() ? _content.asCollection.getMember(key) : 0;
+  }
+
+  template <typename TAdaptedString>
+  VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) {
+    if (isNull())
+      toObject();
+    if (!isObject())
+      return 0;
+    return _content.asCollection.getOrAddMember(key, pool);
+  }
+
+  void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
+    if (_flags & VALUE_IS_OWNED)
+      _content.asString += stringDistance;
+    if (_flags & COLLECTION_MASK)
+      _content.asCollection.movePointers(stringDistance, variantDistance);
+  }
+
+  uint8_t type() const {
+    return _flags & VALUE_MASK;
+  }
+
+ private:
+  void setType(uint8_t t) {
+    _flags &= KEY_IS_OWNED;
+    _flags |= t;
+  }
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
+
+#if defined(__GNUC__)
+#if __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantFunctions.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,166 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TVisitor>
+inline typename TVisitor::result_type variantAccept(const VariantData *var,
+                                                    TVisitor &visitor) {
+  if (var != 0)
+    return var->accept(visitor);
+  else
+    return visitor.visitNull();
+}
+
+inline const CollectionData *variantAsArray(const VariantData *var) {
+  return var != 0 ? var->asArray() : 0;
+}
+
+inline const CollectionData *variantAsObject(const VariantData *var) {
+  return var != 0 ? var->asObject() : 0;
+}
+
+inline CollectionData *variantAsObject(VariantData *var) {
+  return var != 0 ? var->asObject() : 0;
+}
+
+inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
+                            MemoryPool *pool) {
+  if (!dst)
+    return false;
+  if (!src) {
+    dst->setNull();
+    return true;
+  }
+  return dst->copyFrom(*src, pool);
+}
+
+inline int variantCompare(const VariantData *a, const VariantData *b);
+
+inline bool variantIsArray(const VariantData *var) {
+  return var && var->isArray();
+}
+
+inline bool variantIsBoolean(const VariantData *var) {
+  return var && var->isBoolean();
+}
+
+template <typename T>
+inline bool variantIsInteger(const VariantData *var) {
+  return var && var->isInteger<T>();
+}
+
+inline bool variantIsFloat(const VariantData *var) {
+  return var && var->isFloat();
+}
+
+inline bool variantIsString(const VariantData *var) {
+  return var && var->isString();
+}
+
+inline bool variantIsObject(const VariantData *var) {
+  return var && var->isObject();
+}
+
+inline bool variantIsNull(const VariantData *var) {
+  return var == 0 || var->isNull();
+}
+
+inline bool variantSetBoolean(VariantData *var, bool value) {
+  if (!var)
+    return false;
+  var->setBoolean(value);
+  return true;
+}
+
+inline bool variantSetFloat(VariantData *var, Float value) {
+  if (!var)
+    return false;
+  var->setFloat(value);
+  return true;
+}
+
+inline bool variantSetLinkedRaw(VariantData *var,
+                                SerializedValue<const char *> value) {
+  if (!var)
+    return false;
+  var->setLinkedRaw(value);
+  return true;
+}
+
+template <typename T>
+inline bool variantSetOwnedRaw(VariantData *var, SerializedValue<T> value,
+                               MemoryPool *pool) {
+  return var != 0 && var->setOwnedRaw(value, pool);
+}
+
+inline void variantSetNull(VariantData *var) {
+  if (!var)
+    return;
+  var->setNull();
+}
+
+template <typename TAdaptedString>
+inline bool variantSetString(VariantData *var, TAdaptedString value,
+                             MemoryPool *pool) {
+  if (!var)
+    return false;
+  return var->setString(value, pool);
+}
+
+template <typename T>
+inline bool variantSetInteger(VariantData *var, T value) {
+  ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
+  if (!var)
+    return false;
+  var->setInteger(value);
+  return true;
+}
+
+inline size_t variantSize(const VariantData *var) {
+  return var != 0 ? var->size() : 0;
+}
+
+inline CollectionData *variantToArray(VariantData *var) {
+  if (!var)
+    return 0;
+  return &var->toArray();
+}
+
+inline CollectionData *variantToObject(VariantData *var) {
+  if (!var)
+    return 0;
+  return &var->toObject();
+}
+
+inline NO_INLINE VariantData *variantAddElement(VariantData *var,
+                                                MemoryPool *pool) {
+  return var != 0 ? var->addElement(pool) : 0;
+}
+
+inline NO_INLINE VariantData *variantGetOrAddElement(VariantData *var,
+                                                     size_t index,
+                                                     MemoryPool *pool) {
+  return var != 0 ? var->getOrAddElement(index, pool) : 0;
+}
+
+template <typename TChar>
+NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key,
+                                             MemoryPool *pool) {
+  return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
+}
+
+template <typename TString>
+NO_INLINE VariantData *variantGetOrAddMember(VariantData *var,
+                                             const TString &key,
+                                             MemoryPool *pool) {
+  return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantImpl.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,147 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayRef.hpp>
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Numbers/convertNumber.hpp>
+#include <ArduinoJson/Numbers/parseNumber.hpp>
+#include <ArduinoJson/Object/ObjectRef.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+#include <string.h>  // for strcmp
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+inline T VariantData::asIntegral() const {
+  switch (type()) {
+    case VALUE_IS_POSITIVE_INTEGER:
+    case VALUE_IS_BOOLEAN:
+      return convertPositiveInteger<T>(_content.asInteger);
+    case VALUE_IS_NEGATIVE_INTEGER:
+      return convertNegativeInteger<T>(_content.asInteger);
+    case VALUE_IS_LINKED_STRING:
+    case VALUE_IS_OWNED_STRING:
+      return parseNumber<T>(_content.asString);
+    case VALUE_IS_FLOAT:
+      return convertFloat<T>(_content.asFloat);
+    default:
+      return 0;
+  }
+}
+
+inline bool VariantData::asBoolean() const {
+  switch (type()) {
+    case VALUE_IS_POSITIVE_INTEGER:
+    case VALUE_IS_BOOLEAN:
+    case VALUE_IS_NEGATIVE_INTEGER:
+      return _content.asInteger != 0;
+    case VALUE_IS_FLOAT:
+      return _content.asFloat != 0;
+    case VALUE_IS_NULL:
+      return false;
+    default:
+      return true;
+  }
+}
+
+// T = float/double
+template <typename T>
+inline T VariantData::asFloat() const {
+  switch (type()) {
+    case VALUE_IS_POSITIVE_INTEGER:
+    case VALUE_IS_BOOLEAN:
+      return static_cast<T>(_content.asInteger);
+    case VALUE_IS_NEGATIVE_INTEGER:
+      return -static_cast<T>(_content.asInteger);
+    case VALUE_IS_LINKED_STRING:
+    case VALUE_IS_OWNED_STRING:
+      return parseNumber<T>(_content.asString);
+    case VALUE_IS_FLOAT:
+      return static_cast<T>(_content.asFloat);
+    default:
+      return 0;
+  }
+}
+
+inline const char *VariantData::asString() const {
+  switch (type()) {
+    case VALUE_IS_LINKED_STRING:
+    case VALUE_IS_OWNED_STRING:
+      return _content.asString;
+    default:
+      return 0;
+  }
+}
+
+template <typename TVariant>
+typename enable_if<IsVisitable<TVariant>::value, bool>::type VariantRef::set(
+    const TVariant &value) const {
+  VariantConstRef v = value;
+  return variantCopyFrom(_data, v._data, _pool);
+}
+
+template <typename T>
+inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type
+VariantRef::to() const {
+  return ArrayRef(_pool, variantToArray(_data));
+}
+
+template <typename T>
+typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type
+VariantRef::to() const {
+  return ObjectRef(_pool, variantToObject(_data));
+}
+
+template <typename T>
+typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type
+VariantRef::to() const {
+  variantSetNull(_data);
+  return *this;
+}
+
+inline VariantConstRef VariantConstRef::getElement(size_t index) const {
+  return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index];
+}
+
+inline VariantRef VariantRef::addElement() const {
+  return VariantRef(_pool, variantAddElement(_data, _pool));
+}
+
+inline VariantRef VariantRef::getElement(size_t index) const {
+  return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0);
+}
+
+inline VariantRef VariantRef::getOrAddElement(size_t index) const {
+  return VariantRef(_pool, variantGetOrAddElement(_data, index, _pool));
+}
+
+template <typename TChar>
+inline VariantRef VariantRef::getMember(TChar *key) const {
+  return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0);
+}
+
+template <typename TString>
+inline typename enable_if<IsString<TString>::value, VariantRef>::type
+VariantRef::getMember(const TString &key) const {
+  return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0);
+}
+
+template <typename TChar>
+inline VariantRef VariantRef::getOrAddMember(TChar *key) const {
+  return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
+}
+
+template <typename TString>
+inline VariantRef VariantRef::getOrAddMember(const TString &key) const {
+  return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
+}
+
+inline VariantConstRef operator|(VariantConstRef preferedValue,
+                                 VariantConstRef defaultValue) {
+  return preferedValue ? preferedValue : defaultValue;
+}
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantOperators.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,174 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Misc/Visitable.hpp>
+#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantAs.hpp>
+#include <ArduinoJson/Variant/VariantTag.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T1, typename T2>
+CompareResult compare(const T1 &lhs, const T2 &rhs);  // VariantCompare.cpp
+
+template <typename TVariant>
+struct VariantOperators {
+  // Returns the default value if the VariantRef is undefined or incompatible
+  //
+  // int operator|(JsonVariant, int)
+  // float operator|(JsonVariant, float)
+  // bool operator|(JsonVariant, bool)
+  // const char* operator|(JsonVariant, const char*)
+  // char* operator|(JsonVariant, const char*)
+  template <typename T>
+  friend typename enable_if<!IsVariant<T>::value,
+                            typename VariantAs<T>::type>::type
+  operator|(const TVariant &variant, T defaultValue) {
+    if (variant.template is<T>())
+      return variant.template as<T>();
+    else
+      return defaultValue;
+  }
+  //
+  // JsonVariant operator|(JsonVariant, JsonVariant)
+  template <typename T>
+  friend typename enable_if<IsVariant<T>::value, typename T::variant_type>::type
+  operator|(const TVariant &variant, T defaultValue) {
+    if (variant)
+      return variant;
+    else
+      return defaultValue;
+  }
+
+  // value == TVariant
+  template <typename T>
+  friend bool operator==(T *lhs, TVariant rhs) {
+    return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
+  }
+  template <typename T>
+  friend bool operator==(const T &lhs, TVariant rhs) {
+    return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
+  }
+
+  // TVariant == value
+  template <typename T>
+  friend bool operator==(TVariant lhs, T *rhs) {
+    return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
+  }
+  template <typename T>
+  friend typename enable_if<!IsVisitable<T>::value, bool>::type operator==(
+      TVariant lhs, const T &rhs) {
+    return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
+  }
+
+  // value != TVariant
+  template <typename T>
+  friend bool operator!=(T *lhs, TVariant rhs) {
+    return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
+  }
+  template <typename T>
+  friend bool operator!=(const T &lhs, TVariant rhs) {
+    return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
+  }
+
+  // TVariant != value
+  template <typename T>
+  friend bool operator!=(TVariant lhs, T *rhs) {
+    return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
+  }
+  template <typename T>
+  friend typename enable_if<!IsVisitable<T>::value, bool>::type operator!=(
+      TVariant lhs, const T &rhs) {
+    return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
+  }
+
+  // value < TVariant
+  template <typename T>
+  friend bool operator<(T *lhs, TVariant rhs) {
+    return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
+  }
+  template <typename T>
+  friend bool operator<(const T &lhs, TVariant rhs) {
+    return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
+  }
+
+  // TVariant < value
+  template <typename T>
+  friend bool operator<(TVariant lhs, T *rhs) {
+    return compare(lhs, rhs) == COMPARE_RESULT_LESS;
+  }
+  template <typename T>
+  friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<(
+      TVariant lhs, const T &rhs) {
+    return compare(lhs, rhs) == COMPARE_RESULT_LESS;
+  }
+
+  // value <= TVariant
+  template <typename T>
+  friend bool operator<=(T *lhs, TVariant rhs) {
+    return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
+  }
+  template <typename T>
+  friend bool operator<=(const T &lhs, TVariant rhs) {
+    return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
+  }
+
+  // TVariant <= value
+  template <typename T>
+  friend bool operator<=(TVariant lhs, T *rhs) {
+    return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
+  }
+  template <typename T>
+  friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<=(
+      TVariant lhs, const T &rhs) {
+    return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
+  }
+
+  // value > TVariant
+  template <typename T>
+  friend bool operator>(T *lhs, TVariant rhs) {
+    return compare(rhs, lhs) == COMPARE_RESULT_LESS;
+  }
+  template <typename T>
+  friend bool operator>(const T &lhs, TVariant rhs) {
+    return compare(rhs, lhs) == COMPARE_RESULT_LESS;
+  }
+
+  // TVariant > value
+  template <typename T>
+  friend bool operator>(TVariant lhs, T *rhs) {
+    return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
+  }
+  template <typename T>
+  friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>(
+      TVariant lhs, const T &rhs) {
+    return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
+  }
+
+  // value >= TVariant
+  template <typename T>
+  friend bool operator>=(T *lhs, TVariant rhs) {
+    return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
+  }
+  template <typename T>
+  friend bool operator>=(const T &lhs, TVariant rhs) {
+    return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
+  }
+
+  // TVariant >= value
+  template <typename T>
+  friend bool operator>=(TVariant lhs, T *rhs) {
+    return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
+  }
+  template <typename T>
+  friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>=(
+      TVariant lhs, const T &rhs) {
+    return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
+  }
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantRef.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,405 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>  // for uint8_t
+
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/Misc/Visitable.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Strings/StringAdapters.hpp>
+#include <ArduinoJson/Variant/VariantAs.hpp>
+#include <ArduinoJson/Variant/VariantFunctions.hpp>
+#include <ArduinoJson/Variant/VariantOperators.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+#include <ArduinoJson/Variant/VariantShortcuts.hpp>
+#include <ArduinoJson/Variant/VariantTag.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Forward declarations.
+class ArrayRef;
+class ObjectRef;
+
+// Contains the methods shared by VariantRef and VariantConstRef
+template <typename TData>
+class VariantRefBase : public VariantTag {
+ public:
+  // Tells wether the variant has the specified type.
+  // Returns true if the variant has type type T, false otherwise.
+  //
+  // bool is<char>() const;
+  // bool is<signed char>() const;
+  // bool is<signed short>() const;
+  // bool is<signed int>() const;
+  // bool is<signed long>() const;
+  // bool is<unsigned char>() const;
+  // bool is<unsigned short>() const;
+  // bool is<unsigned int>() const;
+  // bool is<unsigned long>() const;
+  template <typename T>
+  FORCE_INLINE
+      typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
+                         bool>::type
+      is() const {
+    return variantIsInteger<T>(_data);
+  }
+  //
+  // bool is<double>() const;
+  // bool is<float>() const;
+  template <typename T>
+  FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
+      const {
+    return variantIsFloat(_data);
+  }
+  //
+  // bool is<bool>() const
+  template <typename T>
+  FORCE_INLINE typename enable_if<is_same<T, bool>::value, bool>::type is()
+      const {
+    return variantIsBoolean(_data);
+  }
+  //
+  // bool is<const char*>() const;
+  // bool is<char*>() const;
+  // bool is<std::string>() const;
+  // bool is<String>() const;
+  template <typename T>
+  FORCE_INLINE typename enable_if<is_same<T, const char *>::value ||
+                                      is_same<T, char *>::value ||
+                                      IsWriteableString<T>::value,
+                                  bool>::type
+  is() const {
+    return variantIsString(_data);
+  }
+  //
+  // bool is<ArrayRef> const;
+  // bool is<const ArrayRef> const;
+  template <typename T>
+  FORCE_INLINE typename enable_if<
+      is_same<typename remove_const<T>::type, ArrayRef>::value, bool>::type
+  is() const {
+    return variantIsArray(_data);
+  }
+  //
+  // bool is<ObjectRef> const;
+  // bool is<const ObjectRef> const;
+  template <typename T>
+  FORCE_INLINE typename enable_if<
+      is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type
+  is() const {
+    return variantIsObject(_data);
+  }
+#if ARDUINOJSON_HAS_NULLPTR
+  //
+  // bool is<nullptr_t> const;
+  template <typename T>
+  FORCE_INLINE
+      typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type
+      is() const {
+    return variantIsNull(_data);
+  }
+#endif
+  // bool is<enum>() const;
+  template <typename T>
+  FORCE_INLINE typename enable_if<is_enum<T>::value, bool>::type is() const {
+    return variantIsInteger<int>(_data);
+  }
+
+  FORCE_INLINE bool isNull() const {
+    return variantIsNull(_data);
+  }
+
+  FORCE_INLINE bool isUndefined() const {
+    return !_data;
+  }
+
+  FORCE_INLINE size_t memoryUsage() const {
+    return _data ? _data->memoryUsage() : 0;
+  }
+
+  FORCE_INLINE size_t nesting() const {
+    return _data ? _data->nesting() : 0;
+  }
+
+  size_t size() const {
+    return variantSize(_data);
+  }
+
+ protected:
+  VariantRefBase(TData *data) : _data(data) {}
+  TData *_data;
+};
+
+// A variant that can be a any value serializable to a JSON value.
+//
+// It can be set to:
+// - a boolean
+// - a char, short, int or a long (signed or unsigned)
+// - a string (const char*)
+// - a reference to a ArrayRef or ObjectRef
+class VariantRef : public VariantRefBase<VariantData>,
+                   public VariantOperators<VariantRef>,
+                   public VariantShortcuts<VariantRef>,
+                   public Visitable {
+  typedef VariantRefBase<VariantData> base_type;
+  friend class VariantConstRef;
+
+ public:
+  // Intenal use only
+  FORCE_INLINE VariantRef(MemoryPool *pool, VariantData *data)
+      : base_type(data), _pool(pool) {}
+
+  // Creates an uninitialized VariantRef
+  FORCE_INLINE VariantRef() : base_type(0), _pool(0) {}
+
+  FORCE_INLINE void clear() const {
+    return variantSetNull(_data);
+  }
+
+  // set(bool value)
+  template <typename T>
+  FORCE_INLINE bool set(
+      T value, typename enable_if<is_same<T, bool>::value>::type * = 0) const {
+    return variantSetBoolean(_data, value);
+  }
+
+  // set(double value);
+  // set(float value);
+  template <typename T>
+  FORCE_INLINE bool set(
+      T value,
+      typename enable_if<is_floating_point<T>::value>::type * = 0) const {
+    return variantSetFloat(_data, static_cast<Float>(value));
+  }
+
+  // set(char)
+  // set(signed short)
+  // set(signed int)
+  // set(signed long)
+  // set(signed char)
+  // set(unsigned short)
+  // set(unsigned int)
+  // set(unsigned long)
+  template <typename T>
+  FORCE_INLINE bool set(
+      T value, typename enable_if<is_integral<T>::value &&
+                                  !is_same<bool, T>::value>::type * = 0) const {
+    return variantSetInteger<T>(_data, value);
+  }
+
+  // set(SerializedValue<const char *>)
+  FORCE_INLINE bool set(SerializedValue<const char *> value) const {
+    return variantSetLinkedRaw(_data, value);
+  }
+
+  // set(SerializedValue<std::string>)
+  // set(SerializedValue<String>)
+  // set(SerializedValue<const __FlashStringHelper*>)
+  template <typename T>
+  FORCE_INLINE bool set(
+      SerializedValue<T> value,
+      typename enable_if<!is_same<const char *, T>::value>::type * = 0) const {
+    return variantSetOwnedRaw(_data, value, _pool);
+  }
+
+  // set(const std::string&)
+  // set(const String&)
+  template <typename T>
+  FORCE_INLINE bool set(
+      const T &value,
+      typename enable_if<IsString<T>::value>::type * = 0) const {
+    return variantSetString(_data, adaptString(value), _pool);
+  }
+  // set(char*)
+  // set(const __FlashStringHelper*)
+  // set(const char*)
+  template <typename T>
+  FORCE_INLINE bool set(
+      T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
+    return variantSetString(_data, adaptString(value), _pool);
+  }
+
+  // set(VariantRef)
+  // set(VariantConstRef)
+  // set(ArrayRef)
+  // set(ArrayConstRef)
+  // set(ObjectRef)
+  // set(ObjecConstRef)
+  // set(const JsonDocument&)
+  template <typename TVariant>
+  typename enable_if<IsVisitable<TVariant>::value, bool>::type set(
+      const TVariant &value) const;
+
+  // set(enum value)
+  template <typename T>
+  FORCE_INLINE bool set(
+      T value, typename enable_if<is_enum<T>::value>::type * = 0) const {
+    return variantSetInteger(_data, static_cast<Integer>(value));
+  }
+
+#if ARDUINOJSON_HAS_NULLPTR
+  // set(nullptr_t)
+  FORCE_INLINE bool set(decltype(nullptr)) const {
+    variantSetNull(_data);
+    return true;
+  }
+#endif
+
+  template <typename T>
+  FORCE_INLINE typename VariantAs<T>::type as() const {
+    return variantAs<typename VariantAs<T>::type>(_data, _pool);
+  }
+
+  template <typename T>
+  FORCE_INLINE operator T() const {
+    return variantAs<T>(_data, _pool);
+  }
+
+  template <typename TVisitor>
+  typename TVisitor::result_type accept(TVisitor &visitor) const {
+    return variantAccept(_data, visitor);
+  }
+
+  // Change the type of the variant
+  //
+  // ArrayRef to<ArrayRef>()
+  template <typename T>
+  typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type to() const;
+  //
+  // ObjectRef to<ObjectRef>()
+  template <typename T>
+  typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type to() const;
+  //
+  // ObjectRef to<VariantRef>()
+  template <typename T>
+  typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
+      const;
+
+  VariantRef addElement() const;
+
+  FORCE_INLINE VariantRef getElement(size_t) const;
+
+  FORCE_INLINE VariantRef getOrAddElement(size_t) const;
+
+  // getMember(const char*) const
+  // getMember(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef getMember(TChar *) const;
+
+  // getMember(const std::string&) const
+  // getMember(const String&) const
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
+  getMember(const TString &) const;
+
+  // getOrAddMember(char*) const
+  // getOrAddMember(const char*) const
+  // getOrAddMember(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef getOrAddMember(TChar *) const;
+
+  // getOrAddMember(const std::string&) const
+  // getOrAddMember(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef getOrAddMember(const TString &) const;
+
+  FORCE_INLINE void remove(size_t index) const {
+    if (_data)
+      _data->remove(index);
+  }
+  // remove(char*) const
+  // remove(const char*) const
+  // remove(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
+      TChar *key) const {
+    if (_data)
+      _data->remove(adaptString(key));
+  }
+  // remove(const std::string&) const
+  // remove(const String&) const
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
+      const TString &key) const {
+    if (_data)
+      _data->remove(adaptString(key));
+  }
+
+ private:
+  MemoryPool *_pool;
+};  // namespace ARDUINOJSON_NAMESPACE
+
+class VariantConstRef : public VariantRefBase<const VariantData>,
+                        public VariantOperators<VariantConstRef>,
+                        public VariantShortcuts<VariantConstRef>,
+                        public Visitable {
+  typedef VariantRefBase<const VariantData> base_type;
+  friend class VariantRef;
+
+ public:
+  VariantConstRef() : base_type(0) {}
+  VariantConstRef(const VariantData *data) : base_type(data) {}
+  VariantConstRef(VariantRef var) : base_type(var._data) {}
+
+  template <typename TVisitor>
+  typename TVisitor::result_type accept(TVisitor &visitor) const {
+    return variantAccept(_data, visitor);
+  }
+
+  template <typename T>
+  FORCE_INLINE typename VariantConstAs<T>::type as() const {
+    return variantAs<typename VariantConstAs<T>::type>(_data);
+  }
+
+  template <typename T>
+  FORCE_INLINE operator T() const {
+    return variantAs<T>(_data);
+  }
+
+  FORCE_INLINE VariantConstRef getElement(size_t) const;
+
+  FORCE_INLINE VariantConstRef operator[](size_t index) const {
+    return getElement(index);
+  }
+
+  // getMember(const std::string&) const
+  // getMember(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantConstRef getMember(const TString &key) const {
+    return VariantConstRef(
+        objectGetMember(variantAsObject(_data), adaptString(key)));
+  }
+
+  // getMember(char*) const
+  // getMember(const char*) const
+  // getMember(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantConstRef getMember(TChar *key) const {
+    const CollectionData *obj = variantAsObject(_data);
+    return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0);
+  }
+
+  // operator[](const std::string&) const
+  // operator[](const String&) const
+  template <typename TString>
+  FORCE_INLINE
+      typename enable_if<IsString<TString>::value, VariantConstRef>::type
+      operator[](const TString &key) const {
+    return getMember(key);
+  }
+
+  // operator[](char*) const
+  // operator[](const char*) const
+  // operator[](const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE
+      typename enable_if<IsString<TChar *>::value, VariantConstRef>::type
+      operator[](TChar *key) const {
+    return getMember(key);
+  }
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantShortcuts.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,23 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayShortcuts.hpp>
+#include <ArduinoJson/Object/ObjectShortcuts.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TVariant>
+class VariantShortcuts : public ObjectShortcuts<TVariant>,
+                         public ArrayShortcuts<TVariant> {
+ public:
+  using ArrayShortcuts<TVariant>::createNestedArray;
+  using ArrayShortcuts<TVariant>::createNestedObject;
+  using ArrayShortcuts<TVariant>::operator[];
+  using ObjectShortcuts<TVariant>::createNestedArray;
+  using ObjectShortcuts<TVariant>::createNestedObject;
+  using ObjectShortcuts<TVariant>::operator[];
+};
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantSlot.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,116 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/integer.hpp>
+#include <ArduinoJson/Polyfills/limits.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+#include <ArduinoJson/Variant/VariantContent.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+typedef int_t<ARDUINOJSON_SLOT_OFFSET_SIZE * 8>::type VariantSlotDiff;
+
+class VariantSlot {
+  // CAUTION: same layout as VariantData
+  // we cannot use composition because it adds padding
+  // (+20% on ESP8266 for example)
+  VariantContent _content;
+  uint8_t _flags;
+  VariantSlotDiff _next;
+  const char* _key;
+
+ public:
+  // Must be a POD!
+  // - no constructor
+  // - no destructor
+  // - no virtual
+  // - no inheritance
+
+  VariantData* data() {
+    return reinterpret_cast<VariantData*>(&_content);
+  }
+
+  const VariantData* data() const {
+    return reinterpret_cast<const VariantData*>(&_content);
+  }
+
+  VariantSlot* next() {
+    return _next ? this + _next : 0;
+  }
+
+  const VariantSlot* next() const {
+    return const_cast<VariantSlot*>(this)->next();
+  }
+
+  VariantSlot* next(size_t distance) {
+    VariantSlot* slot = this;
+    while (distance--) {
+      if (!slot->_next)
+        return 0;
+      slot += slot->_next;
+    }
+    return slot;
+  }
+
+  const VariantSlot* next(size_t distance) const {
+    return const_cast<VariantSlot*>(this)->next(distance);
+  }
+
+  void setNext(VariantSlot* slot) {
+    ARDUINOJSON_ASSERT(!slot || slot - this >=
+                                    numeric_limits<VariantSlotDiff>::lowest());
+    ARDUINOJSON_ASSERT(!slot || slot - this <=
+                                    numeric_limits<VariantSlotDiff>::highest());
+    _next = VariantSlotDiff(slot ? slot - this : 0);
+  }
+
+  void setNextNotNull(VariantSlot* slot) {
+    ARDUINOJSON_ASSERT(slot != 0);
+    ARDUINOJSON_ASSERT(slot - this >=
+                       numeric_limits<VariantSlotDiff>::lowest());
+    ARDUINOJSON_ASSERT(slot - this <=
+                       numeric_limits<VariantSlotDiff>::highest());
+    _next = VariantSlotDiff(slot - this);
+  }
+
+  void setKey(const char* k, storage_policies::store_by_copy) {
+    ARDUINOJSON_ASSERT(k != NULL);
+    _flags |= KEY_IS_OWNED;
+    _key = k;
+  }
+
+  void setKey(const char* k, storage_policies::store_by_address) {
+    ARDUINOJSON_ASSERT(k != NULL);
+    _flags &= VALUE_MASK;
+    _key = k;
+  }
+
+  const char* key() const {
+    return _key;
+  }
+
+  bool ownsKey() const {
+    return (_flags & KEY_IS_OWNED) != 0;
+  }
+
+  void clear() {
+    _next = 0;
+    _flags = 0;
+    _key = 0;
+  }
+
+  void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
+    if (_flags & KEY_IS_OWNED)
+      _key += stringDistance;
+    if (_flags & VALUE_IS_OWNED)
+      _content.asString += stringDistance;
+    if (_flags & COLLECTION_MASK)
+      _content.asCollection.movePointers(stringDistance, variantDistance);
+  }
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantTag.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,16 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+struct VariantTag {};
+
+template <typename T>
+struct IsVariant : is_base_of<VariantTag, T> {};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/Variant/VariantTo.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,32 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+class ArrayRef;
+class ObjectRef;
+class VariantRef;
+
+// A metafunction that returns the type of the value returned by
+// VariantRef::to<T>()
+template <typename T>
+struct VariantTo {};
+
+template <>
+struct VariantTo<ArrayRef> {
+  typedef ArrayRef type;
+};
+template <>
+struct VariantTo<ObjectRef> {
+  typedef ObjectRef type;
+};
+template <>
+struct VariantTo<VariantRef> {
+  typedef VariantRef type;
+};
+
+}  // namespace ARDUINOJSON_NAMESPACE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/compatibility.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,23 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+//
+// clang-format off
+
+#ifdef __GNUC__
+
+#define ARDUINOJSON_PRAGMA(x) _Pragma(#x)
+
+#define ARDUINOJSON_COMPILE_ERROR(msg) ARDUINOJSON_PRAGMA(GCC error msg)
+
+#define ARDUINOJSON_STRINGIFY(S) #S
+
+#define ARDUINOJSON_DEPRECATION_ERROR(X, Y) \
+  ARDUINOJSON_COMPILE_ERROR(ARDUINOJSON_STRINGIFY(X is a Y from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6))
+
+#define StaticJsonBuffer ARDUINOJSON_DEPRECATION_ERROR(StaticJsonBuffer, class)
+#define DynamicJsonBuffer ARDUINOJSON_DEPRECATION_ERROR(DynamicJsonBuffer, class)
+#define JsonBuffer ARDUINOJSON_DEPRECATION_ERROR(JsonBuffer, class)
+#define RawJson ARDUINOJSON_DEPRECATION_ERROR(RawJson, function)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ArduinoJson/version.hpp	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,10 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#define ARDUINOJSON_VERSION "6.17.2"
+#define ARDUINOJSON_VERSION_MAJOR 6
+#define ARDUINOJSON_VERSION_MINOR 17
+#define ARDUINOJSON_VERSION_REVISION 2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CMakeLists.txt	Fri Mar 19 19:30:50 2021 +0000
@@ -0,0 +1,90 @@
+# ArduinoJson - arduinojson.org
+# Copyright Benoit Blanchon 2014-2021
+# MIT License
+
+# I have no idea what this is about, I simply followed the instructions from:
+# https://dominikberner.ch/cmake-interface-lib/
+
+add_library(ArduinoJson INTERFACE)
+
+include(GNUInstallDirs)
+
+# Adding the install interface generator expression makes sure that the include
+# files are installed to the proper location (provided by GNUInstallDirs)
+target_include_directories(ArduinoJson
+    INTERFACE
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+target_compile_definitions(ArduinoJson
+    INTERFACE
+        ARDUINOJSON_DEBUG=$<CONFIG:Debug>
+)
+
+# locations are provided by GNUInstallDirs
+install(
+    TARGETS
+        ArduinoJson
+    EXPORT
+        ArduinoJson_Targets
+    ARCHIVE DESTINATION
+        ${CMAKE_INSTALL_LIBDIR}
+    LIBRARY DESTINATION
+        ${CMAKE_INSTALL_LIBDIR}
+    RUNTIME DESTINATION
+        ${CMAKE_INSTALL_BINDIR}
+)
+
+include(CMakePackageConfigHelpers)
+
+if(${CMAKE_VERSION} VERSION_GREATER "3.14.0") 
+    set(ARCH_INDEPENDENT "ARCH_INDEPENDENT")
+endif()
+
+write_basic_package_version_file(
+        "${PROJECT_BINARY_DIR}/ArduinoJsonConfigVersion.cmake"
+    VERSION
+        ${PROJECT_VERSION}
+    COMPATIBILITY
+        SameMajorVersion
+    ${ARCH_INDEPENDENT}
+)
+
+configure_package_config_file(
+        "${PROJECT_SOURCE_DIR}/extras/ArduinoJsonConfig.cmake.in"
+        "${PROJECT_BINARY_DIR}/ArduinoJsonConfig.cmake"
+    INSTALL_DESTINATION
+        ${CMAKE_INSTALL_DATAROOTDIR}/ArduinoJson/cmake)
+
+install(
+    EXPORT
+        ArduinoJson_Targets
+    FILE
+        ArduinoJsonTargets.cmake
+    DESTINATION
+        ${CMAKE_INSTALL_DATAROOTDIR}/ArduinoJson/cmake
+)
+
+install(
+    FILES
+        "${PROJECT_BINARY_DIR}/ArduinoJsonConfig.cmake"
+        "${PROJECT_BINARY_DIR}/ArduinoJsonConfigVersion.cmake"
+    DESTINATION
+        "${CMAKE_INSTALL_DATAROOTDIR}/ArduinoJson/cmake"
+)
+
+install(
+    FILES
+        ArduinoJson.h
+        ArduinoJson.hpp
+    DESTINATION
+        include
+)
+
+install(
+    DIRECTORY
+        "${CMAKE_CURRENT_SOURCE_DIR}/ArduinoJson"
+    DESTINATION
+        include
+)