:twisted_rightwards_arrows: Merge branch 'release/2.0.9'
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 04a7cc1..5110aea 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -36,7 +36,7 @@
    make re2c
    ```
 
-   To run [`re2c`](http://re2c.org) and generate/overwrite file `src/json.hpp` with your changes in file `src/json.hpp.re2c`.
+   To run [`re2c`](http://re2c.org) and generate/overwrite file `src/json.hpp` with your changes in file `src/json.hpp.re2c`. We currently use re2c version 0.16. Please also use this version, because other re2c versions tend to create code that differs a lot from which makes diffs unusable.
 
 
 2. [`test/src/unit.cpp`](https://github.com/nlohmann/json/blob/master/test/unit.cpp) - This contains the [Catch](https://github.com/philsquared/Catch) unit tests which currently cover [100 %](https://coveralls.io/github/nlohmann/json) of the library's code.
@@ -59,10 +59,13 @@
 
 ## Please don't
 
-- Only make changes to file `src/json.hpp` -- please read the paragraph above and understand why `src/json.hpp.re2c` exists.
+- Please do not only make changes to file `src/json.hpp` -- please read the paragraph above and understand why `src/json.hpp.re2c` exists.
 - The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.8 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means.
 - Specifically, I am aware of compilation problems with **Microsoft Visual Studio** (there even is an [issue label](https://github.com/nlohmann/json/issues?utf8=✓&q=label%3A%22visual+studio%22+) for these kind of bugs). I understand that even in 2016, complete C++11 support isn't there yet. But please also understand that I do not want to drop features or uglify the code just to make Microsoft's sub-standard compiler happy. The past has shown that there are ways to express the functionality such that the code compiles with the most recent MSVC - unfortunately, this is not the main objective of the project.
 - Please refrain from proposing changes that would **break [JSON](http://json.org) conformance**. If you propose a conformant extension of JSON to be supported by the library, please motivate this extension.
+  - We shall not extend the library to **support comments**. There is quite some [controversy](https://www.reddit.com/r/programming/comments/4v6chu/why_json_doesnt_support_comments_douglas_crockford/) around this topic, and there were quite some [issues](https://github.com/nlohmann/json/issues/376) on this. We believe that JSON is fine without comments.
+  - We do not preserve the **insertion order of object elements**. The [JSON standard](https://tools.ietf.org/html/rfc7159.html) defines objects as "an unordered collection of zero or more name/value pairs". To this end, this library does not preserve insertion order of name/value pairs. (In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default.) Note this behavior conforms to the standard, and we shall not it to any other order.
+
 - Please do not open pull requests that address **multiple issues**.
 
 ## Wanted
diff --git a/.gitignore b/.gitignore
index bd8c869..42a18e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,5 @@
 .idea
 cmake-build-debug
 
+
+test/test-*
diff --git a/.travis.yml b/.travis.yml
index d989638..0f9010b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -39,7 +39,17 @@
         sources: ['ubuntu-toolchain-r-test']
         packages: [g++-4.9, valgrind]
     after_success:
-      - valgrind --error-exitcode=1 --leak-check=full test/json_unit
+      - make check TEST_PREFIX="valgrind --error-exitcode=1 --leak-check=full " TEST_PATTERN=""
+
+  # cLang sanitizer
+
+  #- os: linux
+  #  env:
+  #    - LLVM_VERSION=3.8.1
+  #    - SPECIAL=sanitizer
+  #  compiler: clang
+  #  before_script:
+  #    - make clang_sanitize
 
   # cppcheck
 
@@ -68,9 +78,10 @@
       - tar xf lcov_1.11.orig.tar.gz
       - sudo make -C lcov-1.11/ install
       - gem install coveralls-lcov
+      - pip install --user cpp-coveralls
     after_success:
       - make clean
-      - CXXFLAGS="--coverage -g -O0" CPPFLAGS="-DNDEBUG" make
+      - CXXFLAGS="--coverage -g -O0" CPPFLAGS="-DNDEBUG" make json_unit
       - test/json_unit "*"
       - coveralls --build-root test --exclude src/catch.hpp --exclude src/unit-algorithms.cpp --exclude src/unit-allocator.cpp --exclude src/unit-capacity.cpp --exclude src/unit-class_const_iterator.cpp --exclude src/unit-class_iterator.cpp --exclude src/unit-class_lexer.cpp --exclude src/unit-class_parser.cpp --exclude src/unit-comparison.cpp --exclude src/unit-concepts.cpp --exclude src/unit-constructor1.cpp --exclude src/unit-constructor2.cpp --exclude src/unit-convenience.cpp --exclude src/unit-conversions.cpp --exclude src/unit-deserialization.cpp --exclude src/unit-element_access1.cpp --exclude src/unit-element_access2.cpp --exclude src/unit-inspection.cpp --exclude src/unit-iterator_wrapper.cpp --exclude src/unit-iterators1.cpp --exclude src/unit-iterators2.cpp --exclude src/unit-json_patch.cpp --exclude src/unit-json_pointer.cpp --exclude src/unit-modifiers.cpp --exclude src/unit-pointer_access.cpp --exclude src/unit-readme.cpp --exclude src/unit-reference_access.cpp --exclude src/unit-regression.cpp --exclude src/unit-serialization.cpp --exclude src/unit-testsuites.cpp --exclude src/unit-unicode.cpp --include ../src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9'
       - lcov --directory src --directory test/src --capture --output-file coverage.info --rc lcov_branch_coverage=1 --no-external
@@ -236,11 +247,8 @@
   - uname -a
   - $CXX --version
 
-  # compile
-  - make
-
-  # execute unit tests
-  - test/json_unit "*"
+  # compile and execute unit tests
+  - make check
 
   # check if homebrew works (only checks develop branch)
   - if [ `which brew` ]; then
@@ -249,51 +257,3 @@
     brew install nlohmann_json --HEAD ;
     brew test nlohmann_json ;
     fi
-
-#language: cpp
-#
-#dist: trusty
-#sudo: required
-#
-#env:
-#  global:
-#   # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
-#   #   via the "travis encrypt" command using the project repo's public key
-#   - secure: "m89SSgE+ASLO38rSKx7MTXK3n5NkP9bIx95jwY71YEiuFzib30PDJ/DifKnXxBjvy/AkCGztErQRk/8ZCvq+4HXozU2knEGnL/RUitvlwbhzfh2D4lmS3BvWBGS3N3NewoPBrRmdcvnT0xjOGXxtZaJ3P74TkB9GBnlz/HmKORA="
-#
-## from http://stackoverflow.com/a/32127147/266378
-#matrix:
-#  include:
-#    - os: linux
-#      compiler: gcc
-#      addons:
-#        apt:
-#          sources: ['ubuntu-toolchain-r-test']
-#          packages: ['g++-4.9', 'valgrind', 'python-pip', 'python-yaml']
-#      before_script:
-#        - pip install --user git+git://github.com/eddyxu/cpp-coveralls.git
-#      after_success:
-#        - make clean
-#        - touch src/json.hpp
-#        - make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage -std=c++11 -lstdc++" CXX=$COMPILER
-#        - test/json_unit "*"
-#        - coveralls --build-root test --exclude src/catch.hpp --exclude src/unit-algorithms.cpp --exclude src/unit-allocator.cpp --exclude src/unit-capacity.cpp --exclude src/unit-class_const_iterator.cpp --exclude src/unit-class_iterator.cpp --exclude src/unit-class_lexer.cpp --exclude src/unit-class_parser.cpp --exclude src/unit-comparison.cpp --exclude src/unit-concepts.cpp --exclude src/unit-constructor1.cpp --exclude src/unit-constructor2.cpp --exclude src/unit-convenience.cpp --exclude src/unit-conversions.cpp --exclude src/unit-deserialization.cpp --exclude src/unit-element_access1.cpp --exclude src/unit-element_access2.cpp --exclude src/unit-inspection.cpp --exclude src/unit-iterator_wrapper.cpp --exclude src/unit-iterators1.cpp --exclude src/unit-iterators2.cpp --exclude src/unit-json_patch.cpp --exclude src/unit-json_pointer.cpp --exclude src/unit-modifiers.cpp --exclude src/unit-pointer_access.cpp --exclude src/unit-readme.cpp --exclude src/unit-reference_access.cpp --exclude src/unit-regression.cpp --exclude src/unit-serialization.cpp --exclude src/unit-testsuites.cpp --exclude src/unit-unicode.cpp --include ../src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9'
-#      env: COMPILER=g++-4.9  
-#
-#    - os: linux
-#      compiler: gcc
-#      before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
-#      addons:
-#        apt:
-#          sources: ['ubuntu-toolchain-r-test']
-#          packages: ['g++-5', 'valgrind']
-#        coverity_scan:
-#          project:
-#            name: "nlohmann/json"
-#            description: "Build submitted via Travis CI"
-#          notification_email: niels.lohmann@gmail.com
-#          build_command_prepend: "make clean ; sudo cp $(which g++-5) $(which g++)"
-#          build_command: "make"
-#          branch_pattern: coverity_scan
-#      env: COMPILER=g++-5
-#
diff --git a/CMakeLists.txt b/CMakeLists.txt
index efda6e9..8077036 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 3.0)
 
 # define the project
-project(nlohmann_json VERSION 2.0.8 LANGUAGES CXX)
+project(nlohmann_json VERSION 2.0.9 LANGUAGES CXX)
 
 enable_testing()
 
diff --git a/ChangeLog.md b/ChangeLog.md
index 287420c..9254576 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,29 @@
 # Change Log
 All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
 
+## [v2.0.9](https://github.com/nlohmann/json/releases/tag/v2.0.9) (2016-12-16)
+[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.8...v2.0.9)
+
+- \#pragma GCC diagnostic ignored "-Wdocumentation" [\#393](https://github.com/nlohmann/json/issues/393)
+- How to parse this json file and write separate sub object as json files? [\#392](https://github.com/nlohmann/json/issues/392)
+- Integer-overflow \(OSS-Fuzz issue 267\) [\#389](https://github.com/nlohmann/json/issues/389)
+- Implement indefinite-length types from RFC 7049 [\#387](https://github.com/nlohmann/json/issues/387)
+- template parameter "T" is not used in declaring the parameter types of function template [\#386](https://github.com/nlohmann/json/issues/386)
+- Serializing json instances containing already serialized string values without escaping [\#385](https://github.com/nlohmann/json/issues/385)
+- Add test cases from RFC 7049 [\#384](https://github.com/nlohmann/json/issues/384)
+- Add a table of contents to the README file [\#383](https://github.com/nlohmann/json/issues/383)
+- Update FAQ section in the guidelines for contributing [\#382](https://github.com/nlohmann/json/issues/382)
+- Allow for forward declaring nlohmann::json [\#381](https://github.com/nlohmann/json/issues/381)
+- Bug in overflow detection when parsing integers [\#380](https://github.com/nlohmann/json/issues/380)
+- A unique name to mention the library? [\#377](https://github.com/nlohmann/json/issues/377)
+- Support for comments. [\#376](https://github.com/nlohmann/json/issues/376)
+- Non-unique keys in objects. [\#375](https://github.com/nlohmann/json/issues/375)
+- Request: binary serialization/deserialization [\#358](https://github.com/nlohmann/json/issues/358)
+
+- Replace class iterator and const\_iterator by using a single template class to reduce code. [\#395](https://github.com/nlohmann/json/pull/395) ([Bosswestfalen](https://github.com/Bosswestfalen))
+- Clang: quiet a warning [\#391](https://github.com/nlohmann/json/pull/391) ([jaredgrubb](https://github.com/jaredgrubb))
+- Fix issue \#380: Signed integer overflow check [\#390](https://github.com/nlohmann/json/pull/390) ([qwename](https://github.com/qwename))
+
 ## [v2.0.8](https://github.com/nlohmann/json/releases/tag/v2.0.8) (2016-12-02)
 [Full Changelog](https://github.com/nlohmann/json/compare/v2.0.7...v2.0.8)
 
@@ -8,7 +31,6 @@
 - Compiler warnings? [\#372](https://github.com/nlohmann/json/issues/372)
 - docs: how to release a json object in memory? [\#371](https://github.com/nlohmann/json/issues/371)
 - crash in dump [\#370](https://github.com/nlohmann/json/issues/370)
-- Conversion operators not considered [\#369](https://github.com/nlohmann/json/issues/369)
 - Coverity issue \(FORWARD\_NULL\) in lexer\(std::istream& s\) [\#368](https://github.com/nlohmann/json/issues/368)
 - json::parse on failed stream gets stuck [\#366](https://github.com/nlohmann/json/issues/366)
 - Performance improvements [\#365](https://github.com/nlohmann/json/issues/365)
diff --git a/Makefile b/Makefile
index 3fd6d54..fcce453 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,8 @@
 SED = sed
 
 # main target
-all: json_unit
+all:
+	$(MAKE) -C test
 
 # clean up
 clean:
@@ -21,14 +22,14 @@
 
 # build unit tests
 json_unit:
-	@$(MAKE) -C test
+	@$(MAKE) json_unit -C test
 
 # run unit tests
-check: json_unit
-	test/json_unit "*"
+check:
+	$(MAKE) check -C test
 
-check-fast: json_unit
-	test/json_unit
+check-fast:
+	$(MAKE) check -C test TEST_PATTERN=""
 
 
 ##########################################################################
@@ -69,6 +70,7 @@
 clang_sanitize: clean
 	CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE)
 
+
 ##########################################################################
 # maintainer targets
 ##########################################################################
diff --git a/README.md b/README.md
index 0305ea0..97ae685 100644
--- a/README.md
+++ b/README.md
@@ -4,13 +4,29 @@
 [![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json)
 [![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json)
 [![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json)
-[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/fsf5FqYe6GoX68W6)
+[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/8soFCqS532vOyZcK)
 [![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json)
 [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
 [![Github Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases)
 [![Github Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](http://github.com/nlohmann/json/issues)
 [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289)
 
+- [Design goals](#design-goals)
+- [Integration](#integration)
+- [Examples](#examples)
+  - [JSON as first-class data type](#json-as-first-class-data-type)
+  - [Serialization / Deserialization](#serialization--deserialization)
+  - [STL-like access](#stl-like-access)
+  - [Conversion from STL containers](#conversion-from-stl-containers)
+  - [JSON Pointer and JSON Patch](#json-pointer-and-json-patch)
+  - [Implicit conversions](#implicit-conversions)
+  - [Binary formats (CBOR and MessagePack)](#binary-formats-cbor-and-messagepack)
+- [Supported compilers](#supported-compilers)
+- [License](#license)
+- [Thanks](#thanks)
+- [Notes](#notes)
+- [Execute unit tests](#execute-unit-tests)
+
 ## Design goals
 
 There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals:
@@ -48,6 +64,10 @@
 
 ## Examples
 
+Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a602f275f0359ab181221384989810604.html#a602f275f0359ab181221384989810604)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
+
+### JSON as first-class data type
+
 Here are some examples to give you an idea how to use the class.
 
 Assume you want to create the JSON object
@@ -421,6 +441,31 @@
 // etc.
 ```
 
+### Binary formats (CBOR and MessagePack)
+
+Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [CBOR](http://cbor.io) (Concise Binary Object Representation) and [MessagePack](http://msgpack.org) to efficiently encode JSON values to byte vectors and to decode such vectors.
+
+```cpp
+// create a JSON value
+json j = R"({"compact": true, "schema": 0})"_json;
+
+// serialize to CBOR
+std::vector<uint8_t> v_cbor = json::to_cbor(j);
+
+// 0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00
+
+// roundtrip
+json j_from_cbor = json::from_cbor(v_cbor);
+
+// serialize to MessagePack
+std::vector<uint8_t> v_msgpack = json::to_msgpack(j);
+
+// 0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00
+
+// roundtrip
+json j_from_msgpack = json::from_msgpack(v_msgpack);
+```
+
 
 ## Supported compilers
 
@@ -537,6 +582,9 @@
 - [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
 - [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser and improved the benchmarking code.
 - [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan.
+- [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning.
+- [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check.
+- [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one.
 
 Thanks a lot for helping out!
 
@@ -560,7 +608,7 @@
 $ make check
 
 ===============================================================================
-All tests passed (8905518 assertions in 36 test cases)
+All tests passed (11201893 assertions in 43 test cases)
 ```
 
 Alternatively, you can use [CMake](https://cmake.org) and run
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 625f9c1..17c81d8 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -5,7 +5,7 @@
 #---------------------------------------------------------------------------
 DOXYFILE_ENCODING      = UTF-8
 PROJECT_NAME           = "JSON for Modern C++"
-PROJECT_NUMBER         = 2.0.8
+PROJECT_NUMBER         = 2.0.9
 PROJECT_BRIEF          = 
 PROJECT_LOGO           =
 OUTPUT_DIRECTORY       = .
diff --git a/doc/examples/README.link b/doc/examples/README.link
index 48a66aa..128ab1d 100644
--- a/doc/examples/README.link
+++ b/doc/examples/README.link
@@ -1 +1 @@
-<a target="_blank" href="http://melpon.org/wandbox/permlink/G6Pdtdxq01HJvvJz"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="http://melpon.org/wandbox/permlink/8soFCqS532vOyZcK"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/from_cbor.cpp b/doc/examples/from_cbor.cpp
new file mode 100644
index 0000000..92b0522
--- /dev/null
+++ b/doc/examples/from_cbor.cpp
@@ -0,0 +1,18 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+    // create byte vector
+    std::vector<uint8_t> v = {0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63,
+                              0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d,
+                              0x61, 0x00
+                             };
+
+    // deserialize it with CBOR
+    json j = json::from_cbor(v);
+
+    // print the deserialized JSON value
+    std::cout << std::setw(2) << j << std::endl;
+}
diff --git a/doc/examples/from_cbor.link b/doc/examples/from_cbor.link
new file mode 100644
index 0000000..8120498
--- /dev/null
+++ b/doc/examples/from_cbor.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/TDPaxmQ7PsvfWxrs"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/from_cbor.output b/doc/examples/from_cbor.output
new file mode 100644
index 0000000..259f63b
--- /dev/null
+++ b/doc/examples/from_cbor.output
@@ -0,0 +1,4 @@
+{
+  "compact": true,
+  "schema": 0
+}
diff --git a/doc/examples/from_msgpack.cpp b/doc/examples/from_msgpack.cpp
new file mode 100644
index 0000000..d275f13
--- /dev/null
+++ b/doc/examples/from_msgpack.cpp
@@ -0,0 +1,18 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+    // create byte vector
+    std::vector<uint8_t> v = {0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63,
+                              0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d,
+                              0x61, 0x00
+                             };
+
+    // deserialize it with MessagePack
+    json j = json::from_msgpack(v);
+
+    // print the deserialized JSON value
+    std::cout << std::setw(2) << j << std::endl;
+}
diff --git a/doc/examples/from_msgpack.link b/doc/examples/from_msgpack.link
new file mode 100644
index 0000000..0d5e783
--- /dev/null
+++ b/doc/examples/from_msgpack.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/7vRGmLdVcYM7POhE"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/from_msgpack.output b/doc/examples/from_msgpack.output
new file mode 100644
index 0000000..259f63b
--- /dev/null
+++ b/doc/examples/from_msgpack.output
@@ -0,0 +1,4 @@
+{
+  "compact": true,
+  "schema": 0
+}
diff --git a/doc/examples/to_cbor.cpp b/doc/examples/to_cbor.cpp
new file mode 100644
index 0000000..21a5ce8
--- /dev/null
+++ b/doc/examples/to_cbor.cpp
@@ -0,0 +1,19 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+    // create a JSON value
+    json j = R"({"compact": true, "schema": 0})"_json;
+
+    // serialize it to CBOR
+    std::vector<uint8_t> v = json::to_cbor(j);
+
+    // print the vector content
+    for (auto& byte : v)
+    {
+        std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
+    }
+    std::cout << std::endl;
+}
diff --git a/doc/examples/to_cbor.link b/doc/examples/to_cbor.link
new file mode 100644
index 0000000..3ab655c
--- /dev/null
+++ b/doc/examples/to_cbor.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/UaDbrgZ8OPWaShY8"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/to_cbor.output b/doc/examples/to_cbor.output
new file mode 100644
index 0000000..02c9ada
--- /dev/null
+++ b/doc/examples/to_cbor.output
@@ -0,0 +1 @@
+0xa2 0x67 0x63 0x6f 0x6d 0x70 0x61 0x63 0x74 0xf5 0x66 0x73 0x63 0x68 0x65 0x6d 0x61 0x00 
diff --git a/doc/examples/to_msgpack.cpp b/doc/examples/to_msgpack.cpp
new file mode 100644
index 0000000..21c8817
--- /dev/null
+++ b/doc/examples/to_msgpack.cpp
@@ -0,0 +1,19 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+    // create a JSON value
+    json j = R"({"compact": true, "schema": 0})"_json;
+
+    // serialize it to MessagePack
+    std::vector<uint8_t> v = json::to_msgpack(j);
+
+    // print the vector content
+    for (auto& byte : v)
+    {
+        std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
+    }
+    std::cout << std::endl;
+}
diff --git a/doc/examples/to_msgpack.link b/doc/examples/to_msgpack.link
new file mode 100644
index 0000000..4c7d3a2
--- /dev/null
+++ b/doc/examples/to_msgpack.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/jvaU8GEfAusb5dKf"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/to_msgpack.output b/doc/examples/to_msgpack.output
new file mode 100644
index 0000000..4d6c40a
--- /dev/null
+++ b/doc/examples/to_msgpack.output
@@ -0,0 +1 @@
+0x82 0xa7 0x63 0x6f 0x6d 0x70 0x61 0x63 0x74 0xc3 0xa6 0x73 0x63 0x68 0x65 0x6d 0x61 0x00 
diff --git a/doc/index.md b/doc/index.md
index 0b608eb..8292fe6 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -277,4 +277,4 @@
 @author [Niels Lohmann](http://nlohmann.me)
 @see https://github.com/nlohmann/json to download the source code
 
-@version 2.0.8
+@version 2.0.9
diff --git a/doc/json.gif b/doc/json.gif
index a5f1187..7d3bf81 100644
--- a/doc/json.gif
+++ b/doc/json.gif
Binary files differ
diff --git a/src/json.hpp b/src/json.hpp
index 6fed0a1..23058be 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -34,7 +34,7 @@
 #include <cassert> // assert
 #include <cctype> // isdigit
 #include <ciso646> // and, not, or
-#include <cmath> // isfinite, signbit
+#include <cmath> // isfinite, ldexp, signbit
 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
 #include <cstdint> // int64_t, uint64_t
 #include <cstdlib> // strtod, strtof, strtold, strtoul
@@ -75,6 +75,12 @@
     #pragma GCC diagnostic ignored "-Wfloat-equal"
 #endif
 
+// disable documentation warnings on clang
+#if defined(__clang__)
+    #pragma GCC diagnostic push
+    #pragma GCC diagnostic ignored "-Wdocumentation"
+#endif
+
 // allow for portable deprecation warnings
 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
     #define JSON_DEPRECATED __attribute__((deprecated))
@@ -222,6 +228,7 @@
 
   public:
     // forward declarations
+    template<typename U> class iter_impl;
     template<typename Base> class json_reverse_iterator;
     class json_pointer;
 
@@ -256,9 +263,9 @@
     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
 
     /// an iterator for a basic_json container
-    class iterator;
+    using iterator = iter_impl<basic_json>;
     /// a const iterator for a basic_json container
-    class const_iterator;
+    using const_iterator = iter_impl<const basic_json>;
     /// a reverse iterator for a basic_json container
     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
     /// a const reverse iterator for a basic_json container
@@ -944,7 +951,7 @@
 
     With a parser callback function, the result of parsing a JSON text can be
     influenced. When passed to @ref parse(std::istream&, const
-    parser_callback_t) or @ref parse(const char*, const parser_callback_t),
+    parser_callback_t) or @ref parse(const CharT, const parser_callback_t),
     it is called on certain events (passed as @ref parse_event_t via parameter
     @a event) with a set recursion depth @a depth and context JSON value
     @a parsed. The return value of the callback function is a boolean
@@ -987,7 +994,7 @@
     skipped completely or replaced by an empty discarded object.
 
     @sa @ref parse(std::istream&, parser_callback_t) or
-    @ref parse(const char*, parser_callback_t) for examples
+    @ref parse(const CharT, const parser_callback_t) for examples
 
     @since version 1.0.0
     */
@@ -6003,11 +6010,11 @@
 
     @since version 1.0.0 (originally for @ref string_t)
     */
-    template<typename CharPT, typename std::enable_if<
-                 std::is_pointer<CharPT>::value and
-                 std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
-                 sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
-    static basic_json parse(const CharPT s,
+    template<typename CharT, typename std::enable_if<
+                 std::is_pointer<CharT>::value and
+                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
+                 sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
+    static basic_json parse(const CharT s,
                             const parser_callback_t cb = nullptr)
     {
         return parser(reinterpret_cast<const char*>(s), cb).parse();
@@ -6032,7 +6039,7 @@
     @liveexample{The example below demonstrates the `parse()` function with
     and without callback function.,parse__istream__parser_callback_t}
 
-    @sa @ref parse(const char*, const parser_callback_t) for a version
+    @sa @ref parse(const CharT, const parser_callback_t) for a version
     that reads from a string
 
     @since version 1.0.0
@@ -6217,6 +6224,1435 @@
 
     /// @}
 
+    //////////////////////////////////////////
+    // binary serialization/deserialization //
+    //////////////////////////////////////////
+
+    /// @name binary serialization/deserialization support
+    /// @{
+
+  private:
+    template<typename T>
+    static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
+    {
+        assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
+
+        switch (bytes)
+        {
+            case 8:
+            {
+                vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
+                vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
+                vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
+                vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
+                // intentional fall-through
+            }
+
+            case 4:
+            {
+                vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
+                vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
+                // intentional fall-through
+            }
+
+            case 2:
+            {
+                vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
+                // intentional fall-through
+            }
+
+            case 1:
+            {
+                vec.push_back(static_cast<uint8_t>(number & 0xff));
+                break;
+            }
+        }
+    }
+
+    /*!
+    @brief take sufficient bytes from a vector to fill an integer variable
+
+    In the context of binary serialization formats, we need to read several
+    bytes from a byte vector and combine them to multi-byte integral data
+    types.
+
+    @param[in] vec  byte vector to read from
+    @param[in] current_index  the position in the vector after which to read
+
+    @return the next sizeof(T) bytes from @a vec, in reverse order as T
+
+    @tparam T the integral return type
+
+    @throw std::out_of_range if there are less than sizeof(T)+1 bytes in the
+           vector @a vec to read
+
+    In the for loop, the bytes from the vector are copied in reverse order into
+    the return value. In the figures below, let sizeof(T)=4 and `i` be the loop
+    variable.
+
+    Precondition:
+
+    vec:   |   |   | a | b | c | d |      T: |   |   |   |   |
+                 ^               ^             ^                ^
+           current_index         i            ptr        sizeof(T)
+
+    Postcondition:
+
+    vec:   |   |   | a | b | c | d |      T: | d | c | b | a |
+                 ^   ^                                     ^
+                 |   i                                    ptr
+           current_index
+
+    @sa Code adapted from <http://stackoverflow.com/a/41031865/266378>.
+    */
+    template<typename T>
+    static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
+    {
+        if (current_index + sizeof(T) + 1 > vec.size())
+        {
+            throw std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector");
+        }
+
+        T result;
+        uint8_t* ptr = reinterpret_cast<uint8_t*>(&result);
+        for (size_t i = 0; i < sizeof(T); ++i)
+        {
+            *ptr++ = vec[current_index + sizeof(T) - i];
+        }
+        return result;
+    }
+
+    /*!
+    @brief create a MessagePack serialization of a given JSON value
+
+    This is a straightforward implementation of the MessagePack specification.
+
+    @param[in] j  JSON value to serialize
+    @param[in,out] v  byte vector to write the serialization to
+
+    @sa https://github.com/msgpack/msgpack/blob/master/spec.md
+    */
+    static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                // nil
+                v.push_back(0xc0);
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                // true and false
+                v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // MessagePack does not differentiate between positive
+                    // signed integers and unsigned integers. Therefore, we used
+                    // the code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_unsigned < 128)
+                    {
+                        // positive fixnum
+                        add_to_vector(v, 1, j.m_value.number_unsigned);
+                    }
+                    else if (j.m_value.number_unsigned <= UINT8_MAX)
+                    {
+                        // uint 8
+                        v.push_back(0xcc);
+                        add_to_vector(v, 1, j.m_value.number_unsigned);
+                    }
+                    else if (j.m_value.number_unsigned <= UINT16_MAX)
+                    {
+                        // uint 16
+                        v.push_back(0xcd);
+                        add_to_vector(v, 2, j.m_value.number_unsigned);
+                    }
+                    else if (j.m_value.number_unsigned <= UINT32_MAX)
+                    {
+                        // uint 32
+                        v.push_back(0xce);
+                        add_to_vector(v, 4, j.m_value.number_unsigned);
+                    }
+                    else if (j.m_value.number_unsigned <= UINT64_MAX)
+                    {
+                        // uint 64
+                        v.push_back(0xcf);
+                        add_to_vector(v, 8, j.m_value.number_unsigned);
+                    }
+                }
+                else
+                {
+                    if (j.m_value.number_integer >= -32)
+                    {
+                        // negative fixnum
+                        add_to_vector(v, 1, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
+                    {
+                        // int 8
+                        v.push_back(0xd0);
+                        add_to_vector(v, 1, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
+                    {
+                        // int 16
+                        v.push_back(0xd1);
+                        add_to_vector(v, 2, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
+                    {
+                        // int 32
+                        v.push_back(0xd2);
+                        add_to_vector(v, 4, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
+                    {
+                        // int 64
+                        v.push_back(0xd3);
+                        add_to_vector(v, 8, j.m_value.number_integer);
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned < 128)
+                {
+                    // positive fixnum
+                    add_to_vector(v, 1, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= UINT8_MAX)
+                {
+                    // uint 8
+                    v.push_back(0xcc);
+                    add_to_vector(v, 1, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= UINT16_MAX)
+                {
+                    // uint 16
+                    v.push_back(0xcd);
+                    add_to_vector(v, 2, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= UINT32_MAX)
+                {
+                    // uint 32
+                    v.push_back(0xce);
+                    add_to_vector(v, 4, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= UINT64_MAX)
+                {
+                    // uint 64
+                    v.push_back(0xcf);
+                    add_to_vector(v, 8, j.m_value.number_unsigned);
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                // float 64
+                v.push_back(0xcb);
+                const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
+                for (size_t i = 0; i < 8; ++i)
+                {
+                    v.push_back(helper[7 - i]);
+                }
+                break;
+            }
+
+            case value_t::string:
+            {
+                const auto N = j.m_value.string->size();
+                if (N <= 31)
+                {
+                    // fixstr
+                    v.push_back(static_cast<uint8_t>(0xa0 | N));
+                }
+                else if (N <= 255)
+                {
+                    // str 8
+                    v.push_back(0xd9);
+                    add_to_vector(v, 1, N);
+                }
+                else if (N <= 65535)
+                {
+                    // str 16
+                    v.push_back(0xda);
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 4294967295)
+                {
+                    // str 32
+                    v.push_back(0xdb);
+                    add_to_vector(v, 4, N);
+                }
+
+                // append string
+                std::copy(j.m_value.string->begin(), j.m_value.string->end(),
+                          std::back_inserter(v));
+                break;
+            }
+
+            case value_t::array:
+            {
+                const auto N = j.m_value.array->size();
+                if (N <= 15)
+                {
+                    // fixarray
+                    v.push_back(static_cast<uint8_t>(0x90 | N));
+                }
+                else if (N <= 0xffff)
+                {
+                    // array 16
+                    v.push_back(0xdc);
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 0xffffffff)
+                {
+                    // array 32
+                    v.push_back(0xdd);
+                    add_to_vector(v, 4, N);
+                }
+
+                // append each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    to_msgpack_internal(el, v);
+                }
+                break;
+            }
+
+            case value_t::object:
+            {
+                const auto N = j.m_value.object->size();
+                if (N <= 15)
+                {
+                    // fixmap
+                    v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
+                }
+                else if (N <= 65535)
+                {
+                    // map 16
+                    v.push_back(0xde);
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 4294967295)
+                {
+                    // map 32
+                    v.push_back(0xdf);
+                    add_to_vector(v, 4, N);
+                }
+
+                // append each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    to_msgpack_internal(el.first, v);
+                    to_msgpack_internal(el.second, v);
+                }
+                break;
+            }
+
+            default:
+            {
+                break;
+            }
+        }
+    }
+
+    /*!
+    @brief create a CBOR serialization of a given JSON value
+
+    This is a straightforward implementation of the CBOR specification.
+
+    @param[in] j  JSON value to serialize
+    @param[in,out] v  byte vector to write the serialization to
+
+    @sa https://tools.ietf.org/html/rfc7049
+    */
+    static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                v.push_back(0xf6);
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // CBOR does not differentiate between positive signed
+                    // integers and unsigned integers. Therefore, we used the
+                    // code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_integer <= 0x17)
+                    {
+                        add_to_vector(v, 1, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer <= UINT8_MAX)
+                    {
+                        v.push_back(0x18);
+                        // one-byte uint8_t
+                        add_to_vector(v, 1, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer <= UINT16_MAX)
+                    {
+                        v.push_back(0x19);
+                        // two-byte uint16_t
+                        add_to_vector(v, 2, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer <= UINT32_MAX)
+                    {
+                        v.push_back(0x1a);
+                        // four-byte uint32_t
+                        add_to_vector(v, 4, j.m_value.number_integer);
+                    }
+                    else
+                    {
+                        v.push_back(0x1b);
+                        // eight-byte uint64_t
+                        add_to_vector(v, 8, j.m_value.number_integer);
+                    }
+                }
+                else
+                {
+                    // The conversions below encode the sign in the first byte,
+                    // and the value is converted to a positive number.
+                    const auto positive_number = -1 - j.m_value.number_integer;
+                    if (j.m_value.number_integer >= -24)
+                    {
+                        v.push_back(static_cast<uint8_t>(0x20 + positive_number));
+                    }
+                    else if (positive_number <= UINT8_MAX)
+                    {
+                        // int 8
+                        v.push_back(0x38);
+                        add_to_vector(v, 1, positive_number);
+                    }
+                    else if (positive_number <= UINT16_MAX)
+                    {
+                        // int 16
+                        v.push_back(0x39);
+                        add_to_vector(v, 2, positive_number);
+                    }
+                    else if (positive_number <= UINT32_MAX)
+                    {
+                        // int 32
+                        v.push_back(0x3a);
+                        add_to_vector(v, 4, positive_number);
+                    }
+                    else
+                    {
+                        // int 64
+                        v.push_back(0x3b);
+                        add_to_vector(v, 8, positive_number);
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned <= 0x17)
+                {
+                    v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= 0xff)
+                {
+                    v.push_back(0x18);
+                    // one-byte uint8_t
+                    add_to_vector(v, 1, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= 0xffff)
+                {
+                    v.push_back(0x19);
+                    // two-byte uint16_t
+                    add_to_vector(v, 2, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= 0xffffffff)
+                {
+                    v.push_back(0x1a);
+                    // four-byte uint32_t
+                    add_to_vector(v, 4, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
+                {
+                    v.push_back(0x1b);
+                    // eight-byte uint64_t
+                    add_to_vector(v, 8, j.m_value.number_unsigned);
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                // Double-Precision Float
+                v.push_back(0xfb);
+                const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
+                for (size_t i = 0; i < 8; ++i)
+                {
+                    v.push_back(helper[7 - i]);
+                }
+                break;
+            }
+
+            case value_t::string:
+            {
+                const auto N = j.m_value.string->size();
+                if (N <= 0x17)
+                {
+                    v.push_back(0x60 + N);  // 1 byte for string + size
+                }
+                else if (N <= 0xff)
+                {
+                    v.push_back(0x78);  // one-byte uint8_t for N
+                    add_to_vector(v, 1, N);
+                }
+                else if (N <= 0xffff)
+                {
+                    v.push_back(0x79);  // two-byte uint16_t for N
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 0xffffffff)
+                {
+                    v.push_back(0x7a); // four-byte uint32_t for N
+                    add_to_vector(v, 4, N);
+                }
+                // LCOV_EXCL_START
+                else if (N <= 0xffffffffffffffff)
+                {
+                    v.push_back(0x7b);  // eight-byte uint64_t for N
+                    add_to_vector(v, 8, N);
+                }
+                // LCOV_EXCL_STOP
+
+                // append string
+                std::copy(j.m_value.string->begin(), j.m_value.string->end(),
+                          std::back_inserter(v));
+                break;
+            }
+
+            case value_t::array:
+            {
+                const auto N = j.m_value.array->size();
+                if (N <= 0x17)
+                {
+                    v.push_back(0x80 + N);  // 1 byte for array + size
+                }
+                else if (N <= 0xff)
+                {
+                    v.push_back(0x98);  // one-byte uint8_t for N
+                    add_to_vector(v, 1, N);
+                }
+                else if (N <= 0xffff)
+                {
+                    v.push_back(0x99);  // two-byte uint16_t for N
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 0xffffffff)
+                {
+                    v.push_back(0x9a);  // four-byte uint32_t for N
+                    add_to_vector(v, 4, N);
+                }
+                // LCOV_EXCL_START
+                else if (N <= 0xffffffffffffffff)
+                {
+                    v.push_back(0x9b);  // eight-byte uint64_t for N
+                    add_to_vector(v, 8, N);
+                }
+                // LCOV_EXCL_STOP
+
+                // append each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    to_cbor_internal(el, v);
+                }
+                break;
+            }
+
+            case value_t::object:
+            {
+                const auto N = j.m_value.object->size();
+                if (N <= 0x17)
+                {
+                    v.push_back(0xa0 + N);  // 1 byte for object + size
+                }
+                else if (N <= 0xff)
+                {
+                    v.push_back(0xb8);
+                    add_to_vector(v, 1, N);  // one-byte uint8_t for N
+                }
+                else if (N <= 0xffff)
+                {
+                    v.push_back(0xb9);
+                    add_to_vector(v, 2, N);  // two-byte uint16_t for N
+                }
+                else if (N <= 0xffffffff)
+                {
+                    v.push_back(0xba);
+                    add_to_vector(v, 4, N);  // four-byte uint32_t for N
+                }
+                // LCOV_EXCL_START
+                else if (N <= 0xffffffffffffffff)
+                {
+                    v.push_back(0xbb);
+                    add_to_vector(v, 8, N);  // eight-byte uint64_t for N
+                }
+                // LCOV_EXCL_STOP
+
+                // append each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    to_cbor_internal(el.first, v);
+                    to_cbor_internal(el.second, v);
+                }
+                break;
+            }
+
+            default:
+            {
+                break;
+            }
+        }
+    }
+
+    /*!
+    @brief create a JSON value from a given MessagePack vector
+
+    @param[in] v  MessagePack serialization
+    @param[in] idx  byte index to start reading from @a v
+
+    @return deserialized JSON value
+
+    @throw std::invalid_argument if unsupported features from MessagePack were
+    used in the given vector @a v or if the input is not valid MessagePack
+    @throw std::out_of_range if the given vector ends prematurely
+
+    @sa https://github.com/msgpack/msgpack/blob/master/spec.md
+    */
+    static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
+    {
+        // store and increment index
+        const size_t current_idx = idx++;
+
+        if (v[current_idx] <= 0xbf)
+        {
+            if (v[current_idx] <= 0x7f) // positive fixint
+            {
+                return v[current_idx];
+            }
+            else if (v[current_idx] <= 0x8f) // fixmap
+            {
+                basic_json result = value_t::object;
+                const size_t len = v[current_idx] & 0x0f;
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_msgpack_internal(v, idx);
+                    result[key] = from_msgpack_internal(v, idx);
+                }
+                return result;
+            }
+            else if (v[current_idx] <= 0x9f) // fixarray
+            {
+                basic_json result = value_t::array;
+                const size_t len = v[current_idx] & 0x0f;
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_msgpack_internal(v, idx));
+                }
+                return result;
+            }
+            else // fixstr
+            {
+                const size_t len = v[current_idx] & 0x1f;
+                const size_t offset = current_idx + 1;
+                idx += len; // skip content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+        }
+        else if (v[current_idx] >= 0xe0) // negative fixint
+        {
+            return static_cast<int8_t>(v[current_idx]);
+        }
+        else
+        {
+            switch (v[current_idx])
+            {
+                case 0xc0: // nil
+                {
+                    return value_t::null;
+                }
+
+                case 0xc2: // false
+                {
+                    return false;
+                }
+
+                case 0xc3: // true
+                {
+                    return true;
+                }
+
+                case 0xca: // float 32
+                {
+                    // copy bytes in reverse order into the double variable
+                    float res;
+                    for (size_t byte = 0; byte < sizeof(float); ++byte)
+                    {
+                        reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
+                    }
+                    idx += sizeof(float); // skip content bytes
+                    return res;
+                }
+
+                case 0xcb: // float 64
+                {
+                    // copy bytes in reverse order into the double variable
+                    double res;
+                    for (size_t byte = 0; byte < sizeof(double); ++byte)
+                    {
+                        reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
+                    }
+                    idx += sizeof(double); // skip content bytes
+                    return res;
+                }
+
+                case 0xcc: // uint 8
+                {
+                    idx += 1; // skip content byte
+                    return get_from_vector<uint8_t>(v, current_idx);
+                }
+
+                case 0xcd: // uint 16
+                {
+                    idx += 2; // skip 2 content bytes
+                    return get_from_vector<uint16_t>(v, current_idx);
+                }
+
+                case 0xce: // uint 32
+                {
+                    idx += 4; // skip 4 content bytes
+                    return get_from_vector<uint32_t>(v, current_idx);
+                }
+
+                case 0xcf: // uint 64
+                {
+                    idx += 8; // skip 8 content bytes
+                    return get_from_vector<uint64_t>(v, current_idx);
+                }
+
+                case 0xd0: // int 8
+                {
+                    idx += 1; // skip content byte
+                    return get_from_vector<int8_t>(v, current_idx);
+                }
+
+                case 0xd1: // int 16
+                {
+                    idx += 2; // skip 2 content bytes
+                    return get_from_vector<int16_t>(v, current_idx);
+                }
+
+                case 0xd2: // int 32
+                {
+                    idx += 4; // skip 4 content bytes
+                    return get_from_vector<int32_t>(v, current_idx);
+                }
+
+                case 0xd3: // int 64
+                {
+                    idx += 8; // skip 8 content bytes
+                    return get_from_vector<int64_t>(v, current_idx);
+                }
+
+                case 0xd9: // str 8
+                {
+                    const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+                    const size_t offset = current_idx + 2;
+                    idx += len + 1; // skip size byte + content bytes
+                    return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+                }
+
+                case 0xda: // str 16
+                {
+                    const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                    const size_t offset = current_idx + 3;
+                    idx += len + 2; // skip 2 size bytes + content bytes
+                    return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+                }
+
+                case 0xdb: // str 32
+                {
+                    const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                    const size_t offset = current_idx + 5;
+                    idx += len + 4; // skip 4 size bytes + content bytes
+                    return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+                }
+
+                case 0xdc: // array 16
+                {
+                    basic_json result = value_t::array;
+                    const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                    idx += 2; // skip 2 size bytes
+                    for (size_t i = 0; i < len; ++i)
+                    {
+                        result.push_back(from_msgpack_internal(v, idx));
+                    }
+                    return result;
+                }
+
+                case 0xdd: // array 32
+                {
+                    basic_json result = value_t::array;
+                    const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                    idx += 4; // skip 4 size bytes
+                    for (size_t i = 0; i < len; ++i)
+                    {
+                        result.push_back(from_msgpack_internal(v, idx));
+                    }
+                    return result;
+                }
+
+                case 0xde: // map 16
+                {
+                    basic_json result = value_t::object;
+                    const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                    idx += 2; // skip 2 size bytes
+                    for (size_t i = 0; i < len; ++i)
+                    {
+                        std::string key = from_msgpack_internal(v, idx);
+                        result[key] = from_msgpack_internal(v, idx);
+                    }
+                    return result;
+                }
+
+                case 0xdf: // map 32
+                {
+                    basic_json result = value_t::object;
+                    const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                    idx += 4; // skip 4 size bytes
+                    for (size_t i = 0; i < len; ++i)
+                    {
+                        std::string key = from_msgpack_internal(v, idx);
+                        result[key] = from_msgpack_internal(v, idx);
+                    }
+                    return result;
+                }
+
+                default:
+                {
+                    throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
+                }
+            }
+        }
+    }
+
+    /*!
+    @brief create a JSON value from a given CBOR vector
+
+    @param[in] v  CBOR serialization
+    @param[in] idx  byte index to start reading from @a v
+
+    @return deserialized JSON value
+
+    @throw std::invalid_argument if unsupported features from CBOR were used in
+    the given vector @a v or if the input is not valid CBOR
+    @throw std::out_of_range if the given vector ends prematurely
+
+    @sa https://tools.ietf.org/html/rfc7049
+    */
+    static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
+    {
+        // store and increment index
+        const size_t current_idx = idx++;
+
+        switch (v[current_idx])
+        {
+            // Integer 0x00..0x17 (0..23)
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x04:
+            case 0x05:
+            case 0x06:
+            case 0x07:
+            case 0x08:
+            case 0x09:
+            case 0x0a:
+            case 0x0b:
+            case 0x0c:
+            case 0x0d:
+            case 0x0e:
+            case 0x0f:
+            case 0x10:
+            case 0x11:
+            case 0x12:
+            case 0x13:
+            case 0x14:
+            case 0x15:
+            case 0x16:
+            case 0x17:
+            {
+                return v[current_idx];
+            }
+
+            case 0x18: // Unsigned integer (one-byte uint8_t follows)
+            {
+                idx += 1; // skip content byte
+                return get_from_vector<uint8_t>(v, current_idx);
+            }
+
+            case 0x19: // Unsigned integer (two-byte uint16_t follows)
+            {
+                idx += 2; // skip 2 content bytes
+                return get_from_vector<uint16_t>(v, current_idx);
+            }
+
+            case 0x1a: // Unsigned integer (four-byte uint32_t follows)
+            {
+                idx += 4; // skip 4 content bytes
+                return get_from_vector<uint32_t>(v, current_idx);
+            }
+
+            case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
+            {
+                idx += 8; // skip 8 content bytes
+                return get_from_vector<uint64_t>(v, current_idx);
+            }
+
+            // Negative integer -1-0x00..-1-0x17 (-1..-24)
+            case 0x20:
+            case 0x21:
+            case 0x22:
+            case 0x23:
+            case 0x24:
+            case 0x25:
+            case 0x26:
+            case 0x27:
+            case 0x28:
+            case 0x29:
+            case 0x2a:
+            case 0x2b:
+            case 0x2c:
+            case 0x2d:
+            case 0x2e:
+            case 0x2f:
+            case 0x30:
+            case 0x31:
+            case 0x32:
+            case 0x33:
+            case 0x34:
+            case 0x35:
+            case 0x36:
+            case 0x37:
+            {
+                return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
+            }
+
+            case 0x38: // Negative integer (one-byte uint8_t follows)
+            {
+                idx += 1; // skip content byte
+                // must be uint8_t !
+                return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
+            }
+
+            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
+            {
+                idx += 2; // skip 2 content bytes
+                return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
+            }
+
+            case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
+            {
+                idx += 4; // skip 4 content bytes
+                return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
+            }
+
+            case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
+            {
+                idx += 8; // skip 8 content bytes
+                return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
+            }
+
+            // UTF-8 string (0x00..0x17 bytes follow)
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6a:
+            case 0x6b:
+            case 0x6c:
+            case 0x6d:
+            case 0x6e:
+            case 0x6f:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            {
+                const auto len = static_cast<size_t>(v[current_idx] - 0x60);
+                const size_t offset = current_idx + 1;
+                idx += len; // skip content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+            {
+                const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+                const size_t offset = current_idx + 2;
+                idx += len + 1; // skip size byte + content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+            {
+                const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                const size_t offset = current_idx + 3;
+                idx += len + 2; // skip 2 size bytes + content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
+            {
+                const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                const size_t offset = current_idx + 5;
+                idx += len + 4; // skip 4 size bytes + content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
+            {
+                const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+                const size_t offset = current_idx + 9;
+                idx += len + 8; // skip 8 size bytes + content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x7f: // UTF-8 string (indefinite length)
+            {
+                std::string result;
+                while (v[idx] != 0xff)
+                {
+                    string_t s = from_cbor_internal(v, idx);
+                    result += s;
+                }
+                // skip break byte (0xFF)
+                idx += 1;
+                return result;
+            }
+
+            // array (0x00..0x17 data items follow)
+            case 0x80:
+            case 0x81:
+            case 0x82:
+            case 0x83:
+            case 0x84:
+            case 0x85:
+            case 0x86:
+            case 0x87:
+            case 0x88:
+            case 0x89:
+            case 0x8a:
+            case 0x8b:
+            case 0x8c:
+            case 0x8d:
+            case 0x8e:
+            case 0x8f:
+            case 0x90:
+            case 0x91:
+            case 0x92:
+            case 0x93:
+            case 0x94:
+            case 0x95:
+            case 0x96:
+            case 0x97:
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(v[current_idx] - 0x80);
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x98: // array (one-byte uint8_t for n follows)
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+                idx += 1; // skip 1 size byte
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x99: // array (two-byte uint16_t for n follow)
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                idx += 2; // skip 4 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x9a: // array (four-byte uint32_t for n follow)
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                idx += 4; // skip 4 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x9b: // array (eight-byte uint64_t for n follow)
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+                idx += 8; // skip 8 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x9f: // array (indefinite length)
+            {
+                basic_json result = value_t::array;
+                while (v[idx] != 0xff)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                // skip break byte (0xFF)
+                idx += 1;
+                return result;
+            }
+
+            // map (0x00..0x17 pairs of data items follow)
+            case 0xa0:
+            case 0xa1:
+            case 0xa2:
+            case 0xa3:
+            case 0xa4:
+            case 0xa5:
+            case 0xa6:
+            case 0xa7:
+            case 0xa8:
+            case 0xa9:
+            case 0xaa:
+            case 0xab:
+            case 0xac:
+            case 0xad:
+            case 0xae:
+            case 0xaf:
+            case 0xb0:
+            case 0xb1:
+            case 0xb2:
+            case 0xb3:
+            case 0xb4:
+            case 0xb5:
+            case 0xb6:
+            case 0xb7:
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xb8: // map (one-byte uint8_t for n follows)
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+                idx += 1; // skip 1 size byte
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xb9: // map (two-byte uint16_t for n follow)
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                idx += 2; // skip 2 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xba: // map (four-byte uint32_t for n follow)
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                idx += 4; // skip 4 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xbb: // map (eight-byte uint64_t for n follow)
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+                idx += 8; // skip 8 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xbf: // map (indefinite length)
+            {
+                basic_json result = value_t::object;
+                while (v[idx] != 0xff)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                // skip break byte (0xFF)
+                idx += 1;
+                return result;
+            }
+
+            case 0xf4: // false
+            {
+                return false;
+            }
+
+            case 0xf5: // true
+            {
+                return true;
+            }
+
+            case 0xf6: // null
+            {
+                return value_t::null;
+            }
+
+            case 0xf9: // Half-Precision Float (two-byte IEEE 754)
+            {
+                idx += 2; // skip two content bytes
+
+                // code from RFC 7049, Appendix D, Figure 3:
+                // As half-precision floating-point numbers were only added to
+                // IEEE 754 in 2008, today's programming platforms often still
+                // only have limited support for them. It is very easy to
+                // include at least decoding support for them even without such
+                // support. An example of a small decoder for half-precision
+                // floating-point numbers in the C language is shown in Fig. 3.
+                const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
+                const int exp = (half >> 10) & 0x1f;
+                const int mant = half & 0x3ff;
+                double val;
+                if (exp == 0)
+                {
+                    val = std::ldexp(mant, -24);
+                }
+                else if (exp != 31)
+                {
+                    val = std::ldexp(mant + 1024, exp - 25);
+                }
+                else
+                {
+                    val = mant == 0 ? INFINITY : NAN;
+                }
+                return half & 0x8000 ? -val : val;
+            }
+
+            case 0xfa: // Single-Precision Float (four-byte IEEE 754)
+            {
+                // copy bytes in reverse order into the float variable
+                float res;
+                for (size_t byte = 0; byte < sizeof(float); ++byte)
+                {
+                    reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
+                }
+                idx += sizeof(float); // skip content bytes
+                return res;
+            }
+
+            case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
+            {
+                // copy bytes in reverse order into the double variable
+                double res;
+                for (size_t byte = 0; byte < sizeof(double); ++byte)
+                {
+                    reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
+                }
+                idx += sizeof(double); // skip content bytes
+                return res;
+            }
+
+            default: // anything else (0xFF is handled inside the other types)
+            {
+                throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
+            }
+        }
+    }
+
+  public:
+    /*!
+    @brief create a MessagePack serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the MessagePack
+    serialization format. MessagePack is a binary serialization format which
+    aims to be more compact than JSON itself, yet more efficient to parse.
+
+    @param[in] j  JSON value to serialize
+    @return MessagePack serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in MessagePack format.,to_msgpack}
+
+    @sa http://msgpack.org
+    @sa @ref from_msgpack(const std::vector<uint8_t>&) for the analogous
+        deserialization
+    @sa @ref to_cbor(const basic_json& for the related CBOR format
+    */
+    static std::vector<uint8_t> to_msgpack(const basic_json& j)
+    {
+        std::vector<uint8_t> result;
+        to_msgpack_internal(j, result);
+        return result;
+    }
+
+    /*!
+    @brief create a JSON value from a byte vector in MessagePack format
+
+    Deserializes a given byte vector @a v to a JSON value using the MessagePack
+    serialization format.
+
+    @param[in] v  a byte vector in MessagePack format
+    @return deserialized JSON value
+
+    @throw std::invalid_argument if unsupported features from MessagePack were
+    used in the given vector @a v or if the input is not valid MessagePack
+    @throw std::out_of_range if the given vector ends prematurely
+
+    @complexity Linear in the size of the byte vector @a v.
+
+    @liveexample{The example shows the deserialization of a byte vector in
+    MessagePack format to a JSON value.,from_msgpack}
+
+    @sa http://msgpack.org
+    @sa @ref to_msgpack(const basic_json&) for the analogous serialization
+    @sa @ref from_cbor(const std::vector<uint8_t>&) for the related CBOR format
+    */
+    static basic_json from_msgpack(const std::vector<uint8_t>& v)
+    {
+        size_t i = 0;
+        return from_msgpack_internal(v, i);
+    }
+
+    /*!
+    @brief create a MessagePack serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
+    Binary Object Representation) serialization format. CBOR is a binary
+    serialization format which aims to be more compact than JSON itself, yet
+    more efficient to parse.
+
+    @param[in] j  JSON value to serialize
+    @return MessagePack serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in CBOR format.,to_cbor}
+
+    @sa http://cbor.io
+    @sa @ref from_cbor(const std::vector<uint8_t>&) for the analogous
+        deserialization
+    @sa @ref to_msgpack(const basic_json& for the related MessagePack format
+    */
+    static std::vector<uint8_t> to_cbor(const basic_json& j)
+    {
+        std::vector<uint8_t> result;
+        to_cbor_internal(j, result);
+        return result;
+    }
+
+    /*!
+    @brief create a JSON value from a byte vector in CBOR format
+
+    Deserializes a given byte vector @a v to a JSON value using the CBOR
+    (Concise Binary Object Representation) serialization format.
+
+    @param[in] v  a byte vector in CBOR format
+    @return deserialized JSON value
+
+    @throw std::invalid_argument if unsupported features from CBOR were used in
+    the given vector @a v or if the input is not valid MessagePack
+    @throw std::out_of_range if the given vector ends prematurely
+
+    @complexity Linear in the size of the byte vector @a v.
+
+    @liveexample{The example shows the deserialization of a byte vector in CBOR
+    format to a JSON value.,from_cbor}
+
+    @sa http://cbor.io
+    @sa @ref to_cbor(const basic_json&) for the analogous serialization
+    @sa @ref from_msgpack(const std::vector<uint8_t>&) for the related
+        MessagePack format
+    */
+    static basic_json from_cbor(const std::vector<uint8_t>& v)
+    {
+        size_t i = 0;
+        return from_cbor_internal(v, i);
+    }
+
+    /// @}
 
   private:
     ///////////////////////////
@@ -6769,10 +8205,10 @@
 
   public:
     /*!
-    @brief a const random access iterator for the @ref basic_json class
+    @brief a template for a random access iterator for the @ref basic_json class
 
-    This class implements a const iterator for the @ref basic_json class. From
-    this class, the @ref iterator class is derived.
+    This class implements a both iterators (iterator and const_iterator) for the
+    @ref basic_json class.
 
     @note An iterator is called *initialized* when a pointer to a JSON value
           has been set (e.g., by a constructor or a copy assignment). If the
@@ -6785,27 +8221,37 @@
       The iterator that can be moved to point (forward and backward) to any
       element in constant time.
 
-    @since version 1.0.0
+    @since version 1.0.0, simplified in version 2.0.9
     */
-    class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
+    template<typename U>
+    class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
     {
         /// allow basic_json to access private members
         friend class basic_json;
 
+        // make sure U is basic_json or const basic_json
+        static_assert(std::is_same<U, basic_json>::value
+                      or std::is_same<U, const basic_json>::value,
+                      "iter_impl only accepts (const) basic_json");
+
       public:
         /// the type of the values when the iterator is dereferenced
         using value_type = typename basic_json::value_type;
         /// a type to represent differences between iterators
         using difference_type = typename basic_json::difference_type;
         /// defines a pointer to the type iterated over (value_type)
-        using pointer = typename basic_json::const_pointer;
+        using pointer = typename std::conditional<std::is_const<U>::value,
+              typename basic_json::const_pointer,
+              typename basic_json::pointer>::type;
         /// defines a reference to the type iterated over (value_type)
-        using reference = typename basic_json::const_reference;
+        using reference = typename std::conditional<std::is_const<U>::value,
+              typename basic_json::const_reference,
+              typename basic_json::reference>::type;
         /// the category of the iterator
         using iterator_category = std::bidirectional_iterator_tag;
 
         /// default constructor
-        const_iterator() = default;
+        iter_impl() = default;
 
         /*!
         @brief constructor for a given JSON instance
@@ -6813,7 +8259,7 @@
         @pre object != nullptr
         @post The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        explicit const_iterator(pointer object) noexcept
+        explicit iter_impl(pointer object) noexcept
             : m_object(object)
         {
             assert(m_object != nullptr);
@@ -6840,37 +8286,25 @@
             }
         }
 
-        /*!
-        @brief copy constructor given a non-const iterator
-        @param[in] other  iterator to copy from
-        @note It is not checked whether @a other is initialized.
+        /*
+        Use operator `const_iterator` instead of `const_iterator(const iterator&
+        other) noexcept` to avoid two class definitions for @ref iterator and
+        @ref const_iterator.
+
+        This function is only called if this class is an @ref iterator. If this
+        class is a @ref const_iterator this function is not called.
         */
-        explicit const_iterator(const iterator& other) noexcept
-            : m_object(other.m_object)
+        operator const_iterator() const
         {
-            if (m_object != nullptr)
+            const_iterator ret;
+
+            if (m_object)
             {
-                switch (m_object->m_type)
-                {
-                    case basic_json::value_t::object:
-                    {
-                        m_it.object_iterator = other.m_it.object_iterator;
-                        break;
-                    }
-
-                    case basic_json::value_t::array:
-                    {
-                        m_it.array_iterator = other.m_it.array_iterator;
-                        break;
-                    }
-
-                    default:
-                    {
-                        m_it.primitive_iterator = other.m_it.primitive_iterator;
-                        break;
-                    }
-                }
+                ret.m_object = m_object;
+                ret.m_it = m_it;
             }
+
+            return ret;
         }
 
         /*!
@@ -6878,7 +8312,7 @@
         @param[in] other  iterator to copy from
         @note It is not checked whether @a other is initialized.
         */
-        const_iterator(const const_iterator& other) noexcept
+        iter_impl(const iter_impl& other) noexcept
             : m_object(other.m_object), m_it(other.m_it)
         {}
 
@@ -6887,7 +8321,7 @@
         @param[in,out] other  iterator to copy from
         @note It is not checked whether @a other is initialized.
         */
-        const_iterator& operator=(const_iterator other) noexcept(
+        iter_impl& operator=(iter_impl other) noexcept(
             std::is_nothrow_move_constructible<pointer>::value and
             std::is_nothrow_move_assignable<pointer>::value and
             std::is_nothrow_move_constructible<internal_iterator>::value and
@@ -7049,7 +8483,7 @@
         @brief post-increment (it++)
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator operator++(int)
+        iter_impl operator++(int)
         {
             auto result = *this;
             ++(*this);
@@ -7060,7 +8494,7 @@
         @brief pre-increment (++it)
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator& operator++()
+        iter_impl& operator++()
         {
             assert(m_object != nullptr);
 
@@ -7092,7 +8526,7 @@
         @brief post-decrement (it--)
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator operator--(int)
+        iter_impl operator--(int)
         {
             auto result = *this;
             --(*this);
@@ -7103,7 +8537,7 @@
         @brief pre-decrement (--it)
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator& operator--()
+        iter_impl& operator--()
         {
             assert(m_object != nullptr);
 
@@ -7135,7 +8569,7 @@
         @brief  comparison: equal
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator==(const const_iterator& other) const
+        bool operator==(const iter_impl& other) const
         {
             // if objects are not the same, the comparison is undefined
             if (m_object != other.m_object)
@@ -7168,7 +8602,7 @@
         @brief  comparison: not equal
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator!=(const const_iterator& other) const
+        bool operator!=(const iter_impl& other) const
         {
             return not operator==(other);
         }
@@ -7177,7 +8611,7 @@
         @brief  comparison: smaller
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator<(const const_iterator& other) const
+        bool operator<(const iter_impl& other) const
         {
             // if objects are not the same, the comparison is undefined
             if (m_object != other.m_object)
@@ -7210,7 +8644,7 @@
         @brief  comparison: less than or equal
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator<=(const const_iterator& other) const
+        bool operator<=(const iter_impl& other) const
         {
             return not other.operator < (*this);
         }
@@ -7219,7 +8653,7 @@
         @brief  comparison: greater than
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator>(const const_iterator& other) const
+        bool operator>(const iter_impl& other) const
         {
             return not operator<=(other);
         }
@@ -7228,7 +8662,7 @@
         @brief  comparison: greater than or equal
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator>=(const const_iterator& other) const
+        bool operator>=(const iter_impl& other) const
         {
             return not operator<(other);
         }
@@ -7237,7 +8671,7 @@
         @brief  add to iterator
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator& operator+=(difference_type i)
+        iter_impl& operator+=(difference_type i)
         {
             assert(m_object != nullptr);
 
@@ -7268,7 +8702,7 @@
         @brief  subtract from iterator
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator& operator-=(difference_type i)
+        iter_impl& operator-=(difference_type i)
         {
             return operator+=(-i);
         }
@@ -7277,7 +8711,7 @@
         @brief  add to iterator
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator operator+(difference_type i)
+        iter_impl operator+(difference_type i)
         {
             auto result = *this;
             result += i;
@@ -7288,7 +8722,7 @@
         @brief  subtract from iterator
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator operator-(difference_type i)
+        iter_impl operator-(difference_type i)
         {
             auto result = *this;
             result -= i;
@@ -7299,7 +8733,7 @@
         @brief  return difference
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        difference_type operator-(const const_iterator& other) const
+        difference_type operator-(const iter_impl& other) const
         {
             assert(m_object != nullptr);
 
@@ -7396,141 +8830,6 @@
     };
 
     /*!
-    @brief a mutable random access iterator for the @ref basic_json class
-
-    @requirement The class satisfies the following concept requirements:
-    - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
-      The iterator that can be moved to point (forward and backward) to any
-      element in constant time.
-    - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
-      It is possible to write to the pointed-to element.
-
-    @since version 1.0.0
-    */
-    class iterator : public const_iterator
-    {
-      public:
-        using base_iterator = const_iterator;
-        using pointer = typename basic_json::pointer;
-        using reference = typename basic_json::reference;
-
-        /// default constructor
-        iterator() = default;
-
-        /// constructor for a given JSON instance
-        explicit iterator(pointer object) noexcept
-            : base_iterator(object)
-        {}
-
-        /// copy constructor
-        iterator(const iterator& other) noexcept
-            : base_iterator(other)
-        {}
-
-        /// copy assignment
-        iterator& operator=(iterator other) noexcept(
-            std::is_nothrow_move_constructible<pointer>::value and
-            std::is_nothrow_move_assignable<pointer>::value and
-            std::is_nothrow_move_constructible<internal_iterator>::value and
-            std::is_nothrow_move_assignable<internal_iterator>::value
-        )
-        {
-            base_iterator::operator=(other);
-            return *this;
-        }
-
-        /// return a reference to the value pointed to by the iterator
-        reference operator*() const
-        {
-            return const_cast<reference>(base_iterator::operator*());
-        }
-
-        /// dereference the iterator
-        pointer operator->() const
-        {
-            return const_cast<pointer>(base_iterator::operator->());
-        }
-
-        /// post-increment (it++)
-        iterator operator++(int)
-        {
-            iterator result = *this;
-            base_iterator::operator++();
-            return result;
-        }
-
-        /// pre-increment (++it)
-        iterator& operator++()
-        {
-            base_iterator::operator++();
-            return *this;
-        }
-
-        /// post-decrement (it--)
-        iterator operator--(int)
-        {
-            iterator result = *this;
-            base_iterator::operator--();
-            return result;
-        }
-
-        /// pre-decrement (--it)
-        iterator& operator--()
-        {
-            base_iterator::operator--();
-            return *this;
-        }
-
-        /// add to iterator
-        iterator& operator+=(difference_type i)
-        {
-            base_iterator::operator+=(i);
-            return *this;
-        }
-
-        /// subtract from iterator
-        iterator& operator-=(difference_type i)
-        {
-            base_iterator::operator-=(i);
-            return *this;
-        }
-
-        /// add to iterator
-        iterator operator+(difference_type i)
-        {
-            auto result = *this;
-            result += i;
-            return result;
-        }
-
-        /// subtract from iterator
-        iterator operator-(difference_type i)
-        {
-            auto result = *this;
-            result -= i;
-            return result;
-        }
-
-        /// return difference
-        difference_type operator-(const iterator& other) const
-        {
-            return base_iterator::operator-(other);
-        }
-
-        /// access to successor
-        reference operator[](difference_type n) const
-        {
-            return const_cast<reference>(base_iterator::operator[](n));
-        }
-
-        /// return the value of an iterator
-        reference value() const
-        {
-            return const_cast<reference>(base_iterator::value());
-        }
-    };
-
-    /*!
     @brief a template for a reverse iterator class
 
     @tparam Base the base iterator type to reverse. Valid types are @ref
@@ -9068,8 +10367,6 @@
         supplied via the first parameter.  Set this to @a
         static_cast<number_float_t*>(nullptr).
 
-        @param[in] type  the @ref number_float_t in use
-
         @param[in,out] endptr recieves a pointer to the first character after
         the number
 
@@ -9088,8 +10385,6 @@
         supplied via the first parameter.  Set this to @a
         static_cast<number_float_t*>(nullptr).
 
-        @param[in] type  the @ref number_float_t in use
-
         @param[in,out] endptr  recieves a pointer to the first character after
         the number
 
@@ -9108,8 +10403,6 @@
         supplied via the first parameter.  Set this to @a
         static_cast<number_float_t*>(nullptr).
 
-        @param[in] type  the @ref number_float_t in use
-
         @param[in,out] endptr  recieves a pointer to the first character after
         the number
 
@@ -9190,19 +10483,19 @@
                 // skip if definitely not an integer
                 if (type != value_t::number_float)
                 {
-                    // multiply last value by ten and add the new digit
-                    auto temp = value * 10 + *curptr - '0';
+                    auto digit = static_cast<number_unsigned_t>(*curptr - '0');
 
-                    // test for overflow
-                    if (temp < value || temp > max)
+                    // overflow if value * 10 + digit > max, move terms around
+                    // to avoid overflow in intermediate values
+                    if (value > (max - digit) / 10)
                     {
                         // overflow
                         type = value_t::number_float;
                     }
                     else
                     {
-                        // no overflow - save it
-                        value = temp;
+                        // no overflow
+                        value = value * 10 + digit;
                     }
                 }
             }
@@ -9214,7 +10507,22 @@
             }
             else if (type == value_t::number_integer)
             {
-                result.m_value.number_integer = -static_cast<number_integer_t>(value);
+                // invariant: if we parsed a '-', the absolute value is between
+                // 0 (we allow -0) and max == -INT64_MIN
+                assert(value >= 0);
+                assert(value <= max);
+
+                if (value == max)
+                {
+                    // we cannot simply negate value (== max == -INT64_MIN),
+                    // see https://github.com/nlohmann/json/issues/389
+                    result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN);
+                }
+                else
+                {
+                    // all other values can be negated safely
+                    result.m_value.number_integer = -static_cast<number_integer_t>(value);
+                }
             }
             else
             {
@@ -9997,13 +11305,11 @@
         /*!
         @brief replace all occurrences of a substring by another string
 
-        @param[in,out] s  the string to manipulate
+        @param[in,out] s  the string to manipulate; changed so that all
+                          occurrences of @a f are replaced with @a t
         @param[in]     f  the substring to replace with @a t
         @param[in]     t  the string to replace @a f
 
-        @return The string @a s where all occurrences of @a f are replaced
-                with @a t.
-
         @pre The search string @a f must not be empty.
 
         @since version 2.0.0
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index c6a99b8..ac9a331 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -34,7 +34,7 @@
 #include <cassert> // assert
 #include <cctype> // isdigit
 #include <ciso646> // and, not, or
-#include <cmath> // isfinite, signbit
+#include <cmath> // isfinite, ldexp, signbit
 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
 #include <cstdint> // int64_t, uint64_t
 #include <cstdlib> // strtod, strtof, strtold, strtoul
@@ -75,6 +75,12 @@
     #pragma GCC diagnostic ignored "-Wfloat-equal"
 #endif
 
+// disable documentation warnings on clang
+#if defined(__clang__)
+    #pragma GCC diagnostic push
+    #pragma GCC diagnostic ignored "-Wdocumentation"
+#endif
+
 // allow for portable deprecation warnings
 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
     #define JSON_DEPRECATED __attribute__((deprecated))
@@ -222,6 +228,7 @@
 
   public:
     // forward declarations
+    template<typename U> class iter_impl;
     template<typename Base> class json_reverse_iterator;
     class json_pointer;
 
@@ -256,9 +263,9 @@
     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
 
     /// an iterator for a basic_json container
-    class iterator;
+    using iterator = iter_impl<basic_json>;
     /// a const iterator for a basic_json container
-    class const_iterator;
+    using const_iterator = iter_impl<const basic_json>;
     /// a reverse iterator for a basic_json container
     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
     /// a const reverse iterator for a basic_json container
@@ -944,7 +951,7 @@
 
     With a parser callback function, the result of parsing a JSON text can be
     influenced. When passed to @ref parse(std::istream&, const
-    parser_callback_t) or @ref parse(const char*, const parser_callback_t),
+    parser_callback_t) or @ref parse(const CharT, const parser_callback_t),
     it is called on certain events (passed as @ref parse_event_t via parameter
     @a event) with a set recursion depth @a depth and context JSON value
     @a parsed. The return value of the callback function is a boolean
@@ -987,7 +994,7 @@
     skipped completely or replaced by an empty discarded object.
 
     @sa @ref parse(std::istream&, parser_callback_t) or
-    @ref parse(const char*, parser_callback_t) for examples
+    @ref parse(const CharT, const parser_callback_t) for examples
 
     @since version 1.0.0
     */
@@ -6003,11 +6010,11 @@
 
     @since version 1.0.0 (originally for @ref string_t)
     */
-    template<typename CharPT, typename std::enable_if<
-                 std::is_pointer<CharPT>::value and
-                 std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
-                 sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
-    static basic_json parse(const CharPT s,
+    template<typename CharT, typename std::enable_if<
+                 std::is_pointer<CharT>::value and
+                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
+                 sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
+    static basic_json parse(const CharT s,
                             const parser_callback_t cb = nullptr)
     {
         return parser(reinterpret_cast<const char*>(s), cb).parse();
@@ -6032,7 +6039,7 @@
     @liveexample{The example below demonstrates the `parse()` function with
     and without callback function.,parse__istream__parser_callback_t}
 
-    @sa @ref parse(const char*, const parser_callback_t) for a version
+    @sa @ref parse(const CharT, const parser_callback_t) for a version
     that reads from a string
 
     @since version 1.0.0
@@ -6217,6 +6224,1435 @@
 
     /// @}
 
+    //////////////////////////////////////////
+    // binary serialization/deserialization //
+    //////////////////////////////////////////
+
+    /// @name binary serialization/deserialization support
+    /// @{
+
+  private:
+    template<typename T>
+    static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
+    {
+        assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
+
+        switch (bytes)
+        {
+            case 8:
+            {
+                vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
+                vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
+                vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
+                vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
+                // intentional fall-through
+            }
+
+            case 4:
+            {
+                vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
+                vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
+                // intentional fall-through
+            }
+
+            case 2:
+            {
+                vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
+                // intentional fall-through
+            }
+
+            case 1:
+            {
+                vec.push_back(static_cast<uint8_t>(number & 0xff));
+                break;
+            }
+        }
+    }
+
+    /*!
+    @brief take sufficient bytes from a vector to fill an integer variable
+
+    In the context of binary serialization formats, we need to read several
+    bytes from a byte vector and combine them to multi-byte integral data
+    types.
+
+    @param[in] vec  byte vector to read from
+    @param[in] current_index  the position in the vector after which to read
+
+    @return the next sizeof(T) bytes from @a vec, in reverse order as T
+
+    @tparam T the integral return type
+
+    @throw std::out_of_range if there are less than sizeof(T)+1 bytes in the
+           vector @a vec to read
+
+    In the for loop, the bytes from the vector are copied in reverse order into
+    the return value. In the figures below, let sizeof(T)=4 and `i` be the loop
+    variable.
+
+    Precondition:
+
+    vec:   |   |   | a | b | c | d |      T: |   |   |   |   |
+                 ^               ^             ^                ^
+           current_index         i            ptr        sizeof(T)
+
+    Postcondition:
+
+    vec:   |   |   | a | b | c | d |      T: | d | c | b | a |
+                 ^   ^                                     ^
+                 |   i                                    ptr
+           current_index
+
+    @sa Code adapted from <http://stackoverflow.com/a/41031865/266378>.
+    */
+    template<typename T>
+    static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
+    {
+        if (current_index + sizeof(T) + 1 > vec.size())
+        {
+            throw std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector");
+        }
+
+        T result;
+        uint8_t* ptr = reinterpret_cast<uint8_t*>(&result);
+        for (size_t i = 0; i < sizeof(T); ++i)
+        {
+            *ptr++ = vec[current_index + sizeof(T) - i];
+        }
+        return result;
+    }
+
+    /*!
+    @brief create a MessagePack serialization of a given JSON value
+
+    This is a straightforward implementation of the MessagePack specification.
+
+    @param[in] j  JSON value to serialize
+    @param[in,out] v  byte vector to write the serialization to
+
+    @sa https://github.com/msgpack/msgpack/blob/master/spec.md
+    */
+    static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                // nil
+                v.push_back(0xc0);
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                // true and false
+                v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // MessagePack does not differentiate between positive
+                    // signed integers and unsigned integers. Therefore, we used
+                    // the code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_unsigned < 128)
+                    {
+                        // positive fixnum
+                        add_to_vector(v, 1, j.m_value.number_unsigned);
+                    }
+                    else if (j.m_value.number_unsigned <= UINT8_MAX)
+                    {
+                        // uint 8
+                        v.push_back(0xcc);
+                        add_to_vector(v, 1, j.m_value.number_unsigned);
+                    }
+                    else if (j.m_value.number_unsigned <= UINT16_MAX)
+                    {
+                        // uint 16
+                        v.push_back(0xcd);
+                        add_to_vector(v, 2, j.m_value.number_unsigned);
+                    }
+                    else if (j.m_value.number_unsigned <= UINT32_MAX)
+                    {
+                        // uint 32
+                        v.push_back(0xce);
+                        add_to_vector(v, 4, j.m_value.number_unsigned);
+                    }
+                    else if (j.m_value.number_unsigned <= UINT64_MAX)
+                    {
+                        // uint 64
+                        v.push_back(0xcf);
+                        add_to_vector(v, 8, j.m_value.number_unsigned);
+                    }
+                }
+                else
+                {
+                    if (j.m_value.number_integer >= -32)
+                    {
+                        // negative fixnum
+                        add_to_vector(v, 1, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
+                    {
+                        // int 8
+                        v.push_back(0xd0);
+                        add_to_vector(v, 1, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
+                    {
+                        // int 16
+                        v.push_back(0xd1);
+                        add_to_vector(v, 2, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
+                    {
+                        // int 32
+                        v.push_back(0xd2);
+                        add_to_vector(v, 4, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
+                    {
+                        // int 64
+                        v.push_back(0xd3);
+                        add_to_vector(v, 8, j.m_value.number_integer);
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned < 128)
+                {
+                    // positive fixnum
+                    add_to_vector(v, 1, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= UINT8_MAX)
+                {
+                    // uint 8
+                    v.push_back(0xcc);
+                    add_to_vector(v, 1, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= UINT16_MAX)
+                {
+                    // uint 16
+                    v.push_back(0xcd);
+                    add_to_vector(v, 2, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= UINT32_MAX)
+                {
+                    // uint 32
+                    v.push_back(0xce);
+                    add_to_vector(v, 4, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= UINT64_MAX)
+                {
+                    // uint 64
+                    v.push_back(0xcf);
+                    add_to_vector(v, 8, j.m_value.number_unsigned);
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                // float 64
+                v.push_back(0xcb);
+                const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
+                for (size_t i = 0; i < 8; ++i)
+                {
+                    v.push_back(helper[7 - i]);
+                }
+                break;
+            }
+
+            case value_t::string:
+            {
+                const auto N = j.m_value.string->size();
+                if (N <= 31)
+                {
+                    // fixstr
+                    v.push_back(static_cast<uint8_t>(0xa0 | N));
+                }
+                else if (N <= 255)
+                {
+                    // str 8
+                    v.push_back(0xd9);
+                    add_to_vector(v, 1, N);
+                }
+                else if (N <= 65535)
+                {
+                    // str 16
+                    v.push_back(0xda);
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 4294967295)
+                {
+                    // str 32
+                    v.push_back(0xdb);
+                    add_to_vector(v, 4, N);
+                }
+
+                // append string
+                std::copy(j.m_value.string->begin(), j.m_value.string->end(),
+                          std::back_inserter(v));
+                break;
+            }
+
+            case value_t::array:
+            {
+                const auto N = j.m_value.array->size();
+                if (N <= 15)
+                {
+                    // fixarray
+                    v.push_back(static_cast<uint8_t>(0x90 | N));
+                }
+                else if (N <= 0xffff)
+                {
+                    // array 16
+                    v.push_back(0xdc);
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 0xffffffff)
+                {
+                    // array 32
+                    v.push_back(0xdd);
+                    add_to_vector(v, 4, N);
+                }
+
+                // append each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    to_msgpack_internal(el, v);
+                }
+                break;
+            }
+
+            case value_t::object:
+            {
+                const auto N = j.m_value.object->size();
+                if (N <= 15)
+                {
+                    // fixmap
+                    v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
+                }
+                else if (N <= 65535)
+                {
+                    // map 16
+                    v.push_back(0xde);
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 4294967295)
+                {
+                    // map 32
+                    v.push_back(0xdf);
+                    add_to_vector(v, 4, N);
+                }
+
+                // append each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    to_msgpack_internal(el.first, v);
+                    to_msgpack_internal(el.second, v);
+                }
+                break;
+            }
+
+            default:
+            {
+                break;
+            }
+        }
+    }
+
+    /*!
+    @brief create a CBOR serialization of a given JSON value
+
+    This is a straightforward implementation of the CBOR specification.
+
+    @param[in] j  JSON value to serialize
+    @param[in,out] v  byte vector to write the serialization to
+
+    @sa https://tools.ietf.org/html/rfc7049
+    */
+    static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                v.push_back(0xf6);
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // CBOR does not differentiate between positive signed
+                    // integers and unsigned integers. Therefore, we used the
+                    // code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_integer <= 0x17)
+                    {
+                        add_to_vector(v, 1, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer <= UINT8_MAX)
+                    {
+                        v.push_back(0x18);
+                        // one-byte uint8_t
+                        add_to_vector(v, 1, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer <= UINT16_MAX)
+                    {
+                        v.push_back(0x19);
+                        // two-byte uint16_t
+                        add_to_vector(v, 2, j.m_value.number_integer);
+                    }
+                    else if (j.m_value.number_integer <= UINT32_MAX)
+                    {
+                        v.push_back(0x1a);
+                        // four-byte uint32_t
+                        add_to_vector(v, 4, j.m_value.number_integer);
+                    }
+                    else
+                    {
+                        v.push_back(0x1b);
+                        // eight-byte uint64_t
+                        add_to_vector(v, 8, j.m_value.number_integer);
+                    }
+                }
+                else
+                {
+                    // The conversions below encode the sign in the first byte,
+                    // and the value is converted to a positive number.
+                    const auto positive_number = -1 - j.m_value.number_integer;
+                    if (j.m_value.number_integer >= -24)
+                    {
+                        v.push_back(static_cast<uint8_t>(0x20 + positive_number));
+                    }
+                    else if (positive_number <= UINT8_MAX)
+                    {
+                        // int 8
+                        v.push_back(0x38);
+                        add_to_vector(v, 1, positive_number);
+                    }
+                    else if (positive_number <= UINT16_MAX)
+                    {
+                        // int 16
+                        v.push_back(0x39);
+                        add_to_vector(v, 2, positive_number);
+                    }
+                    else if (positive_number <= UINT32_MAX)
+                    {
+                        // int 32
+                        v.push_back(0x3a);
+                        add_to_vector(v, 4, positive_number);
+                    }
+                    else
+                    {
+                        // int 64
+                        v.push_back(0x3b);
+                        add_to_vector(v, 8, positive_number);
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned <= 0x17)
+                {
+                    v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= 0xff)
+                {
+                    v.push_back(0x18);
+                    // one-byte uint8_t
+                    add_to_vector(v, 1, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= 0xffff)
+                {
+                    v.push_back(0x19);
+                    // two-byte uint16_t
+                    add_to_vector(v, 2, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= 0xffffffff)
+                {
+                    v.push_back(0x1a);
+                    // four-byte uint32_t
+                    add_to_vector(v, 4, j.m_value.number_unsigned);
+                }
+                else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
+                {
+                    v.push_back(0x1b);
+                    // eight-byte uint64_t
+                    add_to_vector(v, 8, j.m_value.number_unsigned);
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                // Double-Precision Float
+                v.push_back(0xfb);
+                const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
+                for (size_t i = 0; i < 8; ++i)
+                {
+                    v.push_back(helper[7 - i]);
+                }
+                break;
+            }
+
+            case value_t::string:
+            {
+                const auto N = j.m_value.string->size();
+                if (N <= 0x17)
+                {
+                    v.push_back(0x60 + N);  // 1 byte for string + size
+                }
+                else if (N <= 0xff)
+                {
+                    v.push_back(0x78);  // one-byte uint8_t for N
+                    add_to_vector(v, 1, N);
+                }
+                else if (N <= 0xffff)
+                {
+                    v.push_back(0x79);  // two-byte uint16_t for N
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 0xffffffff)
+                {
+                    v.push_back(0x7a); // four-byte uint32_t for N
+                    add_to_vector(v, 4, N);
+                }
+                // LCOV_EXCL_START
+                else if (N <= 0xffffffffffffffff)
+                {
+                    v.push_back(0x7b);  // eight-byte uint64_t for N
+                    add_to_vector(v, 8, N);
+                }
+                // LCOV_EXCL_STOP
+
+                // append string
+                std::copy(j.m_value.string->begin(), j.m_value.string->end(),
+                          std::back_inserter(v));
+                break;
+            }
+
+            case value_t::array:
+            {
+                const auto N = j.m_value.array->size();
+                if (N <= 0x17)
+                {
+                    v.push_back(0x80 + N);  // 1 byte for array + size
+                }
+                else if (N <= 0xff)
+                {
+                    v.push_back(0x98);  // one-byte uint8_t for N
+                    add_to_vector(v, 1, N);
+                }
+                else if (N <= 0xffff)
+                {
+                    v.push_back(0x99);  // two-byte uint16_t for N
+                    add_to_vector(v, 2, N);
+                }
+                else if (N <= 0xffffffff)
+                {
+                    v.push_back(0x9a);  // four-byte uint32_t for N
+                    add_to_vector(v, 4, N);
+                }
+                // LCOV_EXCL_START
+                else if (N <= 0xffffffffffffffff)
+                {
+                    v.push_back(0x9b);  // eight-byte uint64_t for N
+                    add_to_vector(v, 8, N);
+                }
+                // LCOV_EXCL_STOP
+
+                // append each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    to_cbor_internal(el, v);
+                }
+                break;
+            }
+
+            case value_t::object:
+            {
+                const auto N = j.m_value.object->size();
+                if (N <= 0x17)
+                {
+                    v.push_back(0xa0 + N);  // 1 byte for object + size
+                }
+                else if (N <= 0xff)
+                {
+                    v.push_back(0xb8);
+                    add_to_vector(v, 1, N);  // one-byte uint8_t for N
+                }
+                else if (N <= 0xffff)
+                {
+                    v.push_back(0xb9);
+                    add_to_vector(v, 2, N);  // two-byte uint16_t for N
+                }
+                else if (N <= 0xffffffff)
+                {
+                    v.push_back(0xba);
+                    add_to_vector(v, 4, N);  // four-byte uint32_t for N
+                }
+                // LCOV_EXCL_START
+                else if (N <= 0xffffffffffffffff)
+                {
+                    v.push_back(0xbb);
+                    add_to_vector(v, 8, N);  // eight-byte uint64_t for N
+                }
+                // LCOV_EXCL_STOP
+
+                // append each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    to_cbor_internal(el.first, v);
+                    to_cbor_internal(el.second, v);
+                }
+                break;
+            }
+
+            default:
+            {
+                break;
+            }
+        }
+    }
+
+    /*!
+    @brief create a JSON value from a given MessagePack vector
+
+    @param[in] v  MessagePack serialization
+    @param[in] idx  byte index to start reading from @a v
+
+    @return deserialized JSON value
+
+    @throw std::invalid_argument if unsupported features from MessagePack were
+    used in the given vector @a v or if the input is not valid MessagePack
+    @throw std::out_of_range if the given vector ends prematurely
+
+    @sa https://github.com/msgpack/msgpack/blob/master/spec.md
+    */
+    static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
+    {
+        // store and increment index
+        const size_t current_idx = idx++;
+
+        if (v[current_idx] <= 0xbf)
+        {
+            if (v[current_idx] <= 0x7f) // positive fixint
+            {
+                return v[current_idx];
+            }
+            else if (v[current_idx] <= 0x8f) // fixmap
+            {
+                basic_json result = value_t::object;
+                const size_t len = v[current_idx] & 0x0f;
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_msgpack_internal(v, idx);
+                    result[key] = from_msgpack_internal(v, idx);
+                }
+                return result;
+            }
+            else if (v[current_idx] <= 0x9f) // fixarray
+            {
+                basic_json result = value_t::array;
+                const size_t len = v[current_idx] & 0x0f;
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_msgpack_internal(v, idx));
+                }
+                return result;
+            }
+            else // fixstr
+            {
+                const size_t len = v[current_idx] & 0x1f;
+                const size_t offset = current_idx + 1;
+                idx += len; // skip content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+        }
+        else if (v[current_idx] >= 0xe0) // negative fixint
+        {
+            return static_cast<int8_t>(v[current_idx]);
+        }
+        else
+        {
+            switch (v[current_idx])
+            {
+                case 0xc0: // nil
+                {
+                    return value_t::null;
+                }
+
+                case 0xc2: // false
+                {
+                    return false;
+                }
+
+                case 0xc3: // true
+                {
+                    return true;
+                }
+
+                case 0xca: // float 32
+                {
+                    // copy bytes in reverse order into the double variable
+                    float res;
+                    for (size_t byte = 0; byte < sizeof(float); ++byte)
+                    {
+                        reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
+                    }
+                    idx += sizeof(float); // skip content bytes
+                    return res;
+                }
+
+                case 0xcb: // float 64
+                {
+                    // copy bytes in reverse order into the double variable
+                    double res;
+                    for (size_t byte = 0; byte < sizeof(double); ++byte)
+                    {
+                        reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
+                    }
+                    idx += sizeof(double); // skip content bytes
+                    return res;
+                }
+
+                case 0xcc: // uint 8
+                {
+                    idx += 1; // skip content byte
+                    return get_from_vector<uint8_t>(v, current_idx);
+                }
+
+                case 0xcd: // uint 16
+                {
+                    idx += 2; // skip 2 content bytes
+                    return get_from_vector<uint16_t>(v, current_idx);
+                }
+
+                case 0xce: // uint 32
+                {
+                    idx += 4; // skip 4 content bytes
+                    return get_from_vector<uint32_t>(v, current_idx);
+                }
+
+                case 0xcf: // uint 64
+                {
+                    idx += 8; // skip 8 content bytes
+                    return get_from_vector<uint64_t>(v, current_idx);
+                }
+
+                case 0xd0: // int 8
+                {
+                    idx += 1; // skip content byte
+                    return get_from_vector<int8_t>(v, current_idx);
+                }
+
+                case 0xd1: // int 16
+                {
+                    idx += 2; // skip 2 content bytes
+                    return get_from_vector<int16_t>(v, current_idx);
+                }
+
+                case 0xd2: // int 32
+                {
+                    idx += 4; // skip 4 content bytes
+                    return get_from_vector<int32_t>(v, current_idx);
+                }
+
+                case 0xd3: // int 64
+                {
+                    idx += 8; // skip 8 content bytes
+                    return get_from_vector<int64_t>(v, current_idx);
+                }
+
+                case 0xd9: // str 8
+                {
+                    const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+                    const size_t offset = current_idx + 2;
+                    idx += len + 1; // skip size byte + content bytes
+                    return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+                }
+
+                case 0xda: // str 16
+                {
+                    const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                    const size_t offset = current_idx + 3;
+                    idx += len + 2; // skip 2 size bytes + content bytes
+                    return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+                }
+
+                case 0xdb: // str 32
+                {
+                    const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                    const size_t offset = current_idx + 5;
+                    idx += len + 4; // skip 4 size bytes + content bytes
+                    return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+                }
+
+                case 0xdc: // array 16
+                {
+                    basic_json result = value_t::array;
+                    const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                    idx += 2; // skip 2 size bytes
+                    for (size_t i = 0; i < len; ++i)
+                    {
+                        result.push_back(from_msgpack_internal(v, idx));
+                    }
+                    return result;
+                }
+
+                case 0xdd: // array 32
+                {
+                    basic_json result = value_t::array;
+                    const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                    idx += 4; // skip 4 size bytes
+                    for (size_t i = 0; i < len; ++i)
+                    {
+                        result.push_back(from_msgpack_internal(v, idx));
+                    }
+                    return result;
+                }
+
+                case 0xde: // map 16
+                {
+                    basic_json result = value_t::object;
+                    const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                    idx += 2; // skip 2 size bytes
+                    for (size_t i = 0; i < len; ++i)
+                    {
+                        std::string key = from_msgpack_internal(v, idx);
+                        result[key] = from_msgpack_internal(v, idx);
+                    }
+                    return result;
+                }
+
+                case 0xdf: // map 32
+                {
+                    basic_json result = value_t::object;
+                    const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                    idx += 4; // skip 4 size bytes
+                    for (size_t i = 0; i < len; ++i)
+                    {
+                        std::string key = from_msgpack_internal(v, idx);
+                        result[key] = from_msgpack_internal(v, idx);
+                    }
+                    return result;
+                }
+
+                default:
+                {
+                    throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
+                }
+            }
+        }
+    }
+
+    /*!
+    @brief create a JSON value from a given CBOR vector
+
+    @param[in] v  CBOR serialization
+    @param[in] idx  byte index to start reading from @a v
+
+    @return deserialized JSON value
+
+    @throw std::invalid_argument if unsupported features from CBOR were used in
+    the given vector @a v or if the input is not valid CBOR
+    @throw std::out_of_range if the given vector ends prematurely
+
+    @sa https://tools.ietf.org/html/rfc7049
+    */
+    static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
+    {
+        // store and increment index
+        const size_t current_idx = idx++;
+
+        switch (v[current_idx])
+        {
+            // Integer 0x00..0x17 (0..23)
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x04:
+            case 0x05:
+            case 0x06:
+            case 0x07:
+            case 0x08:
+            case 0x09:
+            case 0x0a:
+            case 0x0b:
+            case 0x0c:
+            case 0x0d:
+            case 0x0e:
+            case 0x0f:
+            case 0x10:
+            case 0x11:
+            case 0x12:
+            case 0x13:
+            case 0x14:
+            case 0x15:
+            case 0x16:
+            case 0x17:
+            {
+                return v[current_idx];
+            }
+
+            case 0x18: // Unsigned integer (one-byte uint8_t follows)
+            {
+                idx += 1; // skip content byte
+                return get_from_vector<uint8_t>(v, current_idx);
+            }
+
+            case 0x19: // Unsigned integer (two-byte uint16_t follows)
+            {
+                idx += 2; // skip 2 content bytes
+                return get_from_vector<uint16_t>(v, current_idx);
+            }
+
+            case 0x1a: // Unsigned integer (four-byte uint32_t follows)
+            {
+                idx += 4; // skip 4 content bytes
+                return get_from_vector<uint32_t>(v, current_idx);
+            }
+
+            case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
+            {
+                idx += 8; // skip 8 content bytes
+                return get_from_vector<uint64_t>(v, current_idx);
+            }
+
+            // Negative integer -1-0x00..-1-0x17 (-1..-24)
+            case 0x20:
+            case 0x21:
+            case 0x22:
+            case 0x23:
+            case 0x24:
+            case 0x25:
+            case 0x26:
+            case 0x27:
+            case 0x28:
+            case 0x29:
+            case 0x2a:
+            case 0x2b:
+            case 0x2c:
+            case 0x2d:
+            case 0x2e:
+            case 0x2f:
+            case 0x30:
+            case 0x31:
+            case 0x32:
+            case 0x33:
+            case 0x34:
+            case 0x35:
+            case 0x36:
+            case 0x37:
+            {
+                return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
+            }
+
+            case 0x38: // Negative integer (one-byte uint8_t follows)
+            {
+                idx += 1; // skip content byte
+                // must be uint8_t !
+                return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
+            }
+
+            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
+            {
+                idx += 2; // skip 2 content bytes
+                return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
+            }
+
+            case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
+            {
+                idx += 4; // skip 4 content bytes
+                return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
+            }
+
+            case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
+            {
+                idx += 8; // skip 8 content bytes
+                return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
+            }
+
+            // UTF-8 string (0x00..0x17 bytes follow)
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6a:
+            case 0x6b:
+            case 0x6c:
+            case 0x6d:
+            case 0x6e:
+            case 0x6f:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            {
+                const auto len = static_cast<size_t>(v[current_idx] - 0x60);
+                const size_t offset = current_idx + 1;
+                idx += len; // skip content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+            {
+                const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+                const size_t offset = current_idx + 2;
+                idx += len + 1; // skip size byte + content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+            {
+                const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                const size_t offset = current_idx + 3;
+                idx += len + 2; // skip 2 size bytes + content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
+            {
+                const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                const size_t offset = current_idx + 5;
+                idx += len + 4; // skip 4 size bytes + content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
+            {
+                const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+                const size_t offset = current_idx + 9;
+                idx += len + 8; // skip 8 size bytes + content bytes
+                return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+            }
+
+            case 0x7f: // UTF-8 string (indefinite length)
+            {
+                std::string result;
+                while (v[idx] != 0xff)
+                {
+                    string_t s = from_cbor_internal(v, idx);
+                    result += s;
+                }
+                // skip break byte (0xFF)
+                idx += 1;
+                return result;
+            }
+
+            // array (0x00..0x17 data items follow)
+            case 0x80:
+            case 0x81:
+            case 0x82:
+            case 0x83:
+            case 0x84:
+            case 0x85:
+            case 0x86:
+            case 0x87:
+            case 0x88:
+            case 0x89:
+            case 0x8a:
+            case 0x8b:
+            case 0x8c:
+            case 0x8d:
+            case 0x8e:
+            case 0x8f:
+            case 0x90:
+            case 0x91:
+            case 0x92:
+            case 0x93:
+            case 0x94:
+            case 0x95:
+            case 0x96:
+            case 0x97:
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(v[current_idx] - 0x80);
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x98: // array (one-byte uint8_t for n follows)
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+                idx += 1; // skip 1 size byte
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x99: // array (two-byte uint16_t for n follow)
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                idx += 2; // skip 4 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x9a: // array (four-byte uint32_t for n follow)
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                idx += 4; // skip 4 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x9b: // array (eight-byte uint64_t for n follow)
+            {
+                basic_json result = value_t::array;
+                const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+                idx += 8; // skip 8 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                return result;
+            }
+
+            case 0x9f: // array (indefinite length)
+            {
+                basic_json result = value_t::array;
+                while (v[idx] != 0xff)
+                {
+                    result.push_back(from_cbor_internal(v, idx));
+                }
+                // skip break byte (0xFF)
+                idx += 1;
+                return result;
+            }
+
+            // map (0x00..0x17 pairs of data items follow)
+            case 0xa0:
+            case 0xa1:
+            case 0xa2:
+            case 0xa3:
+            case 0xa4:
+            case 0xa5:
+            case 0xa6:
+            case 0xa7:
+            case 0xa8:
+            case 0xa9:
+            case 0xaa:
+            case 0xab:
+            case 0xac:
+            case 0xad:
+            case 0xae:
+            case 0xaf:
+            case 0xb0:
+            case 0xb1:
+            case 0xb2:
+            case 0xb3:
+            case 0xb4:
+            case 0xb5:
+            case 0xb6:
+            case 0xb7:
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xb8: // map (one-byte uint8_t for n follows)
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+                idx += 1; // skip 1 size byte
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xb9: // map (two-byte uint16_t for n follow)
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+                idx += 2; // skip 2 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xba: // map (four-byte uint32_t for n follow)
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+                idx += 4; // skip 4 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xbb: // map (eight-byte uint64_t for n follow)
+            {
+                basic_json result = value_t::object;
+                const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+                idx += 8; // skip 8 size bytes
+                for (size_t i = 0; i < len; ++i)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                return result;
+            }
+
+            case 0xbf: // map (indefinite length)
+            {
+                basic_json result = value_t::object;
+                while (v[idx] != 0xff)
+                {
+                    std::string key = from_cbor_internal(v, idx);
+                    result[key] = from_cbor_internal(v, idx);
+                }
+                // skip break byte (0xFF)
+                idx += 1;
+                return result;
+            }
+
+            case 0xf4: // false
+            {
+                return false;
+            }
+
+            case 0xf5: // true
+            {
+                return true;
+            }
+
+            case 0xf6: // null
+            {
+                return value_t::null;
+            }
+
+            case 0xf9: // Half-Precision Float (two-byte IEEE 754)
+            {
+                idx += 2; // skip two content bytes
+
+                // code from RFC 7049, Appendix D, Figure 3:
+                // As half-precision floating-point numbers were only added to
+                // IEEE 754 in 2008, today's programming platforms often still
+                // only have limited support for them. It is very easy to
+                // include at least decoding support for them even without such
+                // support. An example of a small decoder for half-precision
+                // floating-point numbers in the C language is shown in Fig. 3.
+                const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
+                const int exp = (half >> 10) & 0x1f;
+                const int mant = half & 0x3ff;
+                double val;
+                if (exp == 0)
+                {
+                    val = std::ldexp(mant, -24);
+                }
+                else if (exp != 31)
+                {
+                    val = std::ldexp(mant + 1024, exp - 25);
+                }
+                else
+                {
+                    val = mant == 0 ? INFINITY : NAN;
+                }
+                return half & 0x8000 ? -val : val;
+            }
+
+            case 0xfa: // Single-Precision Float (four-byte IEEE 754)
+            {
+                // copy bytes in reverse order into the float variable
+                float res;
+                for (size_t byte = 0; byte < sizeof(float); ++byte)
+                {
+                    reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
+                }
+                idx += sizeof(float); // skip content bytes
+                return res;
+            }
+
+            case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
+            {
+                // copy bytes in reverse order into the double variable
+                double res;
+                for (size_t byte = 0; byte < sizeof(double); ++byte)
+                {
+                    reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
+                }
+                idx += sizeof(double); // skip content bytes
+                return res;
+            }
+
+            default: // anything else (0xFF is handled inside the other types)
+            {
+                throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
+            }
+        }
+    }
+
+  public:
+    /*!
+    @brief create a MessagePack serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the MessagePack
+    serialization format. MessagePack is a binary serialization format which
+    aims to be more compact than JSON itself, yet more efficient to parse.
+
+    @param[in] j  JSON value to serialize
+    @return MessagePack serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in MessagePack format.,to_msgpack}
+
+    @sa http://msgpack.org
+    @sa @ref from_msgpack(const std::vector<uint8_t>&) for the analogous
+        deserialization
+    @sa @ref to_cbor(const basic_json& for the related CBOR format
+    */
+    static std::vector<uint8_t> to_msgpack(const basic_json& j)
+    {
+        std::vector<uint8_t> result;
+        to_msgpack_internal(j, result);
+        return result;
+    }
+
+    /*!
+    @brief create a JSON value from a byte vector in MessagePack format
+
+    Deserializes a given byte vector @a v to a JSON value using the MessagePack
+    serialization format.
+
+    @param[in] v  a byte vector in MessagePack format
+    @return deserialized JSON value
+
+    @throw std::invalid_argument if unsupported features from MessagePack were
+    used in the given vector @a v or if the input is not valid MessagePack
+    @throw std::out_of_range if the given vector ends prematurely
+
+    @complexity Linear in the size of the byte vector @a v.
+
+    @liveexample{The example shows the deserialization of a byte vector in
+    MessagePack format to a JSON value.,from_msgpack}
+
+    @sa http://msgpack.org
+    @sa @ref to_msgpack(const basic_json&) for the analogous serialization
+    @sa @ref from_cbor(const std::vector<uint8_t>&) for the related CBOR format
+    */
+    static basic_json from_msgpack(const std::vector<uint8_t>& v)
+    {
+        size_t i = 0;
+        return from_msgpack_internal(v, i);
+    }
+
+    /*!
+    @brief create a MessagePack serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
+    Binary Object Representation) serialization format. CBOR is a binary
+    serialization format which aims to be more compact than JSON itself, yet
+    more efficient to parse.
+
+    @param[in] j  JSON value to serialize
+    @return MessagePack serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in CBOR format.,to_cbor}
+
+    @sa http://cbor.io
+    @sa @ref from_cbor(const std::vector<uint8_t>&) for the analogous
+        deserialization
+    @sa @ref to_msgpack(const basic_json& for the related MessagePack format
+    */
+    static std::vector<uint8_t> to_cbor(const basic_json& j)
+    {
+        std::vector<uint8_t> result;
+        to_cbor_internal(j, result);
+        return result;
+    }
+
+    /*!
+    @brief create a JSON value from a byte vector in CBOR format
+
+    Deserializes a given byte vector @a v to a JSON value using the CBOR
+    (Concise Binary Object Representation) serialization format.
+
+    @param[in] v  a byte vector in CBOR format
+    @return deserialized JSON value
+
+    @throw std::invalid_argument if unsupported features from CBOR were used in
+    the given vector @a v or if the input is not valid MessagePack
+    @throw std::out_of_range if the given vector ends prematurely
+
+    @complexity Linear in the size of the byte vector @a v.
+
+    @liveexample{The example shows the deserialization of a byte vector in CBOR
+    format to a JSON value.,from_cbor}
+
+    @sa http://cbor.io
+    @sa @ref to_cbor(const basic_json&) for the analogous serialization
+    @sa @ref from_msgpack(const std::vector<uint8_t>&) for the related
+        MessagePack format
+    */
+    static basic_json from_cbor(const std::vector<uint8_t>& v)
+    {
+        size_t i = 0;
+        return from_cbor_internal(v, i);
+    }
+
+    /// @}
 
   private:
     ///////////////////////////
@@ -6769,10 +8205,10 @@
 
   public:
     /*!
-    @brief a const random access iterator for the @ref basic_json class
+    @brief a template for a random access iterator for the @ref basic_json class
 
-    This class implements a const iterator for the @ref basic_json class. From
-    this class, the @ref iterator class is derived.
+    This class implements a both iterators (iterator and const_iterator) for the
+    @ref basic_json class.
 
     @note An iterator is called *initialized* when a pointer to a JSON value
           has been set (e.g., by a constructor or a copy assignment). If the
@@ -6785,27 +8221,37 @@
       The iterator that can be moved to point (forward and backward) to any
       element in constant time.
 
-    @since version 1.0.0
+    @since version 1.0.0, simplified in version 2.0.9
     */
-    class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
+    template<typename U>
+    class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
     {
         /// allow basic_json to access private members
         friend class basic_json;
 
+        // make sure U is basic_json or const basic_json
+        static_assert(std::is_same<U, basic_json>::value
+                      or std::is_same<U, const basic_json>::value,
+                      "iter_impl only accepts (const) basic_json");
+
       public:
         /// the type of the values when the iterator is dereferenced
         using value_type = typename basic_json::value_type;
         /// a type to represent differences between iterators
         using difference_type = typename basic_json::difference_type;
         /// defines a pointer to the type iterated over (value_type)
-        using pointer = typename basic_json::const_pointer;
+        using pointer = typename std::conditional<std::is_const<U>::value,
+              typename basic_json::const_pointer,
+              typename basic_json::pointer>::type;
         /// defines a reference to the type iterated over (value_type)
-        using reference = typename basic_json::const_reference;
+        using reference = typename std::conditional<std::is_const<U>::value,
+              typename basic_json::const_reference,
+              typename basic_json::reference>::type;
         /// the category of the iterator
         using iterator_category = std::bidirectional_iterator_tag;
 
         /// default constructor
-        const_iterator() = default;
+        iter_impl() = default;
 
         /*!
         @brief constructor for a given JSON instance
@@ -6813,7 +8259,7 @@
         @pre object != nullptr
         @post The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        explicit const_iterator(pointer object) noexcept
+        explicit iter_impl(pointer object) noexcept
             : m_object(object)
         {
             assert(m_object != nullptr);
@@ -6840,37 +8286,25 @@
             }
         }
 
-        /*!
-        @brief copy constructor given a non-const iterator
-        @param[in] other  iterator to copy from
-        @note It is not checked whether @a other is initialized.
+        /*
+        Use operator `const_iterator` instead of `const_iterator(const iterator&
+        other) noexcept` to avoid two class definitions for @ref iterator and
+        @ref const_iterator.
+
+        This function is only called if this class is an @ref iterator. If this
+        class is a @ref const_iterator this function is not called.
         */
-        explicit const_iterator(const iterator& other) noexcept
-            : m_object(other.m_object)
+        operator const_iterator() const
         {
-            if (m_object != nullptr)
+            const_iterator ret;
+
+            if (m_object)
             {
-                switch (m_object->m_type)
-                {
-                    case basic_json::value_t::object:
-                    {
-                        m_it.object_iterator = other.m_it.object_iterator;
-                        break;
-                    }
-
-                    case basic_json::value_t::array:
-                    {
-                        m_it.array_iterator = other.m_it.array_iterator;
-                        break;
-                    }
-
-                    default:
-                    {
-                        m_it.primitive_iterator = other.m_it.primitive_iterator;
-                        break;
-                    }
-                }
+                ret.m_object = m_object;
+                ret.m_it = m_it;
             }
+
+            return ret;
         }
 
         /*!
@@ -6878,7 +8312,7 @@
         @param[in] other  iterator to copy from
         @note It is not checked whether @a other is initialized.
         */
-        const_iterator(const const_iterator& other) noexcept
+        iter_impl(const iter_impl& other) noexcept
             : m_object(other.m_object), m_it(other.m_it)
         {}
 
@@ -6887,7 +8321,7 @@
         @param[in,out] other  iterator to copy from
         @note It is not checked whether @a other is initialized.
         */
-        const_iterator& operator=(const_iterator other) noexcept(
+        iter_impl& operator=(iter_impl other) noexcept(
             std::is_nothrow_move_constructible<pointer>::value and
             std::is_nothrow_move_assignable<pointer>::value and
             std::is_nothrow_move_constructible<internal_iterator>::value and
@@ -7049,7 +8483,7 @@
         @brief post-increment (it++)
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator operator++(int)
+        iter_impl operator++(int)
         {
             auto result = *this;
             ++(*this);
@@ -7060,7 +8494,7 @@
         @brief pre-increment (++it)
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator& operator++()
+        iter_impl& operator++()
         {
             assert(m_object != nullptr);
 
@@ -7092,7 +8526,7 @@
         @brief post-decrement (it--)
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator operator--(int)
+        iter_impl operator--(int)
         {
             auto result = *this;
             --(*this);
@@ -7103,7 +8537,7 @@
         @brief pre-decrement (--it)
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator& operator--()
+        iter_impl& operator--()
         {
             assert(m_object != nullptr);
 
@@ -7135,7 +8569,7 @@
         @brief  comparison: equal
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator==(const const_iterator& other) const
+        bool operator==(const iter_impl& other) const
         {
             // if objects are not the same, the comparison is undefined
             if (m_object != other.m_object)
@@ -7168,7 +8602,7 @@
         @brief  comparison: not equal
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator!=(const const_iterator& other) const
+        bool operator!=(const iter_impl& other) const
         {
             return not operator==(other);
         }
@@ -7177,7 +8611,7 @@
         @brief  comparison: smaller
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator<(const const_iterator& other) const
+        bool operator<(const iter_impl& other) const
         {
             // if objects are not the same, the comparison is undefined
             if (m_object != other.m_object)
@@ -7210,7 +8644,7 @@
         @brief  comparison: less than or equal
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator<=(const const_iterator& other) const
+        bool operator<=(const iter_impl& other) const
         {
             return not other.operator < (*this);
         }
@@ -7219,7 +8653,7 @@
         @brief  comparison: greater than
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator>(const const_iterator& other) const
+        bool operator>(const iter_impl& other) const
         {
             return not operator<=(other);
         }
@@ -7228,7 +8662,7 @@
         @brief  comparison: greater than or equal
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        bool operator>=(const const_iterator& other) const
+        bool operator>=(const iter_impl& other) const
         {
             return not operator<(other);
         }
@@ -7237,7 +8671,7 @@
         @brief  add to iterator
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator& operator+=(difference_type i)
+        iter_impl& operator+=(difference_type i)
         {
             assert(m_object != nullptr);
 
@@ -7268,7 +8702,7 @@
         @brief  subtract from iterator
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator& operator-=(difference_type i)
+        iter_impl& operator-=(difference_type i)
         {
             return operator+=(-i);
         }
@@ -7277,7 +8711,7 @@
         @brief  add to iterator
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator operator+(difference_type i)
+        iter_impl operator+(difference_type i)
         {
             auto result = *this;
             result += i;
@@ -7288,7 +8722,7 @@
         @brief  subtract from iterator
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        const_iterator operator-(difference_type i)
+        iter_impl operator-(difference_type i)
         {
             auto result = *this;
             result -= i;
@@ -7299,7 +8733,7 @@
         @brief  return difference
         @pre The iterator is initialized; i.e. `m_object != nullptr`.
         */
-        difference_type operator-(const const_iterator& other) const
+        difference_type operator-(const iter_impl& other) const
         {
             assert(m_object != nullptr);
 
@@ -7396,141 +8830,6 @@
     };
 
     /*!
-    @brief a mutable random access iterator for the @ref basic_json class
-
-    @requirement The class satisfies the following concept requirements:
-    - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
-      The iterator that can be moved to point (forward and backward) to any
-      element in constant time.
-    - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
-      It is possible to write to the pointed-to element.
-
-    @since version 1.0.0
-    */
-    class iterator : public const_iterator
-    {
-      public:
-        using base_iterator = const_iterator;
-        using pointer = typename basic_json::pointer;
-        using reference = typename basic_json::reference;
-
-        /// default constructor
-        iterator() = default;
-
-        /// constructor for a given JSON instance
-        explicit iterator(pointer object) noexcept
-            : base_iterator(object)
-        {}
-
-        /// copy constructor
-        iterator(const iterator& other) noexcept
-            : base_iterator(other)
-        {}
-
-        /// copy assignment
-        iterator& operator=(iterator other) noexcept(
-            std::is_nothrow_move_constructible<pointer>::value and
-            std::is_nothrow_move_assignable<pointer>::value and
-            std::is_nothrow_move_constructible<internal_iterator>::value and
-            std::is_nothrow_move_assignable<internal_iterator>::value
-        )
-        {
-            base_iterator::operator=(other);
-            return *this;
-        }
-
-        /// return a reference to the value pointed to by the iterator
-        reference operator*() const
-        {
-            return const_cast<reference>(base_iterator::operator*());
-        }
-
-        /// dereference the iterator
-        pointer operator->() const
-        {
-            return const_cast<pointer>(base_iterator::operator->());
-        }
-
-        /// post-increment (it++)
-        iterator operator++(int)
-        {
-            iterator result = *this;
-            base_iterator::operator++();
-            return result;
-        }
-
-        /// pre-increment (++it)
-        iterator& operator++()
-        {
-            base_iterator::operator++();
-            return *this;
-        }
-
-        /// post-decrement (it--)
-        iterator operator--(int)
-        {
-            iterator result = *this;
-            base_iterator::operator--();
-            return result;
-        }
-
-        /// pre-decrement (--it)
-        iterator& operator--()
-        {
-            base_iterator::operator--();
-            return *this;
-        }
-
-        /// add to iterator
-        iterator& operator+=(difference_type i)
-        {
-            base_iterator::operator+=(i);
-            return *this;
-        }
-
-        /// subtract from iterator
-        iterator& operator-=(difference_type i)
-        {
-            base_iterator::operator-=(i);
-            return *this;
-        }
-
-        /// add to iterator
-        iterator operator+(difference_type i)
-        {
-            auto result = *this;
-            result += i;
-            return result;
-        }
-
-        /// subtract from iterator
-        iterator operator-(difference_type i)
-        {
-            auto result = *this;
-            result -= i;
-            return result;
-        }
-
-        /// return difference
-        difference_type operator-(const iterator& other) const
-        {
-            return base_iterator::operator-(other);
-        }
-
-        /// access to successor
-        reference operator[](difference_type n) const
-        {
-            return const_cast<reference>(base_iterator::operator[](n));
-        }
-
-        /// return the value of an iterator
-        reference value() const
-        {
-            return const_cast<reference>(base_iterator::value());
-        }
-    };
-
-    /*!
     @brief a template for a reverse iterator class
 
     @tparam Base the base iterator type to reverse. Valid types are @ref
@@ -7883,6 +9182,7 @@
                     re2c:define:YYMARKER     = m_marker;
                     re2c:define:YYFILL       = "fill_line_buffer(@@); // LCOV_EXCL_LINE";
                     re2c:define:YYFILL:naked = 1;
+                    re2c:yyfill:enable       = 1;
                     re2c:indent:string       = "    ";
                     re2c:indent:top          = 1;
                     re2c:labelprefix         = "basic_json_parser_";
@@ -8217,8 +9517,6 @@
         supplied via the first parameter.  Set this to @a
         static_cast<number_float_t*>(nullptr).
 
-        @param[in] type  the @ref number_float_t in use
-
         @param[in,out] endptr recieves a pointer to the first character after
         the number
 
@@ -8237,8 +9535,6 @@
         supplied via the first parameter.  Set this to @a
         static_cast<number_float_t*>(nullptr).
 
-        @param[in] type  the @ref number_float_t in use
-
         @param[in,out] endptr  recieves a pointer to the first character after
         the number
 
@@ -8257,8 +9553,6 @@
         supplied via the first parameter.  Set this to @a
         static_cast<number_float_t*>(nullptr).
 
-        @param[in] type  the @ref number_float_t in use
-
         @param[in,out] endptr  recieves a pointer to the first character after
         the number
 
@@ -8339,19 +9633,19 @@
                 // skip if definitely not an integer
                 if (type != value_t::number_float)
                 {
-                    // multiply last value by ten and add the new digit
-                    auto temp = value * 10 + *curptr - '0';
+                    auto digit = static_cast<number_unsigned_t>(*curptr - '0');
 
-                    // test for overflow
-                    if (temp < value || temp > max)
+                    // overflow if value * 10 + digit > max, move terms around
+                    // to avoid overflow in intermediate values
+                    if (value > (max - digit) / 10)
                     {
                         // overflow
                         type = value_t::number_float;
                     }
                     else
                     {
-                        // no overflow - save it
-                        value = temp;
+                        // no overflow
+                        value = value * 10 + digit;
                     }
                 }
             }
@@ -8363,7 +9657,22 @@
             }
             else if (type == value_t::number_integer)
             {
-                result.m_value.number_integer = -static_cast<number_integer_t>(value);
+                // invariant: if we parsed a '-', the absolute value is between
+                // 0 (we allow -0) and max == -INT64_MIN
+                assert(value >= 0);
+                assert(value <= max);
+
+                if (value == max)
+                {
+                    // we cannot simply negate value (== max == -INT64_MIN),
+                    // see https://github.com/nlohmann/json/issues/389
+                    result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN);
+                }
+                else
+                {
+                    // all other values can be negated safely
+                    result.m_value.number_integer = -static_cast<number_integer_t>(value);
+                }
             }
             else
             {
@@ -9146,13 +10455,11 @@
         /*!
         @brief replace all occurrences of a substring by another string
 
-        @param[in,out] s  the string to manipulate
+        @param[in,out] s  the string to manipulate; changed so that all
+                          occurrences of @a f are replaced with @a t
         @param[in]     f  the substring to replace with @a t
         @param[in]     t  the string to replace @a f
 
-        @return The string @a s where all occurrences of @a f are replaced
-                with @a t.
-
         @pre The search string @a f must not be empty.
 
         @since version 2.0.0
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 782d5b5..f57ddf7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -6,6 +6,7 @@
     "src/unit-algorithms.cpp"
     "src/unit-allocator.cpp"
     "src/unit-capacity.cpp"
+    "src/unit-cbor.cpp"
     "src/unit-class_const_iterator.cpp"
     "src/unit-class_iterator.cpp"
     "src/unit-class_lexer.cpp"
@@ -26,6 +27,7 @@
     "src/unit-json_patch.cpp"
     "src/unit-json_pointer.cpp"
     "src/unit-modifiers.cpp"
+    "src/unit-msgpack.cpp"
     "src/unit-pointer_access.cpp"
     "src/unit-readme.cpp"
     "src/unit-reference_access.cpp"
diff --git a/test/Makefile b/test/Makefile
index ead1f07..488cec8 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -10,6 +10,7 @@
           src/unit-algorithms.cpp \
           src/unit-allocator.cpp \
           src/unit-capacity.cpp \
+          src/unit-cbor.cpp \
           src/unit-class_const_iterator.cpp \
           src/unit-class_iterator.cpp \
           src/unit-class_lexer.cpp \
@@ -30,6 +31,7 @@
           src/unit-json_patch.cpp \
           src/unit-json_pointer.cpp \
           src/unit-modifiers.cpp \
+          src/unit-msgpack.cpp \
           src/unit-pointer_access.cpp \
           src/unit-readme.cpp \
           src/unit-reference_access.cpp \
@@ -40,7 +42,20 @@
 
 OBJECTS = $(SOURCES:.cpp=.o)
 
-all: json_unit
+TESTCASES = $(patsubst src/unit-%.cpp,test-%,$(wildcard src/unit-*.cpp))
+
+##############################################################################
+# main rules
+##############################################################################
+
+all: $(TESTCASES)
+
+clean:
+	rm -fr json_unit $(OBJECTS) $(SOURCES:.cpp=.gcno) $(SOURCES:.cpp=.gcda) $(TESTCASES)
+
+##############################################################################
+# single test file
+##############################################################################
 
 json_unit: $(OBJECTS) ../src/json.hpp src/catch.hpp
 	@echo "[CXXLD] $@"
@@ -50,5 +65,16 @@
 	@echo "[CXX]   $@"
 	@$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
 
-clean:
-	rm -fr json_unit $(OBJECTS) $(SOURCES:.cpp=.gcno) $(SOURCES:.cpp=.gcda)
+
+##############################################################################
+# individual test cases
+##############################################################################
+
+test-%: src/unit-%.cpp ../src/json.hpp src/catch.hpp
+	@echo "[CXXLD] $@"
+	@$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -DCATCH_CONFIG_MAIN $< -o $@
+
+TEST_PATTERN = "*"
+TEST_PREFIX = ""
+check: $(TESTCASES)
+	@cd .. ; for testcase in $(TESTCASES); do echo "Executing $$testcase..."; $(TEST_PREFIX)test/$$testcase $(TEST_PATTERN) || exit 1; done
diff --git a/test/data/json.org/1.json.cbor b/test/data/json.org/1.json.cbor
new file mode 100644
index 0000000..e31034c
--- /dev/null
+++ b/test/data/json.org/1.json.cbor
@@ -0,0 +1 @@
+¡hglossary¢hGlossDiv¢iGlossList¡jGlossEntry§hGlossDef¢lGlossSeeAlso‚cGMLcXMLdparaxHA meta-markup language, used to create markup languages such as DocBook.hGlossSeefmarkupgAcronymdSGMLiGlossTermx$Standard Generalized Markup LanguagefAbbrevmISO 8879:1986fSortAsdSGMLbIDdSGMLetitleaSetitlepexample glossary
\ No newline at end of file
diff --git a/test/data/json.org/1.json.msgpack b/test/data/json.org/1.json.msgpack
new file mode 100644
index 0000000..726875c
--- /dev/null
+++ b/test/data/json.org/1.json.msgpack
Binary files differ
diff --git a/test/data/json.org/2.json.cbor b/test/data/json.org/2.json.cbor
new file mode 100644
index 0000000..ddce516
--- /dev/null
+++ b/test/data/json.org/2.json.cbor
@@ -0,0 +1 @@
+¡dmenu£epopup¡hmenuitemƒ¢gonclicknCreateNewDoc()evaluecNew¢gonclickiOpenDoc()evaluedOpen¢gonclickjCloseDoc()evalueeClosebiddfileevaluedFile
\ No newline at end of file
diff --git a/test/data/json.org/2.json.msgpack b/test/data/json.org/2.json.msgpack
new file mode 100644
index 0000000..3321e1e
--- /dev/null
+++ b/test/data/json.org/2.json.msgpack
@@ -0,0 +1 @@
+¤menuƒ¥popup¨menuitem“‚§onclick®CreateNewDoc()¥value£New‚§onclick©OpenDoc()¥value¤Open‚§onclickªCloseDoc()¥value¥Close¢id¤file¥value¤File
\ No newline at end of file
diff --git a/test/data/json.org/3.json.cbor b/test/data/json.org/3.json.cbor
new file mode 100644
index 0000000..6bd57bf
--- /dev/null
+++ b/test/data/json.org/3.json.cbor
@@ -0,0 +1 @@
+¡fwidget¤edebugbondtext¨gvOffsetdestyledbolddnameetext1ghOffsetúionMouseUpx)sun1.opacity = (sun1.opacity / 100) * 90;ddatajClick Hereialignmentfcenterdsize$fwindow¤ewidthôfheightôdnamekmain_windowetitlexSample Konfabulator Widgeteimage¥gvOffsetúcsrcnImages/Sun.pngialignmentfcenterdnamedsun1ghOffsetú
\ No newline at end of file
diff --git a/test/data/json.org/3.json.msgpack b/test/data/json.org/3.json.msgpack
new file mode 100644
index 0000000..e261cd5
--- /dev/null
+++ b/test/data/json.org/3.json.msgpack
Binary files differ
diff --git a/test/data/json.org/4.json.cbor b/test/data/json.org/4.json.cbor
new file mode 100644
index 0000000..e994dee
--- /dev/null
+++ b/test/data/json.org/4.json.cbor
@@ -0,0 +1,4 @@
+¡gweb-app£oservlet-mapping¥jcofaxToolsh/tools/*hcofaxCDSa/kfileServleti/static/*jcofaxAdminh/admin/*jcofaxEmails/cofaxutil/aemail/*ftaglib¢otaglib-locationw/WEB-INF/tlds/cofax.tldjtaglib-uriicofax.tldgservlet…£lservlet-namehcofaxCDSjinit-param¸*ocachePagesStoredxsearchEngineListTemplatexforSearchEnginesList.htmxconfigGlossary:adminEmailmksm@pobox.comlmaxUrlLengthôrdataStoreTestQueryx"SET NOCOUNT ON;select test='test';sdefaultFileTemplatesarticleTemplate.htmpdataStoreLogFilex$/usr/local/tomcat/logs/datastore.logstemplateLoaderClassxorg.cofax.FilesTemplateLoaderndataStoreClassvorg.cofax.SqlDataStorepredirectionClassxorg.cofax.SqlRedirectionttemplateOverridePath`scacheTemplatesStore2ldataStoreUrlx;jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goonxsearchEngineFileTemplatetforSearchEngines.htmocachePagesTrackÈucachePackageTagsStoreÈmdataStoreNameecofaxqdataStorePasswordrdataStoreTestQueryfuseJSPôsdefaultListTemplateplistTemplate.htmxconfigGlossary:poweredByeCofaxmdataStoreUserbsaojspListTemplateplistTemplate.jspojspFileTemplatesarticleTemplate.jspqdataStoreMaxConnsdscachePagesDirtyRead
+qcachePagesRefresh
+scacheTemplatesTrackdwdataStoreConnUsageLimitdxconfigGlossary:installationAtpPhiladelphia, PAtsearchEngineRobotsDbqWEB-INF/robots.dbvtemplateProcessorClassxorg.cofax.WysiwygTemplatewcachePackageTagsRefresh<xconfigGlossary:staticPatho/content/staticltemplatePathitemplatesluseDataStoreõucacheTemplatesRefreshodataStoreDriverx,com.microsoft.jdbc.sqlserver.SQLServerDriverxconfigGlossary:poweredByIconq/images/cofax.gifucachePackageTagsTrackÈqdataStoreLogLeveledebugrdataStoreInitConns
+mservlet-classxorg.cofax.cds.CDSServlet£lservlet-namejcofaxEmailjinit-param¢pmailHostOverrideemail2hmailHostemail1mservlet-classxorg.cofax.cds.EmailServlet¢lservlet-namejcofaxAdminmservlet-classxorg.cofax.cds.AdminServlet¢lservlet-namekfileServletmservlet-classxorg.cofax.cds.FileServlet£lservlet-namejcofaxToolsjinit-param­klogLocationx%/usr/local/tomcat/logs/CofaxTools.logrfileTransferFolderx4/usr/local/tomcat/webapps/content/fileTransferFoldercloggdataLogodataLogLocationx"/usr/local/tomcat/logs/dataLog.logladminGroupIDmlookInContextoremovePageCachex%/content/admin/remove?cache=pages&id=sremoveTemplateCachex)/content/admin/remove?cache=templates&id=jlogMaxSize`ndataLogMaxSize`jbetaServerõltemplatePathotoolstemplates/mservlet-classxorg.cofax.cms.CofaxToolsServlet
\ No newline at end of file
diff --git a/test/data/json.org/4.json.msgpack b/test/data/json.org/4.json.msgpack
new file mode 100644
index 0000000..587c0af
--- /dev/null
+++ b/test/data/json.org/4.json.msgpack
Binary files differ
diff --git a/test/data/json.org/5.json.cbor b/test/data/json.org/5.json.cbor
new file mode 100644
index 0000000..41f7ba5
--- /dev/null
+++ b/test/data/json.org/5.json.cbor
@@ -0,0 +1 @@
+¡dmenu¢fheaderjSVG Viewereitems–¡biddOpen¢bidgOpenNewelabelhOpen Newö¢bidfZoomInelabelgZoom In¢bidgZoomOutelabelhZoom Out¢bidlOriginalViewelabelmOriginal Viewö¡bidgQuality¡bidePause¡biddMuteö¢biddFindelabelgFind...¢bidiFindAgainelabeljFind Again¡biddCopy¢bidiCopyAgainelabeljCopy Again¢bidgCopySVGelabelhCopy SVG¢bidgViewSVGelabelhView SVG¢bidjViewSourceelabelkView Source¢bidfSaveAselabelgSave Asö¡biddHelp¢bideAboutelabelxAbout Adobe CVG Viewer...
\ No newline at end of file
diff --git a/test/data/json.org/5.json.msgpack b/test/data/json.org/5.json.msgpack
new file mode 100644
index 0000000..cc70155
--- /dev/null
+++ b/test/data/json.org/5.json.msgpack
Binary files differ
diff --git a/test/data/json_nlohmann_tests/all_unicode.json.cbor b/test/data/json_nlohmann_tests/all_unicode.json.cbor
new file mode 100644
index 0000000..208f3cb
--- /dev/null
+++ b/test/data/json_nlohmann_tests/all_unicode.json.cbor
Binary files differ
diff --git a/test/data/json_nlohmann_tests/all_unicode.json.msgpack b/test/data/json_nlohmann_tests/all_unicode.json.msgpack
new file mode 100644
index 0000000..b024316
--- /dev/null
+++ b/test/data/json_nlohmann_tests/all_unicode.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip01.json.cbor b/test/data/json_roundtrip/roundtrip01.json.cbor
new file mode 100644
index 0000000..6977b91
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip01.json.cbor
@@ -0,0 +1 @@
+ö
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip01.json.msgpack b/test/data/json_roundtrip/roundtrip01.json.msgpack
new file mode 100644
index 0000000..37932df
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip01.json.msgpack
@@ -0,0 +1 @@
+‘À
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip02.json.cbor b/test/data/json_roundtrip/roundtrip02.json.cbor
new file mode 100644
index 0000000..6a7b9cf
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip02.json.cbor
@@ -0,0 +1 @@
+õ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip02.json.msgpack b/test/data/json_roundtrip/roundtrip02.json.msgpack
new file mode 100644
index 0000000..52b4164
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip02.json.msgpack
@@ -0,0 +1 @@
+‘Ã
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip03.json.cbor b/test/data/json_roundtrip/roundtrip03.json.cbor
new file mode 100644
index 0000000..c14c133
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip03.json.cbor
@@ -0,0 +1 @@
+ô
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip03.json.msgpack b/test/data/json_roundtrip/roundtrip03.json.msgpack
new file mode 100644
index 0000000..ea59298
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip03.json.msgpack
@@ -0,0 +1 @@
+‘Â
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip04.json.cbor b/test/data/json_roundtrip/roundtrip04.json.cbor
new file mode 100644
index 0000000..8b040ea
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip04.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip04.json.msgpack b/test/data/json_roundtrip/roundtrip04.json.msgpack
new file mode 100644
index 0000000..5b8551b
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip04.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip05.json.cbor b/test/data/json_roundtrip/roundtrip05.json.cbor
new file mode 100644
index 0000000..bb4b1a5
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip05.json.cbor
@@ -0,0 +1 @@
+cfoo
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip05.json.msgpack b/test/data/json_roundtrip/roundtrip05.json.msgpack
new file mode 100644
index 0000000..fed9247
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip05.json.msgpack
@@ -0,0 +1 @@
+‘£foo
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip06.json.cbor b/test/data/json_roundtrip/roundtrip06.json.cbor
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip06.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip06.json.msgpack b/test/data/json_roundtrip/roundtrip06.json.msgpack
new file mode 100644
index 0000000..9e99dd5
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip06.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip07.json.cbor b/test/data/json_roundtrip/roundtrip07.json.cbor
new file mode 100644
index 0000000..eea1bf0
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip07.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip07.json.msgpack b/test/data/json_roundtrip/roundtrip07.json.msgpack
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip07.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip08.json.cbor b/test/data/json_roundtrip/roundtrip08.json.cbor
new file mode 100644
index 0000000..e1707ae
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip08.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip08.json.msgpack b/test/data/json_roundtrip/roundtrip08.json.msgpack
new file mode 100644
index 0000000..b361f80
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip08.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip09.json.cbor b/test/data/json_roundtrip/roundtrip09.json.cbor
new file mode 100644
index 0000000..1f39c42
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip09.json.cbor
@@ -0,0 +1 @@
+¡cfoocbar
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip09.json.msgpack b/test/data/json_roundtrip/roundtrip09.json.msgpack
new file mode 100644
index 0000000..5ace8ec
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip09.json.msgpack
@@ -0,0 +1 @@
+£foo£bar
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip10.json.cbor b/test/data/json_roundtrip/roundtrip10.json.cbor
new file mode 100644
index 0000000..68a615c
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip10.json.cbor
@@ -0,0 +1 @@
+¢aaöcfoocbar
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip10.json.msgpack b/test/data/json_roundtrip/roundtrip10.json.msgpack
new file mode 100644
index 0000000..f9791c1
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip10.json.msgpack
@@ -0,0 +1 @@
+‚¡aÀ£foo£bar
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip11.json.cbor b/test/data/json_roundtrip/roundtrip11.json.cbor
new file mode 100644
index 0000000..0949b11
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip11.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip11.json.msgpack b/test/data/json_roundtrip/roundtrip11.json.msgpack
new file mode 100644
index 0000000..97689a4
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip11.json.msgpack
@@ -0,0 +1 @@
+‘ÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip12.json.cbor b/test/data/json_roundtrip/roundtrip12.json.cbor
new file mode 100644
index 0000000..3636a1e
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip12.json.cbor
@@ -0,0 +1 @@
+:ÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip12.json.msgpack b/test/data/json_roundtrip/roundtrip12.json.msgpack
new file mode 100644
index 0000000..d523c4a
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip12.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip13.json.cbor b/test/data/json_roundtrip/roundtrip13.json.cbor
new file mode 100644
index 0000000..3948e5f
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip13.json.cbor
@@ -0,0 +1 @@
+;"ô}é
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip13.json.msgpack b/test/data/json_roundtrip/roundtrip13.json.msgpack
new file mode 100644
index 0000000..5b19d3e
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip13.json.msgpack
@@ -0,0 +1 @@
+‘ÓîÝï‚~ë
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip14.json.cbor b/test/data/json_roundtrip/roundtrip14.json.cbor
new file mode 100644
index 0000000..ea2a38b
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip14.json.cbor
@@ -0,0 +1 @@
+;ÿÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip14.json.msgpack b/test/data/json_roundtrip/roundtrip14.json.msgpack
new file mode 100644
index 0000000..4b87c84
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip14.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip15.json.cbor b/test/data/json_roundtrip/roundtrip15.json.cbor
new file mode 100644
index 0000000..17bb347
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip15.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip15.json.msgpack b/test/data/json_roundtrip/roundtrip15.json.msgpack
new file mode 100644
index 0000000..0ad68ff
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip15.json.msgpack
@@ -0,0 +1 @@
+‘
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip16.json.cbor b/test/data/json_roundtrip/roundtrip16.json.cbor
new file mode 100644
index 0000000..c051d45
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip16.json.cbor
@@ -0,0 +1 @@
+ÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip16.json.msgpack b/test/data/json_roundtrip/roundtrip16.json.msgpack
new file mode 100644
index 0000000..199e499
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip16.json.msgpack
@@ -0,0 +1 @@
+‘Îÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip17.json.cbor b/test/data/json_roundtrip/roundtrip17.json.cbor
new file mode 100644
index 0000000..413dbd2
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip17.json.cbor
@@ -0,0 +1 @@
+ÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip17.json.msgpack b/test/data/json_roundtrip/roundtrip17.json.msgpack
new file mode 100644
index 0000000..7e2a955
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip17.json.msgpack
@@ -0,0 +1 @@
+‘Îÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip18.json.cbor b/test/data/json_roundtrip/roundtrip18.json.cbor
new file mode 100644
index 0000000..17a08f1
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip18.json.cbor
@@ -0,0 +1 @@
+"ô}é
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip18.json.msgpack b/test/data/json_roundtrip/roundtrip18.json.msgpack
new file mode 100644
index 0000000..a24c12b
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip18.json.msgpack
@@ -0,0 +1 @@
+‘Ï"ô}é
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip19.json.cbor b/test/data/json_roundtrip/roundtrip19.json.cbor
new file mode 100644
index 0000000..a8ff265
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip19.json.cbor
@@ -0,0 +1 @@
+ÿÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip19.json.msgpack b/test/data/json_roundtrip/roundtrip19.json.msgpack
new file mode 100644
index 0000000..670c193
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip19.json.msgpack
@@ -0,0 +1 @@
+‘Ïÿÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip20.json.cbor b/test/data/json_roundtrip/roundtrip20.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip20.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip20.json.msgpack b/test/data/json_roundtrip/roundtrip20.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip20.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip21.json.cbor b/test/data/json_roundtrip/roundtrip21.json.cbor
new file mode 100644
index 0000000..90e1bef
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip21.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip21.json.msgpack b/test/data/json_roundtrip/roundtrip21.json.msgpack
new file mode 100644
index 0000000..ebe72a0
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip21.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip22.json.cbor b/test/data/json_roundtrip/roundtrip22.json.cbor
new file mode 100644
index 0000000..1af4e2c
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip22.json.cbor
@@ -0,0 +1 @@
+û?óÀƒn—
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip22.json.msgpack b/test/data/json_roundtrip/roundtrip22.json.msgpack
new file mode 100644
index 0000000..bb8b079
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip22.json.msgpack
@@ -0,0 +1 @@
+‘Ë?óÀƒn—
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip23.json.cbor b/test/data/json_roundtrip/roundtrip23.json.cbor
new file mode 100644
index 0000000..80a2fa1
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip23.json.cbor
@@ -0,0 +1 @@
+û¿óÀƒn—
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip23.json.msgpack b/test/data/json_roundtrip/roundtrip23.json.msgpack
new file mode 100644
index 0000000..76ac419
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip23.json.msgpack
@@ -0,0 +1 @@
+‘Ë¿óÀƒn—
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip24.json.cbor b/test/data/json_roundtrip/roundtrip24.json.cbor
new file mode 100644
index 0000000..86aea39
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip24.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip24.json.msgpack b/test/data/json_roundtrip/roundtrip24.json.msgpack
new file mode 100644
index 0000000..f5bf071
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip24.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip25.json.cbor b/test/data/json_roundtrip/roundtrip25.json.cbor
new file mode 100644
index 0000000..4a361ca
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip25.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip25.json.msgpack b/test/data/json_roundtrip/roundtrip25.json.msgpack
new file mode 100644
index 0000000..c45fb04
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip25.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip26.json.cbor b/test/data/json_roundtrip/roundtrip26.json.cbor
new file mode 100644
index 0000000..c5de720
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip26.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip26.json.msgpack b/test/data/json_roundtrip/roundtrip26.json.msgpack
new file mode 100644
index 0000000..0a6b037
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip26.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip27.json.cbor b/test/data/json_roundtrip/roundtrip27.json.cbor
new file mode 100644
index 0000000..e1fcb16
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip27.json.cbor
@@ -0,0 +1 @@
+ûïÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip27.json.msgpack b/test/data/json_roundtrip/roundtrip27.json.msgpack
new file mode 100644
index 0000000..5f03c19
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip27.json.msgpack
@@ -0,0 +1 @@
+‘Ëïÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip28.json.cbor b/test/data/json_roundtrip/roundtrip28.json.cbor
new file mode 100644
index 0000000..86aea39
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip28.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip28.json.msgpack b/test/data/json_roundtrip/roundtrip28.json.msgpack
new file mode 100644
index 0000000..f5bf071
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip28.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip29.json.cbor b/test/data/json_roundtrip/roundtrip29.json.cbor
new file mode 100644
index 0000000..85c00ac
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip29.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip29.json.msgpack b/test/data/json_roundtrip/roundtrip29.json.msgpack
new file mode 100644
index 0000000..b1ef60a
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip29.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip30.json.cbor b/test/data/json_roundtrip/roundtrip30.json.cbor
new file mode 100644
index 0000000..f8cdaac
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip30.json.cbor
@@ -0,0 +1 @@
+û9¹	ãõöÂ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip30.json.msgpack b/test/data/json_roundtrip/roundtrip30.json.msgpack
new file mode 100644
index 0000000..4362c4c
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip30.json.msgpack
@@ -0,0 +1 @@
+‘Ë9¹	ãõöÂ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip31.json.cbor b/test/data/json_roundtrip/roundtrip31.json.cbor
new file mode 100644
index 0000000..cb47b07
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip31.json.cbor
@@ -0,0 +1 @@
+ûF/)Äî±Uå
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip31.json.msgpack b/test/data/json_roundtrip/roundtrip31.json.msgpack
new file mode 100644
index 0000000..e4d9e9a
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip31.json.msgpack
@@ -0,0 +1 @@
+‘ËF/)Äî±Uå
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip32.json.cbor b/test/data/json_roundtrip/roundtrip32.json.cbor
new file mode 100644
index 0000000..cb47b07
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip32.json.cbor
@@ -0,0 +1 @@
+ûF/)Äî±Uå
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip32.json.msgpack b/test/data/json_roundtrip/roundtrip32.json.msgpack
new file mode 100644
index 0000000..e4d9e9a
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip32.json.msgpack
@@ -0,0 +1 @@
+‘ËF/)Äî±Uå
\ No newline at end of file
diff --git a/test/data/json_tests/pass1.json.cbor b/test/data/json_tests/pass1.json.cbor
new file mode 100644
index 0000000..063bf93
--- /dev/null
+++ b/test/data/json_tests/pass1.json.cbor
Binary files differ
diff --git a/test/data/json_tests/pass1.json.msgpack b/test/data/json_tests/pass1.json.msgpack
new file mode 100644
index 0000000..6b1e731
--- /dev/null
+++ b/test/data/json_tests/pass1.json.msgpack
Binary files differ
diff --git a/test/data/json_tests/pass2.json.cbor b/test/data/json_tests/pass2.json.cbor
new file mode 100644
index 0000000..fe3a096
--- /dev/null
+++ b/test/data/json_tests/pass2.json.cbor
@@ -0,0 +1 @@
+lNot too deep
\ No newline at end of file
diff --git a/test/data/json_tests/pass2.json.msgpack b/test/data/json_tests/pass2.json.msgpack
new file mode 100644
index 0000000..336ce90
--- /dev/null
+++ b/test/data/json_tests/pass2.json.msgpack
@@ -0,0 +1 @@
+‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘¬Not too deep
\ No newline at end of file
diff --git a/test/data/json_tests/pass3.json.cbor b/test/data/json_tests/pass3.json.cbor
new file mode 100644
index 0000000..d29b43d
--- /dev/null
+++ b/test/data/json_tests/pass3.json.cbor
@@ -0,0 +1 @@
+¡wJSON Test Pattern pass3¢lIn this testpIt is an object.sThe outermost valuexmust be an object or array.
\ No newline at end of file
diff --git a/test/data/json_tests/pass3.json.msgpack b/test/data/json_tests/pass3.json.msgpack
new file mode 100644
index 0000000..aee4236
--- /dev/null
+++ b/test/data/json_tests/pass3.json.msgpack
@@ -0,0 +1 @@
+·JSON Test Pattern pass3‚¬In this test°It is an object.³The outermost value»must be an object or array.
\ No newline at end of file
diff --git a/test/data/json_testsuite/sample.json.cbor b/test/data/json_testsuite/sample.json.cbor
new file mode 100644
index 0000000..3f1d8dd
--- /dev/null
+++ b/test/data/json_testsuite/sample.json.cbor
Binary files differ
diff --git a/test/data/json_testsuite/sample.json.msgpack b/test/data/json_testsuite/sample.json.msgpack
new file mode 100644
index 0000000..e1338dd
--- /dev/null
+++ b/test/data/json_testsuite/sample.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.cbor
new file mode 100644
index 0000000..ca9d0c9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.cbor
@@ -0,0 +1 @@
+€
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.msgpack
new file mode 100644
index 0000000..df3dff5
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.msgpack
@@ -0,0 +1 @@
+‘
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.cbor
new file mode 100644
index 0000000..2a24392
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.cbor
@@ -0,0 +1 @@
+`
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.msgpack
new file mode 100644
index 0000000..f8569fa
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.msgpack
@@ -0,0 +1 @@
+‘ 
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.cbor
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.msgpack
new file mode 100644
index 0000000..9e99dd5
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.cbor
new file mode 100644
index 0000000..bc7cf32
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.cbor
@@ -0,0 +1 @@
+aa
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.msgpack
new file mode 100644
index 0000000..42f2686
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.msgpack
@@ -0,0 +1 @@
+‘¡a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_false.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_false.json.cbor
new file mode 100644
index 0000000..c14c133
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_false.json.cbor
@@ -0,0 +1 @@
+ô
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_false.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_false.json.msgpack
new file mode 100644
index 0000000..ea59298
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_false.json.msgpack
@@ -0,0 +1 @@
+‘Â
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.cbor
new file mode 100644
index 0000000..e1c3c73
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.cbor
@@ -0,0 +1 @@
+„öa1 
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.msgpack
new file mode 100644
index 0000000..ef5e47a
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.msgpack
@@ -0,0 +1 @@
+”À¡1€
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_null.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_null.json.cbor
new file mode 100644
index 0000000..6977b91
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_null.json.cbor
@@ -0,0 +1 @@
+ö
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_null.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_null.json.msgpack
new file mode 100644
index 0000000..37932df
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_null.json.msgpack
@@ -0,0 +1 @@
+‘À
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.cbor
new file mode 100644
index 0000000..17bb347
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.msgpack
new file mode 100644
index 0000000..0ad68ff
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.msgpack
@@ -0,0 +1 @@
+‘
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.cbor
new file mode 100644
index 0000000..17bb347
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.msgpack
new file mode 100644
index 0000000..0ad68ff
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.msgpack
@@ -0,0 +1 @@
+‘
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.cbor
new file mode 100644
index 0000000..f7d666b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.cbor
@@ -0,0 +1 @@
+…ööö
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.msgpack
new file mode 100644
index 0000000..dd22b5c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.msgpack
@@ -0,0 +1 @@
+•ÀÀÀ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.cbor
new file mode 100644
index 0000000..02b41ff
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.msgpack
new file mode 100644
index 0000000..9dee29f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.msgpack
@@ -0,0 +1 @@
+‘
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number.json.cbor
new file mode 100644
index 0000000..42ad655
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number.json.cbor
@@ -0,0 +1 @@
+ûMÝ2é2¬X¾
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number.json.msgpack
new file mode 100644
index 0000000..d8016f8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number.json.msgpack
@@ -0,0 +1 @@
+‘ËMÝ2é2¬X¾
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.cbor
new file mode 100644
index 0000000..e8a0edf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.msgpack
new file mode 100644
index 0000000..4919983
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.msgpack
@@ -0,0 +1 @@
+‘
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.cbor
new file mode 100644
index 0000000..ae8b39c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.cbor
@@ -0,0 +1 @@
+û¯½¤ŒähçÇ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.msgpack
new file mode 100644
index 0000000..22b7026
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.msgpack
@@ -0,0 +1 @@
+‘˯½¤ŒähçÇ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.cbor
new file mode 100644
index 0000000..362d407
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.msgpack
new file mode 100644
index 0000000..59db48b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.cbor
new file mode 100644
index 0000000..eb4b0a6
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.msgpack
new file mode 100644
index 0000000..6560b32
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.cbor
new file mode 100644
index 0000000..8b040ea
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.msgpack
new file mode 100644
index 0000000..5b8551b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.cbor
new file mode 100644
index 0000000..346ebfb
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.cbor
@@ -0,0 +1 @@
+8z
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.msgpack
new file mode 100644
index 0000000..8da6fb9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.msgpack
@@ -0,0 +1 @@
+‘Ð…
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.cbor
new file mode 100644
index 0000000..0949b11
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.msgpack
new file mode 100644
index 0000000..97689a4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.msgpack
@@ -0,0 +1 @@
+‘ÿ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.cbor
new file mode 100644
index 0000000..8b040ea
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.msgpack
new file mode 100644
index 0000000..5b8551b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.cbor
new file mode 100644
index 0000000..a8dcf21
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.cbor
@@ -0,0 +1 @@
+ûD€ðÏMՒ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.msgpack
new file mode 100644
index 0000000..579cf7d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.msgpack
@@ -0,0 +1 @@
+‘ËD€ðÏMՒ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.cbor
new file mode 100644
index 0000000..d9f391b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.cbor
@@ -0,0 +1 @@
+û?„záG®{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.msgpack
new file mode 100644
index 0000000..3ac2971
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.msgpack
@@ -0,0 +1 @@
+‘Ë?„záG®{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.cbor
new file mode 100644
index 0000000..1f64a67
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.msgpack
new file mode 100644
index 0000000..34ba122
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.cbor
new file mode 100644
index 0000000..cc16a23
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.msgpack
new file mode 100644
index 0000000..7c1cc37
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.cbor
new file mode 100644
index 0000000..92ec4de
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.cbor
@@ -0,0 +1 @@
+ûP¨¿O§
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.msgpack
new file mode 100644
index 0000000..ec7fe04
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.msgpack
@@ -0,0 +1 @@
+‘ËP¨¿O§
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.cbor
new file mode 100644
index 0000000..d9f391b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.cbor
@@ -0,0 +1 @@
+û?„záG®{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.msgpack
new file mode 100644
index 0000000..3ac2971
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.msgpack
@@ -0,0 +1 @@
+‘Ë?„záG®{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.cbor
new file mode 100644
index 0000000..5d2e2a4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.msgpack
new file mode 100644
index 0000000..1398605
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.cbor
new file mode 100644
index 0000000..1f64a67
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.msgpack
new file mode 100644
index 0000000..34ba122
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.cbor
new file mode 100644
index 0000000..362d407
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.msgpack
new file mode 100644
index 0000000..59db48b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.cbor
new file mode 100644
index 0000000..35fe6ad
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.cbor
@@ -0,0 +1 @@
+{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.msgpack
new file mode 100644
index 0000000..d3ae4d8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.msgpack
@@ -0,0 +1 @@
+‘{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.cbor
new file mode 100644
index 0000000..6776a12
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.cbor
@@ -0,0 +1 @@
+û@^Ý<î
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.msgpack
new file mode 100644
index 0000000..09dcbc6
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.msgpack
@@ -0,0 +1 @@
+‘Ë@^Ý<î
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json.cbor
new file mode 100644
index 0000000..e7a5832
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object.json.cbor
new file mode 100644
index 0000000..13593c1
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object.json.cbor
@@ -0,0 +1 @@
+¢cdfgcfghcasdcsdf
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object.json.msgpack
new file mode 100644
index 0000000..e902e95
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object.json.msgpack
@@ -0,0 +1 @@
+‚£dfg£fgh£asd£sdf
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.cbor
new file mode 100644
index 0000000..b233b30
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.cbor
@@ -0,0 +1 @@
+¡casdcsdf
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.msgpack
new file mode 100644
index 0000000..8c89ddb
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.msgpack
@@ -0,0 +1 @@
+£asd£sdf
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.cbor
new file mode 100644
index 0000000..94a640e
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.cbor
@@ -0,0 +1 @@
+¡aaac
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.msgpack
new file mode 100644
index 0000000..e82b938
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.msgpack
@@ -0,0 +1 @@
+¡a¡c
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.cbor
new file mode 100644
index 0000000..7799d3b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.cbor
@@ -0,0 +1 @@
+¡aaab
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.msgpack
new file mode 100644
index 0000000..12507c1
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.msgpack
@@ -0,0 +1 @@
+¡a¡b
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.cbor
new file mode 100644
index 0000000..eea1bf0
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.msgpack
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.cbor
new file mode 100644
index 0000000..9563c4d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.msgpack
new file mode 100644
index 0000000..c89d18f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.cbor
new file mode 100644
index 0000000..c76791c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.msgpack
new file mode 100644
index 0000000..0106921
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.cbor
new file mode 100644
index 0000000..6d145dd
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.cbor
@@ -0,0 +1 @@
+¢cmaxûEÀ'ç/cminûÅÀ'ç/
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.msgpack
new file mode 100644
index 0000000..5f9299b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.msgpack
@@ -0,0 +1 @@
+‚£maxËEÀ'ç/£minËÅÀ'ç/
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.cbor
new file mode 100644
index 0000000..f6d3858
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.cbor
@@ -0,0 +1 @@
+¢ax¡bidx(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxbidx(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.msgpack
new file mode 100644
index 0000000..6c99095
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.cbor
new file mode 100644
index 0000000..59c63ac
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.cbor
@@ -0,0 +1 @@
+¡aa€
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.msgpack
new file mode 100644
index 0000000..704d8df
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.msgpack
@@ -0,0 +1 @@
+¡a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.cbor
new file mode 100644
index 0000000..4e47941
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.cbor
@@ -0,0 +1 @@
+¡etitlex!Полтора Землекопа
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.msgpack
new file mode 100644
index 0000000..540f238
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.cbor
new file mode 100644
index 0000000..7799d3b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.cbor
@@ -0,0 +1 @@
+¡aaab
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.msgpack
new file mode 100644
index 0000000..12507c1
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.msgpack
@@ -0,0 +1 @@
+¡a¡b
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.cbor
new file mode 100644
index 0000000..0d6409b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.cbor
@@ -0,0 +1 @@
+f`Īካ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.msgpack
new file mode 100644
index 0000000..612152f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.msgpack
@@ -0,0 +1 @@
+‘¦`Īካ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.cbor
new file mode 100644
index 0000000..78091ec
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.cbor
@@ -0,0 +1 @@
+d𝄞
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.msgpack
new file mode 100644
index 0000000..a8d174a
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.msgpack
@@ -0,0 +1 @@
+‘¤ð„ž
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.cbor
new file mode 100644
index 0000000..63af665
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.cbor
@@ -0,0 +1 @@
+d𐐷
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.msgpack
new file mode 100644
index 0000000..7d0b6e4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.msgpack
@@ -0,0 +1 @@
+‘¤ð·
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.cbor
new file mode 100644
index 0000000..6d0d25b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.cbor
@@ -0,0 +1 @@
+h😹💍
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.msgpack
new file mode 100644
index 0000000..72009e8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.msgpack
@@ -0,0 +1 @@
+‘¨ðŸ˜¹ðŸ’
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.cbor
new file mode 100644
index 0000000..8cbf174
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.msgpack
new file mode 100644
index 0000000..017114b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.cbor
new file mode 100644
index 0000000..906aaaa
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.cbor
@@ -0,0 +1 @@
+f\u0000
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.msgpack
new file mode 100644
index 0000000..c4bab43
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.msgpack
@@ -0,0 +1 @@
+‘¦\u0000
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.cbor
new file mode 100644
index 0000000..217272c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.cbor
@@ -0,0 +1 @@
+a"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.msgpack
new file mode 100644
index 0000000..daab159
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.msgpack
@@ -0,0 +1 @@
+‘¡"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.cbor
new file mode 100644
index 0000000..30687cc
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.cbor
@@ -0,0 +1 @@
+ma/*b*/c/*d//e
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.msgpack
new file mode 100644
index 0000000..5364f2c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.msgpack
@@ -0,0 +1 @@
+‘­a/*b*/c/*d//e
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.cbor
new file mode 100644
index 0000000..75e194f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.cbor
@@ -0,0 +1 @@
+b\a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.msgpack
new file mode 100644
index 0000000..ea41d05
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.msgpack
@@ -0,0 +1 @@
+‘¢\a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.cbor
new file mode 100644
index 0000000..3425cfc
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.cbor
@@ -0,0 +1 @@
+b\n
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.msgpack
new file mode 100644
index 0000000..327cf1f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.msgpack
@@ -0,0 +1 @@
+‘¢\n
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.cbor
new file mode 100644
index 0000000..3eb5fc1
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.cbor
@@ -0,0 +1 @@
+a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.msgpack
new file mode 100644
index 0000000..8954efe
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.msgpack
@@ -0,0 +1 @@
+‘¡
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.cbor
new file mode 100644
index 0000000..3406655
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.cbor
@@ -0,0 +1 @@
+cï¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.msgpack
new file mode 100644
index 0000000..80e7452
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.msgpack
@@ -0,0 +1 @@
+‘£ï¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.cbor
new file mode 100644
index 0000000..0705ec8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.cbor
@@ -0,0 +1 @@
+casd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.msgpack
new file mode 100644
index 0000000..1788db3
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.msgpack
@@ -0,0 +1 @@
+‘£asd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.cbor
new file mode 100644
index 0000000..0705ec8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.cbor
@@ -0,0 +1 @@
+casd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.msgpack
new file mode 100644
index 0000000..1788db3
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.msgpack
@@ -0,0 +1 @@
+‘£asd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.cbor
new file mode 100644
index 0000000..a74256d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.cbor
@@ -0,0 +1 @@
+dô¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.msgpack
new file mode 100644
index 0000000..39a157e
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.msgpack
@@ -0,0 +1 @@
+‘¤ô¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.cbor
new file mode 100644
index 0000000..0a32b32
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.cbor
@@ -0,0 +1 @@
+inew line
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.msgpack
new file mode 100644
index 0000000..84ccc51
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.msgpack
@@ -0,0 +1 @@
+‘©new line
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.cbor
new file mode 100644
index 0000000..a74256d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.cbor
@@ -0,0 +1 @@
+dô¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.msgpack
new file mode 100644
index 0000000..39a157e
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.msgpack
@@ -0,0 +1 @@
+‘¤ô¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.cbor
new file mode 100644
index 0000000..977d892
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.cbor
@@ -0,0 +1 @@
+d𛿿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.msgpack
new file mode 100644
index 0000000..19b98bd
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.msgpack
@@ -0,0 +1 @@
+‘¤ð›¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.cbor
new file mode 100644
index 0000000..3406655
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.cbor
@@ -0,0 +1 @@
+cï¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.msgpack
new file mode 100644
index 0000000..80e7452
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.msgpack
@@ -0,0 +1 @@
+‘£ï¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.cbor
new file mode 100644
index 0000000..aa34c41
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.msgpack
new file mode 100644
index 0000000..3c8ba66
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.cbor
new file mode 100644
index 0000000..ef1fa66
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.cbor
@@ -0,0 +1 @@
+a,
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.msgpack
new file mode 100644
index 0000000..3d07f7f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.msgpack
@@ -0,0 +1 @@
+‘¡,
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.cbor
new file mode 100644
index 0000000..1405cf9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.cbor
@@ -0,0 +1 @@
+bπ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.msgpack
new file mode 100644
index 0000000..d9738e2
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.msgpack
@@ -0,0 +1 @@
+‘¢Ï€
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.cbor
new file mode 100644
index 0000000..1674aea
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.cbor
@@ -0,0 +1 @@
+dasd 
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.msgpack
new file mode 100644
index 0000000..d33b64d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.msgpack
@@ -0,0 +1 @@
+‘¤asd 
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_space.json.cbor
new file mode 100644
index 0000000..a19cbb9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_space.json.cbor
@@ -0,0 +1 @@
+a 
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_space.json.msgpack
new file mode 100644
index 0000000..ad19734
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_space.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.cbor
new file mode 100644
index 0000000..77815d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.cbor
@@ -0,0 +1 @@
+cà ¡
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.msgpack
new file mode 100644
index 0000000..1d94ad0
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.msgpack
@@ -0,0 +1 @@
+‘£à ¡
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.cbor
new file mode 100644
index 0000000..2cb1c8d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.cbor
@@ -0,0 +1 @@
+bÄ£
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.msgpack
new file mode 100644
index 0000000..e100f62
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.msgpack
@@ -0,0 +1 @@
+‘¢Ä£
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.cbor
new file mode 100644
index 0000000..4f74251
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.cbor
@@ -0,0 +1 @@
+c

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.msgpack
new file mode 100644
index 0000000..00866ae
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.msgpack
@@ -0,0 +1 @@
+‘£â€¨
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.cbor
new file mode 100644
index 0000000..d35b667
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.cbor
@@ -0,0 +1 @@
+c

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.msgpack
new file mode 100644
index 0000000..b8f541d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.msgpack
@@ -0,0 +1 @@
+‘£â€©
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.cbor
new file mode 100644
index 0000000..7c90b15
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.cbor
@@ -0,0 +1 @@
+jaクリス
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.msgpack
new file mode 100644
index 0000000..9dd9e30
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.msgpack
@@ -0,0 +1 @@
+‘ªaクリス
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.cbor
new file mode 100644
index 0000000..a5d8eef
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.cbor
@@ -0,0 +1 @@
+a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.msgpack
new file mode 100644
index 0000000..b2827c9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.msgpack
@@ -0,0 +1 @@
+‘¡
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.cbor
new file mode 100644
index 0000000..9eeef8e
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.cbor
@@ -0,0 +1 @@
+cꙭ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.msgpack
new file mode 100644
index 0000000..cfdc561
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.msgpack
@@ -0,0 +1 @@
+‘£ê™­
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.cbor
new file mode 100644
index 0000000..c8d5c77
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.cbor
@@ -0,0 +1 @@
+a\
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.msgpack
new file mode 100644
index 0000000..2083b69
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.msgpack
@@ -0,0 +1 @@
+‘¡\
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.cbor
new file mode 100644
index 0000000..e46815f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.cbor
@@ -0,0 +1 @@
+i⍂㈴⍂
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.msgpack
new file mode 100644
index 0000000..8451f4a
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.msgpack
@@ -0,0 +1 @@
+‘©â‚㈴⍂
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.cbor
new file mode 100644
index 0000000..2c33ac2
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.cbor
@@ -0,0 +1 @@
+c​
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.msgpack
new file mode 100644
index 0000000..b175034
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.msgpack
@@ -0,0 +1 @@
+‘£â€‹
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.cbor
new file mode 100644
index 0000000..ca6cae4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.cbor
@@ -0,0 +1 @@
+c⁤
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.msgpack
new file mode 100644
index 0000000..febc5e0
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.msgpack
@@ -0,0 +1 @@
+‘£â¤
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.cbor
new file mode 100644
index 0000000..217272c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.cbor
@@ -0,0 +1 @@
+a"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.msgpack
new file mode 100644
index 0000000..daab159
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.msgpack
@@ -0,0 +1 @@
+‘¡"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.cbor
new file mode 100644
index 0000000..41f5884
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.cbor
@@ -0,0 +1 @@
+g€𝄞
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.msgpack
new file mode 100644
index 0000000..c0089d8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.msgpack
@@ -0,0 +1 @@
+‘§â‚¬ð„ž
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.cbor
new file mode 100644
index 0000000..ec51b86
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.cbor
@@ -0,0 +1 @@
+caa
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.msgpack
new file mode 100644
index 0000000..e0a87ec
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.msgpack
@@ -0,0 +1 @@
+‘£aa
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.cbor
new file mode 100644
index 0000000..3a6e607
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.msgpack
new file mode 100644
index 0000000..5277188
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.cbor
new file mode 100644
index 0000000..d9ba731
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.cbor
@@ -0,0 +1 @@
+*
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.msgpack
new file mode 100644
index 0000000..f59ec20
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.msgpack
@@ -0,0 +1 @@
+*
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.cbor
new file mode 100644
index 0000000..8a0eb60
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.cbor
@@ -0,0 +1 @@
+û¿¹™™™™™š
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.msgpack
new file mode 100644
index 0000000..8d624e4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.msgpack
@@ -0,0 +1 @@
+Ë¿¹™™™™™š
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.cbor
new file mode 100644
index 0000000..f7a8cad
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.msgpack
new file mode 100644
index 0000000..e7754ca
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.cbor
new file mode 100644
index 0000000..4616cca
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.cbor
@@ -0,0 +1 @@
+casd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.msgpack
new file mode 100644
index 0000000..ac624bf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.msgpack
@@ -0,0 +1 @@
+£asd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.cbor
new file mode 100644
index 0000000..bb7d13c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.msgpack
new file mode 100644
index 0000000..6b10f95
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.cbor
new file mode 100644
index 0000000..64845fb
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.cbor
@@ -0,0 +1 @@
+`
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.msgpack
new file mode 100644
index 0000000..eea1bf0
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.cbor
new file mode 100644
index 0000000..bc7cf32
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.cbor
@@ -0,0 +1 @@
+aa
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.msgpack
new file mode 100644
index 0000000..42f2686
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.msgpack
@@ -0,0 +1 @@
+‘¡a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.cbor
new file mode 100644
index 0000000..6a7b9cf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.cbor
@@ -0,0 +1 @@
+õ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.msgpack
new file mode 100644
index 0000000..52b4164
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.msgpack
@@ -0,0 +1 @@
+‘Ã
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.cbor
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.cbor
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.msgpack
new file mode 100644
index 0000000..9e99dd5
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.msgpack
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/data/regression/floats.json.cbor b/test/data/regression/floats.json.cbor
new file mode 100644
index 0000000..9fe6a82
--- /dev/null
+++ b/test/data/regression/floats.json.cbor
Binary files differ
diff --git a/test/data/regression/floats.json.msgpack b/test/data/regression/floats.json.msgpack
new file mode 100644
index 0000000..e54198c
--- /dev/null
+++ b/test/data/regression/floats.json.msgpack
Binary files differ
diff --git a/test/data/regression/signed_ints.json.cbor b/test/data/regression/signed_ints.json.cbor
new file mode 100644
index 0000000..2124691
--- /dev/null
+++ b/test/data/regression/signed_ints.json.cbor
Binary files differ
diff --git a/test/data/regression/signed_ints.json.msgpack b/test/data/regression/signed_ints.json.msgpack
new file mode 100644
index 0000000..d1daa46
--- /dev/null
+++ b/test/data/regression/signed_ints.json.msgpack
Binary files differ
diff --git a/test/data/regression/unsigned_ints.json.cbor b/test/data/regression/unsigned_ints.json.cbor
new file mode 100644
index 0000000..63b7f93
--- /dev/null
+++ b/test/data/regression/unsigned_ints.json.cbor
Binary files differ
diff --git a/test/data/regression/unsigned_ints.json.msgpack b/test/data/regression/unsigned_ints.json.msgpack
new file mode 100644
index 0000000..c995381
--- /dev/null
+++ b/test/data/regression/unsigned_ints.json.msgpack
Binary files differ
diff --git a/test/data/regression/working_file.json.cbor b/test/data/regression/working_file.json.cbor
new file mode 100644
index 0000000..db5befa
--- /dev/null
+++ b/test/data/regression/working_file.json.cbor
@@ -0,0 +1 @@
+©jFullScreenõcFOVZpAmbientOcclusionônRenderDistancejWindowResX€jWindowResY8kMipmapLeveleVSyncõtAnisotropicFiltering
\ No newline at end of file
diff --git a/test/data/regression/working_file.json.msgpack b/test/data/regression/working_file.json.msgpack
new file mode 100644
index 0000000..3abaa15
--- /dev/null
+++ b/test/data/regression/working_file.json.msgpack
@@ -0,0 +1 @@
+‰ªFullScreenãFOVZ°AmbientOcclusion®RenderDistanceªWindowResXÍ€ªWindowResYÍ8«MipmapLevel¥VSyncôAnisotropicFiltering
\ No newline at end of file
diff --git a/test/src/fuzz.cpp b/test/src/fuzz.cpp
index 880dc1c..ef403ea 100644
--- a/test/src/fuzz.cpp
+++ b/test/src/fuzz.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (fuzz test support)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Run "make fuzz_testing" and follow the instructions.
diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp
index 5197f80..31be655 100644
--- a/test/src/unit-algorithms.cpp
+++ b/test/src/unit-algorithms.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp
index f6cecc8..25fd334 100644
--- a/test/src/unit-allocator.cpp
+++ b/test/src/unit-allocator.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-capacity.cpp b/test/src/unit-capacity.cpp
index 97c19cf..7fc3d49 100644
--- a/test/src/unit-capacity.cpp
+++ b/test/src/unit-capacity.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp
new file mode 100644
index 0000000..14944cf
--- /dev/null
+++ b/test/src/unit-cbor.cpp
@@ -0,0 +1,1548 @@
+/*
+    __ _____ _____ _____
+ __|  |   __|     |   | |  JSON for Modern C++ (test suite)
+|  |  |__   |  |  | | | |  version 2.0.9
+|_____|_____|_____|_|___|  https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
+
+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.
+*/
+
+#include "catch.hpp"
+
+#include "json.hpp"
+using nlohmann::json;
+
+#include <fstream>
+
+TEST_CASE("CBOR")
+{
+    SECTION("individual values")
+    {
+        SECTION("discarded")
+        {
+            // discarded values are not serialized
+            json j = json::value_t::discarded;
+            const auto result = json::to_cbor(j);
+            CHECK(result.empty());
+        }
+
+        SECTION("null")
+        {
+            json j = nullptr;
+            std::vector<uint8_t> expected = {0xf6};
+            const auto result = json::to_cbor(j);
+            CHECK(result == expected);
+
+            // roundtrip
+            CHECK(json::from_cbor(result) == j);
+        }
+
+        SECTION("boolean")
+        {
+            SECTION("true")
+            {
+                json j = true;
+                std::vector<uint8_t> expected = {0xf5};
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("false")
+            {
+                json j = false;
+                std::vector<uint8_t> expected = {0xf4};
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+        }
+
+        SECTION("number")
+        {
+            SECTION("signed")
+            {
+                SECTION("-9223372036854775808..-4294967297")
+                {
+                    std::vector<int64_t> numbers;
+                    numbers.push_back(INT64_MIN);
+                    numbers.push_back(-1000000000000000000);
+                    numbers.push_back(-100000000000000000);
+                    numbers.push_back(-10000000000000000);
+                    numbers.push_back(-1000000000000000);
+                    numbers.push_back(-100000000000000);
+                    numbers.push_back(-10000000000000);
+                    numbers.push_back(-1000000000000);
+                    numbers.push_back(-100000000000);
+                    numbers.push_back(-10000000000);
+                    numbers.push_back(-4294967297);
+                    for (auto i : numbers)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(0x3b));
+                        uint64_t positive = static_cast<uint64_t>(-1 - i);
+                        expected.push_back(static_cast<uint8_t>((positive >> 56) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((positive >> 48) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((positive >> 40) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((positive >> 32) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((positive >> 24) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((positive >> 16) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((positive >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(positive & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 9);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x3b);
+                        uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+                                            (static_cast<uint64_t>(result[2]) << 060) +
+                                            (static_cast<uint64_t>(result[3]) << 050) +
+                                            (static_cast<uint64_t>(result[4]) << 040) +
+                                            (static_cast<uint64_t>(result[5]) << 030) +
+                                            (static_cast<uint64_t>(result[6]) << 020) +
+                                            (static_cast<uint64_t>(result[7]) << 010) +
+                                            static_cast<uint64_t>(result[8]));
+                        CHECK(restored == positive);
+                        CHECK(-1 - static_cast<int64_t>(restored) == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("-4294967296..-65537")
+                {
+                    std::vector<int64_t> numbers;
+                    numbers.push_back(-65537);
+                    numbers.push_back(-100000);
+                    numbers.push_back(-1000000);
+                    numbers.push_back(-10000000);
+                    numbers.push_back(-100000000);
+                    numbers.push_back(-1000000000);
+                    numbers.push_back(-4294967296);
+                    for (auto i : numbers)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(0x3a));
+                        uint32_t positive = static_cast<uint32_t>(static_cast<uint64_t>(-1 - i) & 0x00000000ffffffff);
+                        expected.push_back(static_cast<uint8_t>((positive >> 24) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((positive >> 16) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((positive >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(positive & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 5);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x3a);
+                        uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+                                            (static_cast<uint32_t>(result[2]) << 020) +
+                                            (static_cast<uint32_t>(result[3]) << 010) +
+                                            static_cast<uint32_t>(result[4]));
+                        CHECK(restored == positive);
+                        CHECK(-1ll - restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("-65536..-257")
+                {
+                    for (int32_t i = -65536; i <= -257; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(0x39));
+                        uint16_t positive = static_cast<uint16_t>(-1 - i);
+                        expected.push_back(static_cast<uint8_t>((positive >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(positive & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 3);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x39);
+                        uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+                        CHECK(restored == positive);
+                        CHECK(-1 - restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("-9263 (int 16)")
+                {
+                    json j = -9263;
+                    std::vector<uint8_t> expected = {0x39, 0x24, 0x2e};
+
+                    const auto result = json::to_cbor(j);
+                    CHECK(result == expected);
+
+                    int16_t restored = -1 - ((result[1] << 8) + result[2]);
+                    CHECK(restored == -9263);
+
+                    // roundtrip
+                    CHECK(json::from_cbor(result) == j);
+                }
+
+                SECTION("-256..-24")
+                {
+                    for (auto i = -256; i < -24; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0x38);
+                        expected.push_back(static_cast<uint8_t>(-1 - i));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 2);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x38);
+                        CHECK(static_cast<int16_t>(-1 - result[1]) == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("-24..-1")
+                {
+                    for (auto i = -24; i <= -1; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0x20 - 1 - static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 1);
+
+                        // check individual bytes
+                        CHECK(static_cast<int8_t>(0x20 - 1 - result[0]) == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("0..23")
+                {
+                    for (size_t i = 0; i <= 23; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 1);
+
+                        // check individual bytes
+                        CHECK(result[0] == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("24..255")
+                {
+                    for (size_t i = 24; i <= 255; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(0x18));
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 2);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x18);
+                        CHECK(result[1] == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("256..65535")
+                {
+                    for (size_t i = 256; i <= 65535; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(0x19));
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 3);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x19);
+                        uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("65536..4294967295")
+                {
+                    for (uint32_t i :
+                            {
+                                65536u, 77777u, 1048576u
+                            })
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0x1a);
+                        expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 5);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x1a);
+                        uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+                                            (static_cast<uint32_t>(result[2]) << 020) +
+                                            (static_cast<uint32_t>(result[3]) << 010) +
+                                            static_cast<uint32_t>(result[4]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("4294967296..4611686018427387903")
+                {
+                    for (uint64_t i :
+                            {
+                                4294967296ul, 4611686018427387903ul
+                            })
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0x1b);
+                        expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 9);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x1b);
+                        uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+                                            (static_cast<uint64_t>(result[2]) << 060) +
+                                            (static_cast<uint64_t>(result[3]) << 050) +
+                                            (static_cast<uint64_t>(result[4]) << 040) +
+                                            (static_cast<uint64_t>(result[5]) << 030) +
+                                            (static_cast<uint64_t>(result[6]) << 020) +
+                                            (static_cast<uint64_t>(result[7]) << 010) +
+                                            static_cast<uint64_t>(result[8]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                /*
+                SECTION("-32768..-129 (int 16)")
+                {
+                    for (int16_t i = -32768; i <= -129; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xd1);
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 3);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xd1);
+                        int16_t restored = (result[1] << 8) + result[2];
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+                */
+            }
+
+            SECTION("unsigned")
+            {
+                SECTION("0..23 (Integer)")
+                {
+                    for (size_t i = 0; i <= 23; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 1);
+
+                        // check individual bytes
+                        CHECK(result[0] == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("24..255 (one-byte uint8_t)")
+                {
+                    for (size_t i = 24; i <= 255; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0x18);
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 2);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x18);
+                        uint8_t restored = static_cast<uint8_t>(result[1]);
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("256..65535 (two-byte uint16_t)")
+                {
+                    for (size_t i = 256; i <= 65535; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0x19);
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 3);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x19);
+                        uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("65536..4294967295 (four-byte uint32_t)")
+                {
+                    for (uint32_t i :
+                            {
+                                65536u, 77777u, 1048576u
+                            })
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0x1a);
+                        expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 5);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x1a);
+                        uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+                                            (static_cast<uint32_t>(result[2]) << 020) +
+                                            (static_cast<uint32_t>(result[3]) << 010) +
+                                            static_cast<uint32_t>(result[4]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+
+                SECTION("4294967296..4611686018427387903 (eight-byte uint64_t)")
+                {
+                    for (uint64_t i :
+                            {
+                                4294967296ul, 4611686018427387903ul
+                            })
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0x1b);
+                        expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_cbor(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 9);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0x1b);
+                        uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+                                            (static_cast<uint64_t>(result[2]) << 060) +
+                                            (static_cast<uint64_t>(result[3]) << 050) +
+                                            (static_cast<uint64_t>(result[4]) << 040) +
+                                            (static_cast<uint64_t>(result[5]) << 030) +
+                                            (static_cast<uint64_t>(result[6]) << 020) +
+                                            (static_cast<uint64_t>(result[7]) << 010) +
+                                            static_cast<uint64_t>(result[8]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_cbor(result) == j);
+                    }
+                }
+            }
+
+            SECTION("float")
+            {
+                SECTION("3.1415925")
+                {
+                    double v = 3.1415925;
+                    json j = v;
+                    std::vector<uint8_t> expected =
+                    {
+                        0xfb, 0x40, 0x09, 0x21, 0xfb, 0x3f, 0xa6, 0xde, 0xfc
+                    };
+                    const auto result = json::to_cbor(j);
+                    CHECK(result == expected);
+
+                    // restore value (reverse array for endianess)
+                    double restored;
+                    std::reverse(expected.begin(), expected.end());
+                    memcpy(&restored, expected.data(), sizeof(double));
+                    CHECK(restored == v);
+
+                    // roundtrip
+                    CHECK(json::from_cbor(result) == j);
+                }
+            }
+
+            SECTION("half-precision float (edge cases)")
+            {
+                SECTION("infinity")
+                {
+                    json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
+                    CHECK(j == nullptr);
+                }
+
+                SECTION("NaN")
+                {
+                    json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x01}));
+                    CHECK(j == nullptr);
+                }
+            }
+        }
+
+        SECTION("string")
+        {
+            SECTION("N = 0..23")
+            {
+                for (size_t N = 0; N <= 0x17; ++N)
+                {
+                    CAPTURE(N);
+
+                    // create JSON value with string containing of N * 'x'
+                    const auto s = std::string(N, 'x');
+                    json j = s;
+
+                    // create expected byte vector
+                    std::vector<uint8_t> expected;
+                    expected.push_back(static_cast<uint8_t>(0x60 + N));
+                    for (size_t i = 0; i < N; ++i)
+                    {
+                        expected.push_back('x');
+                    }
+
+                    // compare result + size
+                    const auto result = json::to_cbor(j);
+                    CHECK(result == expected);
+                    CHECK(result.size() == N + 1);
+                    // check that no null byte is appended
+                    if (N > 0)
+                    {
+                        CHECK(result.back() != '\x00');
+                    }
+
+                    // roundtrip
+                    CHECK(json::from_cbor(result) == j);
+                }
+            }
+
+            SECTION("N = 24..255")
+            {
+                for (size_t N = 24; N <= 255; ++N)
+                {
+                    CAPTURE(N);
+
+                    // create JSON value with string containing of N * 'x'
+                    const auto s = std::string(N, 'x');
+                    json j = s;
+
+                    // create expected byte vector
+                    std::vector<uint8_t> expected;
+                    expected.push_back(0x78);
+                    expected.push_back(static_cast<uint8_t>(N));
+                    for (size_t i = 0; i < N; ++i)
+                    {
+                        expected.push_back('x');
+                    }
+
+                    // compare result + size
+                    const auto result = json::to_cbor(j);
+                    CHECK(result == expected);
+                    CHECK(result.size() == N + 2);
+                    // check that no null byte is appended
+                    CHECK(result.back() != '\x00');
+
+                    // roundtrip
+                    CHECK(json::from_cbor(result) == j);
+                }
+            }
+
+            SECTION("N = 256..65535")
+            {
+                for (size_t N :
+                        {
+                            256u, 999u, 1025u, 3333u, 2048u, 65535u
+                        })
+                {
+                    CAPTURE(N);
+
+                    // create JSON value with string containing of N * 'x'
+                    const auto s = std::string(N, 'x');
+                    json j = s;
+
+                    // create expected byte vector (hack: create string first)
+                    std::vector<uint8_t> expected(N, 'x');
+                    // reverse order of commands, because we insert at begin()
+                    expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
+                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
+                    expected.insert(expected.begin(), 0x79);
+
+                    // compare result + size
+                    const auto result = json::to_cbor(j);
+                    CHECK(result == expected);
+                    CHECK(result.size() == N + 3);
+                    // check that no null byte is appended
+                    CHECK(result.back() != '\x00');
+
+                    // roundtrip
+                    CHECK(json::from_cbor(result) == j);
+                }
+            }
+
+            SECTION("N = 65536..4294967295")
+            {
+                for (size_t N :
+                        {
+                            65536u, 77777u, 1048576u
+                        })
+                {
+                    CAPTURE(N);
+
+                    // create JSON value with string containing of N * 'x'
+                    const auto s = std::string(N, 'x');
+                    json j = s;
+
+                    // create expected byte vector (hack: create string first)
+                    std::vector<uint8_t> expected(N, 'x');
+                    // reverse order of commands, because we insert at begin()
+                    expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
+                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
+                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
+                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
+                    expected.insert(expected.begin(), 0x7a);
+
+                    // compare result + size
+                    const auto result = json::to_cbor(j);
+                    CHECK(result == expected);
+                    CHECK(result.size() == N + 5);
+                    // check that no null byte is appended
+                    CHECK(result.back() != '\x00');
+
+                    // roundtrip
+                    CHECK(json::from_cbor(result) == j);
+                }
+            }
+        }
+
+        SECTION("array")
+        {
+            SECTION("empty")
+            {
+                json j = json::array();
+                std::vector<uint8_t> expected = {0x80};
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("[null]")
+            {
+                json j = {nullptr};
+                std::vector<uint8_t> expected = {0x81, 0xf6};
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("[1,2,3,4,5]")
+            {
+                json j = json::parse("[1,2,3,4,5]");
+                std::vector<uint8_t> expected = {0x85, 0x01, 0x02, 0x03, 0x04, 0x05};
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("[[[[]]]]")
+            {
+                json j = json::parse("[[[[]]]]");
+                std::vector<uint8_t> expected = {0x81, 0x81, 0x81, 0x80};
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("array with uint16_t elements")
+            {
+                json j(257, nullptr);
+                std::vector<uint8_t> expected(j.size() + 3, 0xf6); // all null
+                expected[0] = 0x99; // array 16 bit
+                expected[1] = 0x01; // size (0x0101), byte 0
+                expected[2] = 0x01; // size (0x0101), byte 1
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("array with uint32_t elements")
+            {
+                json j(65793, nullptr);
+                std::vector<uint8_t> expected(j.size() + 5, 0xf6); // all null
+                expected[0] = 0x9a; // array 32 bit
+                expected[1] = 0x00; // size (0x00010101), byte 0
+                expected[2] = 0x01; // size (0x00010101), byte 1
+                expected[3] = 0x01; // size (0x00010101), byte 2
+                expected[4] = 0x01; // size (0x00010101), byte 3
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            /*
+            SECTION("array with uint64_t elements")
+            {
+                json j(4294967296, nullptr);
+                std::vector<uint8_t> expected(j.size() + 9, 0xf6); // all null
+                expected[0] = 0x9b; // array 64 bit
+                expected[1] = 0x00; // size (0x0000000100000000), byte 0
+                expected[2] = 0x00; // size (0x0000000100000000), byte 1
+                expected[3] = 0x00; // size (0x0000000100000000), byte 2
+                expected[4] = 0x01; // size (0x0000000100000000), byte 3
+                expected[5] = 0x00; // size (0x0000000100000000), byte 4
+                expected[6] = 0x00; // size (0x0000000100000000), byte 5
+                expected[7] = 0x00; // size (0x0000000100000000), byte 6
+                expected[8] = 0x00; // size (0x0000000100000000), byte 7
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+            */
+        }
+
+        SECTION("object")
+        {
+            SECTION("empty")
+            {
+                json j = json::object();
+                std::vector<uint8_t> expected = {0xa0};
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("{\"\":null}")
+            {
+                json j = {{"", nullptr}};
+                std::vector<uint8_t> expected = {0xa1, 0x60, 0xf6};
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
+            {
+                json j = json::parse("{\"a\": {\"b\": {\"c\": {}}}}");
+                std::vector<uint8_t> expected =
+                {
+                    0xa1, 0x61, 0x61, 0xa1, 0x61, 0x62, 0xa1, 0x61, 0x63, 0xa0
+                };
+                const auto result = json::to_cbor(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("object with uint8_t elements")
+            {
+                json j;
+                for (auto i = 0; i < 255; ++i)
+                {
+                    // format i to a fixed width of 5
+                    // each entry will need 7 bytes: 6 for string, 1 for null
+                    std::stringstream ss;
+                    ss << std::setw(5) << std::setfill('0') << i;
+                    j.emplace(ss.str(), nullptr);
+                }
+
+                const auto result = json::to_cbor(j);
+
+                // Checking against an expected vector byte by byte is
+                // difficult, because no assumption on the order of key/value
+                // pairs are made. We therefore only check the prefix (type and
+                // size and the overall size. The rest is then handled in the
+                // roundtrip check.
+                CHECK(result.size() == 1787); // 1 type, 1 size, 255*7 content
+                CHECK(result[0] == 0xb8); // map 8 bit
+                CHECK(result[1] == 0xff); // size byte (0xff)
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("object with uint16_t elements")
+            {
+                json j;
+                for (auto i = 0; i < 256; ++i)
+                {
+                    // format i to a fixed width of 5
+                    // each entry will need 7 bytes: 6 for string, 1 for null
+                    std::stringstream ss;
+                    ss << std::setw(5) << std::setfill('0') << i;
+                    j.emplace(ss.str(), nullptr);
+                }
+
+                const auto result = json::to_cbor(j);
+
+                // Checking against an expected vector byte by byte is
+                // difficult, because no assumption on the order of key/value
+                // pairs are made. We therefore only check the prefix (type and
+                // size and the overall size. The rest is then handled in the
+                // roundtrip check.
+                CHECK(result.size() == 1795); // 1 type, 2 size, 256*7 content
+                CHECK(result[0] == 0xb9); // map 16 bit
+                CHECK(result[1] == 0x01); // byte 0 of size (0x0100)
+                CHECK(result[2] == 0x00); // byte 1 of size (0x0100)
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+
+            SECTION("object with uint32_t elements")
+            {
+                json j;
+                for (auto i = 0; i < 65536; ++i)
+                {
+                    // format i to a fixed width of 5
+                    // each entry will need 7 bytes: 6 for string, 1 for null
+                    std::stringstream ss;
+                    ss << std::setw(5) << std::setfill('0') << i;
+                    j.emplace(ss.str(), nullptr);
+                }
+
+                const auto result = json::to_cbor(j);
+
+                // Checking against an expected vector byte by byte is
+                // difficult, because no assumption on the order of key/value
+                // pairs are made. We therefore only check the prefix (type and
+                // size and the overall size. The rest is then handled in the
+                // roundtrip check.
+                CHECK(result.size() == 458757); // 1 type, 4 size, 65536*7 content
+                CHECK(result[0] == 0xba); // map 32 bit
+                CHECK(result[1] == 0x00); // byte 0 of size (0x00010000)
+                CHECK(result[2] == 0x01); // byte 1 of size (0x00010000)
+                CHECK(result[3] == 0x00); // byte 2 of size (0x00010000)
+                CHECK(result[4] == 0x00); // byte 3 of size (0x00010000)
+
+                // roundtrip
+                CHECK(json::from_cbor(result) == j);
+            }
+        }
+    }
+
+    SECTION("additonal deserialization")
+    {
+        SECTION("0x7b (string)")
+        {
+            std::vector<uint8_t> given = {0x7b, 0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x01, 0x61
+                                         };
+            json j = json::from_cbor(given);
+            CHECK(j == "a");
+        }
+
+        SECTION("0x9b (array)")
+        {
+            std::vector<uint8_t> given = {0x9b, 0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x01, 0xf4
+                                         };
+            json j = json::from_cbor(given);
+            CHECK(j == json::parse("[false]"));
+        }
+
+        SECTION("0xbb (map)")
+        {
+            std::vector<uint8_t> given = {0xbb, 0x00, 0x00, 0x00, 0x00,
+                                          0x00, 0x00, 0x00, 0x01, 0x60, 0xf4
+                                         };
+            json j = json::from_cbor(given);
+            CHECK(j == json::parse("{\"\": false}"));
+        }
+    }
+
+    SECTION("errors")
+    {
+        SECTION("too short byte vector")
+        {
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x18})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x19})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x19, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), std::out_of_range);
+            CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), std::out_of_range);
+        }
+    }
+}
+
+// use this testcase outside [hide] to run it with Valgrind
+TEST_CASE("single CBOR roundtrip")
+{
+    SECTION("sample.json")
+    {
+        std::string filename = "test/data/json_testsuite/sample.json";
+
+        // parse JSON file
+        std::ifstream f_json(filename);
+        json j1 = json::parse(f_json);
+
+        // parse MessagePack file
+        std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
+        std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_cbor)),
+                                    std::istreambuf_iterator<char>());
+        json j2;
+        CHECK_NOTHROW(j2 = json::from_cbor(packed));
+
+        // compare parsed JSON values
+        CHECK(j1 == j2);
+    }
+}
+
+TEST_CASE("CBOR roundtrips", "[hide]")
+{
+    SECTION("input from flynn")
+    {
+        for (std::string filename :
+                {
+                    "test/data/json_nlohmann_tests/all_unicode.json",
+                    "test/data/json.org/1.json",
+                    "test/data/json.org/2.json",
+                    "test/data/json.org/3.json",
+                    "test/data/json.org/4.json",
+                    "test/data/json.org/5.json",
+                    "test/data/json_roundtrip/roundtrip01.json",
+                    "test/data/json_roundtrip/roundtrip02.json",
+                    "test/data/json_roundtrip/roundtrip03.json",
+                    "test/data/json_roundtrip/roundtrip04.json",
+                    "test/data/json_roundtrip/roundtrip05.json",
+                    "test/data/json_roundtrip/roundtrip06.json",
+                    "test/data/json_roundtrip/roundtrip07.json",
+                    "test/data/json_roundtrip/roundtrip08.json",
+                    "test/data/json_roundtrip/roundtrip09.json",
+                    "test/data/json_roundtrip/roundtrip10.json",
+                    "test/data/json_roundtrip/roundtrip11.json",
+                    "test/data/json_roundtrip/roundtrip12.json",
+                    "test/data/json_roundtrip/roundtrip13.json",
+                    "test/data/json_roundtrip/roundtrip14.json",
+                    "test/data/json_roundtrip/roundtrip15.json",
+                    "test/data/json_roundtrip/roundtrip16.json",
+                    "test/data/json_roundtrip/roundtrip17.json",
+                    "test/data/json_roundtrip/roundtrip18.json",
+                    "test/data/json_roundtrip/roundtrip19.json",
+                    "test/data/json_roundtrip/roundtrip20.json",
+                    "test/data/json_roundtrip/roundtrip21.json",
+                    "test/data/json_roundtrip/roundtrip22.json",
+                    "test/data/json_roundtrip/roundtrip23.json",
+                    "test/data/json_roundtrip/roundtrip24.json",
+                    "test/data/json_roundtrip/roundtrip25.json",
+                    "test/data/json_roundtrip/roundtrip26.json",
+                    "test/data/json_roundtrip/roundtrip27.json",
+                    "test/data/json_roundtrip/roundtrip28.json",
+                    "test/data/json_roundtrip/roundtrip29.json",
+                    "test/data/json_roundtrip/roundtrip30.json",
+                    "test/data/json_roundtrip/roundtrip31.json",
+                    "test/data/json_roundtrip/roundtrip32.json",
+                    "test/data/json_testsuite/sample.json", // kills AppVeyor
+                    "test/data/json_tests/pass1.json",
+                    "test/data/json_tests/pass2.json",
+                    "test/data/json_tests/pass3.json",
+                    "test/data/regression/floats.json",
+                    "test/data/regression/signed_ints.json",
+                    "test/data/regression/unsigned_ints.json",
+                    "test/data/regression/working_file.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_empty.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_false.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_null.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_0e1.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_after_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json",
+                    //"test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json",
+                    //"test/data/nst_json_testsuite/test_parsing/y_number_too_big_pos_int.json",
+                    //"test/data/nst_json_testsuite/test_parsing/y_number_very_big_negative_int.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_basic.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_empty.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_simple.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_comments.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_in_array.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_pi.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json",
+                    // "test/data/nst_json_testsuite/test_parsing/y_string_utf16.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_utf8.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json"
+                })
+        {
+            CAPTURE(filename);
+
+            // parse JSON file
+            std::ifstream f_json(filename);
+            json j1 = json::parse(f_json);
+
+            // parse CBOR file
+            std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
+            std::vector<uint8_t> packed(
+                (std::istreambuf_iterator<char>(f_cbor)),
+                std::istreambuf_iterator<char>());
+            json j2;
+            CHECK_NOTHROW(j2 = json::from_cbor(packed));
+
+            // compare parsed JSON values
+            CHECK(j1 == j2);
+        }
+    }
+}
+
+TEST_CASE("examples from RFC 7049 Appendix A")
+{
+    SECTION("numbers")
+    {
+        CHECK(json::to_cbor(json::parse("0")) == std::vector<uint8_t>({0x00}));
+        CHECK(json::parse("0") == json::from_cbor(std::vector<uint8_t>({0x00})));
+
+        CHECK(json::to_cbor(json::parse("1")) == std::vector<uint8_t>({0x01}));
+        CHECK(json::parse("1") == json::from_cbor(std::vector<uint8_t>({0x01})));
+
+        CHECK(json::to_cbor(json::parse("10")) == std::vector<uint8_t>({0x0a}));
+        CHECK(json::parse("10") == json::from_cbor(std::vector<uint8_t>({0x0a})));
+
+        CHECK(json::to_cbor(json::parse("23")) == std::vector<uint8_t>({0x17}));
+        CHECK(json::parse("23") == json::from_cbor(std::vector<uint8_t>({0x17})));
+
+        CHECK(json::to_cbor(json::parse("24")) == std::vector<uint8_t>({0x18, 0x18}));
+        CHECK(json::parse("24") == json::from_cbor(std::vector<uint8_t>({0x18, 0x18})));
+
+        CHECK(json::to_cbor(json::parse("25")) == std::vector<uint8_t>({0x18, 0x19}));
+        CHECK(json::parse("25") == json::from_cbor(std::vector<uint8_t>({0x18, 0x19})));
+
+        CHECK(json::to_cbor(json::parse("100")) == std::vector<uint8_t>({0x18, 0x64}));
+        CHECK(json::parse("100") == json::from_cbor(std::vector<uint8_t>({0x18, 0x64})));
+
+        CHECK(json::to_cbor(json::parse("1000")) == std::vector<uint8_t>({0x19, 0x03, 0xe8}));
+        CHECK(json::parse("1000") == json::from_cbor(std::vector<uint8_t>({0x19, 0x03, 0xe8})));
+
+        CHECK(json::to_cbor(json::parse("1000000")) == std::vector<uint8_t>({0x1a, 0x00, 0x0f, 0x42, 0x40}));
+        CHECK(json::parse("1000000") == json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x0f, 0x42, 0x40})));
+
+        CHECK(json::to_cbor(json::parse("1000000000000")) == std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00}));
+        CHECK(json::parse("1000000000000") == json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00})));
+
+        CHECK(json::to_cbor(json::parse("18446744073709551615")) == std::vector<uint8_t>({0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}));
+        CHECK(json::parse("18446744073709551615") == json::from_cbor(std::vector<uint8_t>({0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})));
+
+        // positive bignum is not supported
+        //CHECK(json::to_cbor(json::parse("18446744073709551616")) == std::vector<uint8_t>({0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}));
+        //CHECK(json::parse("18446744073709551616") == json::from_cbor(std::vector<uint8_t>({0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})));
+
+        //CHECK(json::to_cbor(json::parse("-18446744073709551616")) == std::vector<uint8_t>({0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}));
+        //CHECK(json::parse("-18446744073709551616") == json::from_cbor(std::vector<uint8_t>({0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})));
+
+        // negative bignum is not supported
+        //CHECK(json::to_cbor(json::parse("-18446744073709551617")) == std::vector<uint8_t>({0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}));
+        //CHECK(json::parse("-18446744073709551617") == json::from_cbor(std::vector<uint8_t>({0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})));
+
+        CHECK(json::to_cbor(json::parse("-1")) == std::vector<uint8_t>({0x20}));
+        CHECK(json::parse("-1") == json::from_cbor(std::vector<uint8_t>({0x20})));
+
+        CHECK(json::to_cbor(json::parse("-10")) == std::vector<uint8_t>({0x29}));
+        CHECK(json::parse("-10") == json::from_cbor(std::vector<uint8_t>({0x29})));
+
+        CHECK(json::to_cbor(json::parse("-100")) == std::vector<uint8_t>({0x38, 0x63}));
+        CHECK(json::parse("-100") == json::from_cbor(std::vector<uint8_t>({0x38, 0x63})));
+
+        CHECK(json::to_cbor(json::parse("-1000")) == std::vector<uint8_t>({0x39, 0x03, 0xe7}));
+        CHECK(json::parse("-1000") == json::from_cbor(std::vector<uint8_t>({0x39, 0x03, 0xe7})));
+
+        // half-precision float
+        //CHECK(json::to_cbor(json::parse("0.0")) == std::vector<uint8_t>({0xf9, 0x00, 0x00}));
+        CHECK(json::parse("0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x00})));
+
+        // half-precision float
+        //CHECK(json::to_cbor(json::parse("-0.0")) == std::vector<uint8_t>({0xf9, 0x80, 0x00}));
+        CHECK(json::parse("-0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00})));
+
+        // half-precision float
+        //CHECK(json::to_cbor(json::parse("1.0")) == std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
+        CHECK(json::parse("1.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00})));
+
+        CHECK(json::to_cbor(json::parse("1.1")) == std::vector<uint8_t>({0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a}));
+        CHECK(json::parse("1.1") == json::from_cbor(std::vector<uint8_t>({0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a})));
+
+        // half-precision float
+        //CHECK(json::to_cbor(json::parse("1.5")) == std::vector<uint8_t>({0xf9, 0x3e, 0x00}));
+        CHECK(json::parse("1.5") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3e, 0x00})));
+
+        // half-precision float
+        //CHECK(json::to_cbor(json::parse("65504.0")) == std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
+        CHECK(json::parse("65504.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff})));
+
+        //CHECK(json::to_cbor(json::parse("100000.0")) == std::vector<uint8_t>({0xfa, 0x47, 0xc3, 0x50, 0x00}));
+        CHECK(json::parse("100000.0") == json::from_cbor(std::vector<uint8_t>({0xfa, 0x47, 0xc3, 0x50, 0x00})));
+
+        //CHECK(json::to_cbor(json::parse("3.4028234663852886e+38")) == std::vector<uint8_t>({0xfa, 0x7f, 0x7f, 0xff, 0xff}));
+        CHECK(json::parse("3.4028234663852886e+38") == json::from_cbor(std::vector<uint8_t>({0xfa, 0x7f, 0x7f, 0xff, 0xff})));
+
+        CHECK(json::to_cbor(json::parse("1.0e+300")) == std::vector<uint8_t>({0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c}));
+        CHECK(json::parse("1.0e+300") == json::from_cbor(std::vector<uint8_t>({0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c})));
+
+        // half-precision float
+        //CHECK(json::to_cbor(json::parse("5.960464477539063e-8")) == std::vector<uint8_t>({0xf9, 0x00, 0x01}));
+        CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
+
+        // half-precision float
+        //CHECK(json::to_cbor(json::parse("0.00006103515625")) == std::vector<uint8_t>({0xf9, 0x04, 0x00}));
+        CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
+
+        // half-precision float
+        //CHECK(json::to_cbor(json::parse("-4.0")) == std::vector<uint8_t>({0xf9, 0xc4, 0x00}));
+        CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
+
+        CHECK(json::to_cbor(json::parse("-4.1")) == std::vector<uint8_t>({0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}));
+        CHECK(json::parse("-4.1") == json::from_cbor(std::vector<uint8_t>({0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66})));
+    }
+
+    SECTION("simple values")
+    {
+        CHECK(json::to_cbor(json::parse("false")) == std::vector<uint8_t>({0xf4}));
+        CHECK(json::parse("false") == json::from_cbor(std::vector<uint8_t>({0xf4})));
+
+        CHECK(json::to_cbor(json::parse("true")) == std::vector<uint8_t>({0xf5}));
+        CHECK(json::parse("true") == json::from_cbor(std::vector<uint8_t>({0xf5})));
+
+        CHECK(json::to_cbor(json::parse("true")) == std::vector<uint8_t>({0xf5}));
+        CHECK(json::parse("true") == json::from_cbor(std::vector<uint8_t>({0xf5})));
+    }
+
+    SECTION("strings")
+    {
+        CHECK(json::to_cbor(json::parse("\"\"")) == std::vector<uint8_t>({0x60}));
+        CHECK(json::parse("\"\"") == json::from_cbor(std::vector<uint8_t>({0x60})));
+
+        CHECK(json::to_cbor(json::parse("\"a\"")) == std::vector<uint8_t>({0x61, 0x61}));
+        CHECK(json::parse("\"a\"") == json::from_cbor(std::vector<uint8_t>({0x61, 0x61})));
+
+        CHECK(json::to_cbor(json::parse("\"IETF\"")) == std::vector<uint8_t>({0x64, 0x49, 0x45, 0x54, 0x46}));
+        CHECK(json::parse("\"IETF\"") == json::from_cbor(std::vector<uint8_t>({0x64, 0x49, 0x45, 0x54, 0x46})));
+
+        CHECK(json::to_cbor(json::parse("\"\\u00fc\"")) == std::vector<uint8_t>({0x62, 0xc3, 0xbc}));
+        CHECK(json::parse("\"\\u00fc\"") == json::from_cbor(std::vector<uint8_t>({0x62, 0xc3, 0xbc})));
+
+        CHECK(json::to_cbor(json::parse("\"\\u6c34\"")) == std::vector<uint8_t>({0x63, 0xe6, 0xb0, 0xb4}));
+        CHECK(json::parse("\"\\u6c34\"") == json::from_cbor(std::vector<uint8_t>({0x63, 0xe6, 0xb0, 0xb4})));
+
+        CHECK(json::to_cbor(json::parse("\"\\ud800\\udd51\"")) == std::vector<uint8_t>({0x64, 0xf0, 0x90, 0x85, 0x91}));
+        CHECK(json::parse("\"\\ud800\\udd51\"") == json::from_cbor(std::vector<uint8_t>({0x64, 0xf0, 0x90, 0x85, 0x91})));
+
+        // indefinite length strings
+        CHECK(json::parse("\"streaming\"") == json::from_cbor(std::vector<uint8_t>({0x7f, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x67, 0xff})));
+    }
+
+    SECTION("arrays")
+    {
+        CHECK(json::to_cbor(json::parse("[]")) == std::vector<uint8_t>({0x80}));
+        CHECK(json::parse("[]") == json::from_cbor(std::vector<uint8_t>({0x80})));
+
+        CHECK(json::to_cbor(json::parse("[1, 2, 3]")) == std::vector<uint8_t>({0x83, 0x01, 0x02, 0x03}));
+        CHECK(json::parse("[1, 2, 3]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x02, 0x03})));
+
+        CHECK(json::to_cbor(json::parse("[1, [2, 3], [4, 5]]")) == std::vector<uint8_t>({0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05}));
+        CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05})));
+
+        CHECK(json::to_cbor(json::parse("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]")) == std::vector<uint8_t>({0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19}));
+        CHECK(json::parse("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]") == json::from_cbor(std::vector<uint8_t>({0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19})));
+
+        // indefinite length arrays
+        CHECK(json::parse("[]") == json::from_cbor(std::vector<uint8_t>({0x9f, 0xff})));
+        CHECK(json::parse("[1, [2, 3], [4, 5]] ") == json::from_cbor(std::vector<uint8_t>({0x9f, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff, 0xff})));
+        CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x9f, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05, 0xff})));
+        CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff})));
+        CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x9f, 0x02, 0x03, 0xff, 0x82, 0x04, 0x05})));
+        CHECK(json::parse("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]") == json::from_cbor(std::vector<uint8_t>({0x9f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0xff})));
+    }
+
+    SECTION("objects")
+    {
+        CHECK(json::to_cbor(json::parse("{}")) == std::vector<uint8_t>({0xa0}));
+        CHECK(json::parse("{}") == json::from_cbor(std::vector<uint8_t>({0xa0})));
+
+        CHECK(json::to_cbor(json::parse("{\"a\": 1, \"b\": [2, 3]}")) == std::vector<uint8_t>({0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03}));
+        CHECK(json::parse("{\"a\": 1, \"b\": [2, 3]}") == json::from_cbor(std::vector<uint8_t>({0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03})));
+
+        CHECK(json::to_cbor(json::parse("[\"a\", {\"b\": \"c\"}]")) == std::vector<uint8_t>({0x82, 0x61, 0x61, 0xa1, 0x61, 0x62, 0x61, 0x63}));
+        CHECK(json::parse("[\"a\", {\"b\": \"c\"}]") == json::from_cbor(std::vector<uint8_t>({0x82, 0x61, 0x61, 0xa1, 0x61, 0x62, 0x61, 0x63})));
+
+        CHECK(json::to_cbor(json::parse("{\"a\": \"A\", \"b\": \"B\", \"c\": \"C\", \"d\": \"D\", \"e\": \"E\"}")) == std::vector<uint8_t>({0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61, 0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61, 0x44, 0x61, 0x65, 0x61, 0x45}));
+        CHECK(json::parse("{\"a\": \"A\", \"b\": \"B\", \"c\": \"C\", \"d\": \"D\", \"e\": \"E\"}") == json::from_cbor(std::vector<uint8_t>({0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61, 0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61, 0x44, 0x61, 0x65, 0x61, 0x45})));
+
+        // indefinite length objects
+        CHECK(json::parse("{\"a\": 1, \"b\": [2, 3]}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x61, 0x61, 0x01, 0x61, 0x62, 0x9f, 0x02, 0x03, 0xff, 0xff})));
+        CHECK(json::parse("[\"a\", {\"b\": \"c\"}]") == json::from_cbor(std::vector<uint8_t>({0x82, 0x61, 0x61, 0xbf, 0x61, 0x62, 0x61, 0x63, 0xff})));
+        CHECK(json::parse("{\"Fun\": true, \"Amt\": -2}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff})));
+    }
+}
diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp
index 2ef6244..2970b86 100644
--- a/test/src/unit-class_const_iterator.cpp
+++ b/test/src/unit-class_const_iterator.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp
index 3d82fce..14c6828 100644
--- a/test/src/unit-class_iterator.cpp
+++ b/test/src/unit-class_iterator.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp
index 22a04b0..6dec3f8 100644
--- a/test/src/unit-class_lexer.cpp
+++ b/test/src/unit-class_lexer.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp
index dad6b1e..7bf23d5 100644
--- a/test/src/unit-class_parser.cpp
+++ b/test/src/unit-class_parser.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-comparison.cpp b/test/src/unit-comparison.cpp
index 582146a..73c31ab 100644
--- a/test/src/unit-comparison.cpp
+++ b/test/src/unit-comparison.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-concepts.cpp b/test/src/unit-concepts.cpp
index 002ccdf..dea6b51 100644
--- a/test/src/unit-concepts.cpp
+++ b/test/src/unit-concepts.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp
index 6804a3a..23c0db3 100644
--- a/test/src/unit-constructor1.cpp
+++ b/test/src/unit-constructor1.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-constructor2.cpp b/test/src/unit-constructor2.cpp
index 1edad6a..0bbd13c 100644
--- a/test/src/unit-constructor2.cpp
+++ b/test/src/unit-constructor2.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-convenience.cpp b/test/src/unit-convenience.cpp
index 8791caf..94341be 100644
--- a/test/src/unit-convenience.cpp
+++ b/test/src/unit-convenience.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp
index 1c49a93..72c3bf6 100644
--- a/test/src/unit-conversions.cpp
+++ b/test/src/unit-conversions.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp
index 969a775..605c596 100644
--- a/test/src/unit-deserialization.cpp
+++ b/test/src/unit-deserialization.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp
index d3b9ed4..0a1715e 100644
--- a/test/src/unit-element_access1.cpp
+++ b/test/src/unit-element_access1.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp
index ed1348f..29be17a 100644
--- a/test/src/unit-element_access2.cpp
+++ b/test/src/unit-element_access2.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp
index d373c10..1660c71 100644
--- a/test/src/unit-inspection.cpp
+++ b/test/src/unit-inspection.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-iterator_wrapper.cpp b/test/src/unit-iterator_wrapper.cpp
index af1fa08..96928eb 100644
--- a/test/src/unit-iterator_wrapper.cpp
+++ b/test/src/unit-iterator_wrapper.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp
index d51c454..60f7c2f 100644
--- a/test/src/unit-iterators1.cpp
+++ b/test/src/unit-iterators1.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp
index f231c8e..da0fc93 100644
--- a/test/src/unit-iterators2.cpp
+++ b/test/src/unit-iterators2.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp
index 9a40ce7..880bc46 100644
--- a/test/src/unit-json_patch.cpp
+++ b/test/src/unit-json_patch.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp
index 35558d2..91d003a 100644
--- a/test/src/unit-json_pointer.cpp
+++ b/test/src/unit-json_pointer.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp
index 08a6dd3..02ffa6a 100644
--- a/test/src/unit-modifiers.cpp
+++ b/test/src/unit-modifiers.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp
new file mode 100644
index 0000000..46997e2
--- /dev/null
+++ b/test/src/unit-msgpack.cpp
@@ -0,0 +1,1216 @@
+/*
+    __ _____ _____ _____
+ __|  |   __|     |   | |  JSON for Modern C++ (test suite)
+|  |  |__   |  |  | | | |  version 2.0.9
+|_____|_____|_____|_|___|  https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
+
+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.
+*/
+
+#include "catch.hpp"
+
+#include "json.hpp"
+using nlohmann::json;
+
+#include <fstream>
+
+TEST_CASE("MessagePack")
+{
+    SECTION("individual values")
+    {
+        SECTION("discarded")
+        {
+            // discarded values are not serialized
+            json j = json::value_t::discarded;
+            const auto result = json::to_msgpack(j);
+            CHECK(result.empty());
+        }
+
+        SECTION("null")
+        {
+            json j = nullptr;
+            std::vector<uint8_t> expected = {0xc0};
+            const auto result = json::to_msgpack(j);
+            CHECK(result == expected);
+
+            // roundtrip
+            CHECK(json::from_msgpack(result) == j);
+        }
+
+        SECTION("boolean")
+        {
+            SECTION("true")
+            {
+                json j = true;
+                std::vector<uint8_t> expected = {0xc3};
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("false")
+            {
+                json j = false;
+                std::vector<uint8_t> expected = {0xc2};
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+        }
+
+        SECTION("number")
+        {
+            SECTION("signed")
+            {
+                SECTION("-32..-1 (negative fixnum)")
+                {
+                    for (auto i = -32; i <= -1; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 1);
+
+                        // check individual bytes
+                        CHECK(static_cast<int8_t>(result[0]) == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("0..127 (positive fixnum)")
+                {
+                    for (size_t i = 0; i <= 127; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 1);
+
+                        // check individual bytes
+                        CHECK(result[0] == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("128..255 (int 8)")
+                {
+                    for (size_t i = 128; i <= 255; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xcc);
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 2);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xcc);
+                        uint8_t restored = static_cast<uint8_t>(result[1]);
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("256..65535 (int 16)")
+                {
+                    for (size_t i = 256; i <= 65535; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xcd);
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 3);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xcd);
+                        uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("65536..4294967295 (int 32)")
+                {
+                    for (uint32_t i :
+                            {
+                                65536u, 77777u, 1048576u, 4294967295u
+                            })
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xce);
+                        expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 5);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xce);
+                        uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+                                            (static_cast<uint32_t>(result[2]) << 020) +
+                                            (static_cast<uint32_t>(result[3]) << 010) +
+                                            static_cast<uint32_t>(result[4]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("4294967296..9223372036854775807 (int 64)")
+                {
+                    for (uint64_t i :
+                            {
+                                4294967296lu, 9223372036854775807lu
+                            })
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = -1;
+                        j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xcf);
+                        expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 9);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xcf);
+                        uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+                                            (static_cast<uint64_t>(result[2]) << 060) +
+                                            (static_cast<uint64_t>(result[3]) << 050) +
+                                            (static_cast<uint64_t>(result[4]) << 040) +
+                                            (static_cast<uint64_t>(result[5]) << 030) +
+                                            (static_cast<uint64_t>(result[6]) << 020) +
+                                            (static_cast<uint64_t>(result[7]) << 010) +
+                                            static_cast<uint64_t>(result[8]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("-128..-33 (int 8)")
+                {
+                    for (auto i = -128; i <= -33; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xd0);
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 2);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xd0);
+                        CHECK(static_cast<int8_t>(result[1]) == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("-9263 (int 16)")
+                {
+                    json j = -9263;
+                    std::vector<uint8_t> expected = {0xd1, 0xdb, 0xd1};
+
+                    const auto result = json::to_msgpack(j);
+                    CHECK(result == expected);
+
+                    int16_t restored = (result[1] << 8) + result[2];
+                    CHECK(restored == -9263);
+
+                    // roundtrip
+                    CHECK(json::from_msgpack(result) == j);
+                }
+
+                SECTION("-32768..-129 (int 16)")
+                {
+                    for (int16_t i = -32768; i <= -129; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xd1);
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 3);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xd1);
+                        int16_t restored = (result[1] << 8) + result[2];
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("-32769..-2147483648")
+                {
+                    std::vector<int32_t> numbers;
+                    numbers.push_back(-32769);
+                    numbers.push_back(-65536);
+                    numbers.push_back(-77777);
+                    numbers.push_back(-1048576);
+                    numbers.push_back(-2147483648);
+                    for (auto i : numbers)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xd2);
+                        expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 5);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xd2);
+                        uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+                                            (static_cast<uint32_t>(result[2]) << 020) +
+                                            (static_cast<uint32_t>(result[3]) << 010) +
+                                            static_cast<uint32_t>(result[4]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("-9223372036854775808..-2147483649 (int 64)")
+                {
+                    std::vector<int64_t> numbers;
+                    numbers.push_back(INT64_MIN);
+                    numbers.push_back(-2147483649ll);
+                    for (auto i : numbers)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_integer());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xd3);
+                        expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 9);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xd3);
+                        int64_t restored = static_cast<int64_t>((static_cast<int64_t>(result[1]) << 070) +
+                                                                (static_cast<int64_t>(result[2]) << 060) +
+                                                                (static_cast<int64_t>(result[3]) << 050) +
+                                                                (static_cast<int64_t>(result[4]) << 040) +
+                                                                (static_cast<int64_t>(result[5]) << 030) +
+                                                                (static_cast<int64_t>(result[6]) << 020) +
+                                                                (static_cast<int64_t>(result[7]) << 010) +
+                                                                static_cast<int64_t>(result[8]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+            }
+
+            SECTION("unsigned")
+            {
+                SECTION("0..127 (positive fixnum)")
+                {
+                    for (size_t i = 0; i <= 127; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 1);
+
+                        // check individual bytes
+                        CHECK(result[0] == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("128..255 (uint 8)")
+                {
+                    for (size_t i = 128; i <= 255; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xcc);
+                        expected.push_back(static_cast<uint8_t>(i));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 2);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xcc);
+                        uint8_t restored = static_cast<uint8_t>(result[1]);
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("256..65535 (uint 16)")
+                {
+                    for (size_t i = 256; i <= 65535; ++i)
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xcd);
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 3);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xcd);
+                        uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("65536..4294967295 (uint 32)")
+                {
+                    for (uint32_t i :
+                            {
+                                65536u, 77777u, 1048576u, 4294967295u
+                            })
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xce);
+                        expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 5);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xce);
+                        uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+                                            (static_cast<uint32_t>(result[2]) << 020) +
+                                            (static_cast<uint32_t>(result[3]) << 010) +
+                                            static_cast<uint32_t>(result[4]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+
+                SECTION("4294967296..18446744073709551615 (uint 64)")
+                {
+                    for (uint64_t i :
+                            {
+                                4294967296lu, 18446744073709551615lu
+                            })
+                    {
+                        CAPTURE(i);
+
+                        // create JSON value with unsigned integer number
+                        json j = i;
+
+                        // check type
+                        CHECK(j.is_number_unsigned());
+
+                        // create expected byte vector
+                        std::vector<uint8_t> expected;
+                        expected.push_back(0xcf);
+                        expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+                        expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+                        expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+                        // compare result + size
+                        const auto result = json::to_msgpack(j);
+                        CHECK(result == expected);
+                        CHECK(result.size() == 9);
+
+                        // check individual bytes
+                        CHECK(result[0] == 0xcf);
+                        uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+                                            (static_cast<uint64_t>(result[2]) << 060) +
+                                            (static_cast<uint64_t>(result[3]) << 050) +
+                                            (static_cast<uint64_t>(result[4]) << 040) +
+                                            (static_cast<uint64_t>(result[5]) << 030) +
+                                            (static_cast<uint64_t>(result[6]) << 020) +
+                                            (static_cast<uint64_t>(result[7]) << 010) +
+                                            static_cast<uint64_t>(result[8]));
+                        CHECK(restored == i);
+
+                        // roundtrip
+                        CHECK(json::from_msgpack(result) == j);
+                    }
+                }
+            }
+
+            SECTION("float")
+            {
+                SECTION("3.1415925")
+                {
+                    double v = 3.1415925;
+                    json j = v;
+                    std::vector<uint8_t> expected =
+                    {
+                        0xcb, 0x40, 0x09, 0x21, 0xfb, 0x3f, 0xa6, 0xde, 0xfc
+                    };
+                    const auto result = json::to_msgpack(j);
+                    CHECK(result == expected);
+
+                    // restore value (reverse array for endianess)
+                    double restored;
+                    std::reverse(expected.begin(), expected.end());
+                    memcpy(&restored, expected.data(), sizeof(double));
+                    CHECK(restored == v);
+
+                    // roundtrip
+                    CHECK(json::from_msgpack(result) == j);
+                }
+            }
+        }
+
+        SECTION("string")
+        {
+            SECTION("N = 0..31")
+            {
+                // explicitly enumerate the first byte for all 32 strings
+                const std::vector<uint8_t> first_bytes =
+                {
+                    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+                    0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1,
+                    0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
+                    0xbb, 0xbc, 0xbd, 0xbe, 0xbf
+                };
+
+                for (size_t N = 0; N < first_bytes.size(); ++N)
+                {
+                    CAPTURE(N);
+
+                    // create JSON value with string containing of N * 'x'
+                    const auto s = std::string(N, 'x');
+                    json j = s;
+
+                    // create expected byte vector
+                    std::vector<uint8_t> expected;
+                    expected.push_back(first_bytes[N]);
+                    for (size_t i = 0; i < N; ++i)
+                    {
+                        expected.push_back('x');
+                    }
+
+                    // check first byte
+                    CHECK((first_bytes[N] & 0x1f) == N);
+
+                    // compare result + size
+                    const auto result = json::to_msgpack(j);
+                    CHECK(result == expected);
+                    CHECK(result.size() == N + 1);
+                    // check that no null byte is appended
+                    if (N > 0)
+                    {
+                        CHECK(result.back() != '\x00');
+                    }
+
+                    // roundtrip
+                    CHECK(json::from_msgpack(result) == j);
+                }
+            }
+
+            SECTION("N = 32..255")
+            {
+                for (size_t N = 32; N <= 255; ++N)
+                {
+                    CAPTURE(N);
+
+                    // create JSON value with string containing of N * 'x'
+                    const auto s = std::string(N, 'x');
+                    json j = s;
+
+                    // create expected byte vector
+                    std::vector<uint8_t> expected;
+                    expected.push_back(0xd9);
+                    expected.push_back(static_cast<uint8_t>(N));
+                    for (size_t i = 0; i < N; ++i)
+                    {
+                        expected.push_back('x');
+                    }
+
+                    // compare result + size
+                    const auto result = json::to_msgpack(j);
+                    CHECK(result == expected);
+                    CHECK(result.size() == N + 2);
+                    // check that no null byte is appended
+                    CHECK(result.back() != '\x00');
+
+                    // roundtrip
+                    CHECK(json::from_msgpack(result) == j);
+                }
+            }
+
+            SECTION("N = 256..65535")
+            {
+                for (size_t N :
+                        {
+                            256u, 999u, 1025u, 3333u, 2048u, 65535u
+                        })
+                {
+                    CAPTURE(N);
+
+                    // create JSON value with string containing of N * 'x'
+                    const auto s = std::string(N, 'x');
+                    json j = s;
+
+                    // create expected byte vector (hack: create string first)
+                    std::vector<uint8_t> expected(N, 'x');
+                    // reverse order of commands, because we insert at begin()
+                    expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
+                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
+                    expected.insert(expected.begin(), 0xda);
+
+                    // compare result + size
+                    const auto result = json::to_msgpack(j);
+                    CHECK(result == expected);
+                    CHECK(result.size() == N + 3);
+                    // check that no null byte is appended
+                    CHECK(result.back() != '\x00');
+
+                    // roundtrip
+                    CHECK(json::from_msgpack(result) == j);
+                }
+            }
+
+            SECTION("N = 65536..4294967295")
+            {
+                for (size_t N :
+                        {
+                            65536u, 77777u, 1048576u
+                        })
+                {
+                    CAPTURE(N);
+
+                    // create JSON value with string containing of N * 'x'
+                    const auto s = std::string(N, 'x');
+                    json j = s;
+
+                    // create expected byte vector (hack: create string first)
+                    std::vector<uint8_t> expected(N, 'x');
+                    // reverse order of commands, because we insert at begin()
+                    expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
+                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
+                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
+                    expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
+                    expected.insert(expected.begin(), 0xdb);
+
+                    // compare result + size
+                    const auto result = json::to_msgpack(j);
+                    CHECK(result == expected);
+                    CHECK(result.size() == N + 5);
+                    // check that no null byte is appended
+                    CHECK(result.back() != '\x00');
+
+                    // roundtrip
+                    CHECK(json::from_msgpack(result) == j);
+                }
+            }
+        }
+
+        SECTION("array")
+        {
+            SECTION("empty")
+            {
+                json j = json::array();
+                std::vector<uint8_t> expected = {0x90};
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("[null]")
+            {
+                json j = {nullptr};
+                std::vector<uint8_t> expected = {0x91, 0xc0};
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("[1,2,3,4,5]")
+            {
+                json j = json::parse("[1,2,3,4,5]");
+                std::vector<uint8_t> expected = {0x95, 0x01, 0x02, 0x03, 0x04, 0x05};
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("[[[[]]]]")
+            {
+                json j = json::parse("[[[[]]]]");
+                std::vector<uint8_t> expected = {0x91, 0x91, 0x91, 0x90};
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("array 16")
+            {
+                json j(16, nullptr);
+                std::vector<uint8_t> expected(j.size() + 3, 0xc0); // all null
+                expected[0] = 0xdc; // array 16
+                expected[1] = 0x00; // size (0x0010), byte 0
+                expected[2] = 0x10; // size (0x0010), byte 1
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("array 32")
+            {
+                json j(65536, nullptr);
+                std::vector<uint8_t> expected(j.size() + 5, 0xc0); // all null
+                expected[0] = 0xdd; // array 32
+                expected[1] = 0x00; // size (0x00100000), byte 0
+                expected[2] = 0x01; // size (0x00100000), byte 1
+                expected[3] = 0x00; // size (0x00100000), byte 2
+                expected[4] = 0x00; // size (0x00100000), byte 3
+                const auto result = json::to_msgpack(j);
+                //CHECK(result == expected);
+
+                CHECK(result.size() == expected.size());
+                for (size_t i = 0; i < expected.size(); ++i)
+                {
+                    CAPTURE(i);
+                    CHECK(result[i] == expected[i]);
+                }
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+        }
+
+        SECTION("object")
+        {
+            SECTION("empty")
+            {
+                json j = json::object();
+                std::vector<uint8_t> expected = {0x80};
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("{\"\":null}")
+            {
+                json j = {{"", nullptr}};
+                std::vector<uint8_t> expected = {0x81, 0xa0, 0xc0};
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
+            {
+                json j = json::parse("{\"a\": {\"b\": {\"c\": {}}}}");
+                std::vector<uint8_t> expected =
+                {
+                    0x81, 0xa1, 0x61, 0x81, 0xa1, 0x62, 0x81, 0xa1, 0x63, 0x80
+                };
+                const auto result = json::to_msgpack(j);
+                CHECK(result == expected);
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("map 16")
+            {
+                json j = R"({"00": null, "01": null, "02": null, "03": null,
+                             "04": null, "05": null, "06": null, "07": null,
+                             "08": null, "09": null, "10": null, "11": null,
+                             "12": null, "13": null, "14": null, "15": null})"_json;
+
+                const auto result = json::to_msgpack(j);
+
+                // Checking against an expected vector byte by byte is
+                // difficult, because no assumption on the order of key/value
+                // pairs are made. We therefore only check the prefix (type and
+                // size and the overall size. The rest is then handled in the
+                // roundtrip check.
+                CHECK(result.size() == 67); // 1 type, 2 size, 16*4 content
+                CHECK(result[0] == 0xde); // map 16
+                CHECK(result[1] == 0x00); // byte 0 of size (0x0010)
+                CHECK(result[2] == 0x10); // byte 1 of size (0x0010)
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+
+            SECTION("map 32")
+            {
+                json j;
+                for (auto i = 0; i < 65536; ++i)
+                {
+                    // format i to a fixed width of 5
+                    // each entry will need 7 bytes: 6 for fixstr, 1 for null
+                    std::stringstream ss;
+                    ss << std::setw(5) << std::setfill('0') << i;
+                    j.emplace(ss.str(), nullptr);
+                }
+
+                const auto result = json::to_msgpack(j);
+
+                // Checking against an expected vector byte by byte is
+                // difficult, because no assumption on the order of key/value
+                // pairs are made. We therefore only check the prefix (type and
+                // size and the overall size. The rest is then handled in the
+                // roundtrip check.
+                CHECK(result.size() == 458757); // 1 type, 4 size, 65536*7 content
+                CHECK(result[0] == 0xdf); // map 32
+                CHECK(result[1] == 0x00); // byte 0 of size (0x00010000)
+                CHECK(result[2] == 0x01); // byte 1 of size (0x00010000)
+                CHECK(result[3] == 0x00); // byte 2 of size (0x00010000)
+                CHECK(result[4] == 0x00); // byte 3 of size (0x00010000)
+
+                // roundtrip
+                CHECK(json::from_msgpack(result) == j);
+            }
+        }
+    }
+
+    SECTION("from float32")
+    {
+        auto given = std::vector<uint8_t>({0xca, 0x41, 0xc8, 0x00, 0x01});
+        json j = json::from_msgpack(given);
+        CHECK(j.get<double>() == Approx(25.0000019073486));
+    }
+}
+
+
+// use this testcase outside [hide] to run it with Valgrind
+TEST_CASE("single MessagePack roundtrip")
+{
+    SECTION("sample.json")
+    {
+        std::string filename = "test/data/json_testsuite/sample.json";
+
+        // parse JSON file
+        std::ifstream f_json(filename);
+        json j1 = json::parse(f_json);
+
+        // parse MessagePack file
+        std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
+        std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_msgpack)),
+                                    std::istreambuf_iterator<char>());
+        json j2;
+        CHECK_NOTHROW(j2 = json::from_msgpack(packed));
+
+        // compare parsed JSON values
+        CHECK(j1 == j2);
+    }
+}
+
+
+TEST_CASE("MessagePack roundtrips", "[hide]")
+{
+    SECTION("input from msgpack-python")
+    {
+        for (std::string filename :
+                {
+                    "test/data/json_nlohmann_tests/all_unicode.json",
+                    "test/data/json.org/1.json",
+                    "test/data/json.org/2.json",
+                    "test/data/json.org/3.json",
+                    "test/data/json.org/4.json",
+                    "test/data/json.org/5.json",
+                    "test/data/json_roundtrip/roundtrip01.json",
+                    "test/data/json_roundtrip/roundtrip02.json",
+                    "test/data/json_roundtrip/roundtrip03.json",
+                    "test/data/json_roundtrip/roundtrip04.json",
+                    "test/data/json_roundtrip/roundtrip05.json",
+                    "test/data/json_roundtrip/roundtrip06.json",
+                    "test/data/json_roundtrip/roundtrip07.json",
+                    "test/data/json_roundtrip/roundtrip08.json",
+                    "test/data/json_roundtrip/roundtrip09.json",
+                    "test/data/json_roundtrip/roundtrip10.json",
+                    "test/data/json_roundtrip/roundtrip11.json",
+                    "test/data/json_roundtrip/roundtrip12.json",
+                    "test/data/json_roundtrip/roundtrip13.json",
+                    "test/data/json_roundtrip/roundtrip14.json",
+                    "test/data/json_roundtrip/roundtrip15.json",
+                    "test/data/json_roundtrip/roundtrip16.json",
+                    "test/data/json_roundtrip/roundtrip17.json",
+                    "test/data/json_roundtrip/roundtrip18.json",
+                    "test/data/json_roundtrip/roundtrip19.json",
+                    "test/data/json_roundtrip/roundtrip20.json",
+                    "test/data/json_roundtrip/roundtrip21.json",
+                    "test/data/json_roundtrip/roundtrip22.json",
+                    "test/data/json_roundtrip/roundtrip23.json",
+                    "test/data/json_roundtrip/roundtrip24.json",
+                    "test/data/json_roundtrip/roundtrip25.json",
+                    "test/data/json_roundtrip/roundtrip26.json",
+                    "test/data/json_roundtrip/roundtrip27.json",
+                    "test/data/json_roundtrip/roundtrip28.json",
+                    "test/data/json_roundtrip/roundtrip29.json",
+                    "test/data/json_roundtrip/roundtrip30.json",
+                    "test/data/json_roundtrip/roundtrip31.json",
+                    "test/data/json_roundtrip/roundtrip32.json",
+                    "test/data/json_testsuite/sample.json", // kills AppVeyor
+                    "test/data/json_tests/pass1.json",
+                    "test/data/json_tests/pass2.json",
+                    "test/data/json_tests/pass3.json",
+                    "test/data/regression/floats.json",
+                    "test/data/regression/signed_ints.json",
+                    "test/data/regression/unsigned_ints.json",
+                    "test/data/regression/working_file.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_empty.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_false.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_null.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_0e1.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_after_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json",
+                    //"test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json",
+                    //"test/data/nst_json_testsuite/test_parsing/y_number_too_big_pos_int.json",
+                    //"test/data/nst_json_testsuite/test_parsing/y_number_very_big_negative_int.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_basic.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_empty.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_simple.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_comments.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_in_array.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_pi.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_space.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json",
+                    // "test/data/nst_json_testsuite/test_parsing/y_string_utf16.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_utf8.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json",
+                    "test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json"
+                })
+        {
+            CAPTURE(filename);
+
+            // parse JSON file
+            std::ifstream f_json(filename);
+            json j1 = json::parse(f_json);
+
+            // parse MessagePack file
+            std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
+            std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_msgpack)),
+                                        std::istreambuf_iterator<char>());
+            json j2;
+            CHECK_NOTHROW(j2 = json::from_msgpack(packed));
+
+            // compare parsed JSON values
+            CHECK(j1 == j2);
+        }
+    }
+}
diff --git a/test/src/unit-pointer_access.cpp b/test/src/unit-pointer_access.cpp
index 5d5eb16..e1c9caa 100644
--- a/test/src/unit-pointer_access.cpp
+++ b/test/src/unit-pointer_access.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp
index 07f3636..92b1322 100644
--- a/test/src/unit-readme.cpp
+++ b/test/src/unit-readme.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp
index a036d2f..4a8047f 100644
--- a/test/src/unit-reference_access.cpp
+++ b/test/src/unit-reference_access.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index e04513c..1e720dd 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -516,4 +516,28 @@
         CHECK_THROWS_AS(j << ss, std::invalid_argument);
         CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input");
     }
+
+    SECTION("issue #389 - Integer-overflow (OSS-Fuzz issue 267)")
+    {
+        // original test case
+        json j1 = json::parse("-9223372036854775808");
+        CHECK(j1.is_number_integer());
+        CHECK(j1.get<json::number_integer_t>() == INT64_MIN);
+
+        // edge case (+1; still an integer)
+        json j2 = json::parse("-9223372036854775807");
+        CHECK(j2.is_number_integer());
+        CHECK(j2.get<json::number_integer_t>() == INT64_MIN + 1);
+
+        // edge case (-1; overflow -> floats)
+        json j3 = json::parse("-9223372036854775809");
+        CHECK(j3.is_number_float());
+    }
+
+    SECTION("issue #380 - bug in overflow detection when parsing integers")
+    {
+        json j = json::parse("166020696663385964490");
+        CHECK(j.is_number_float());
+        CHECK(j.dump() == "1.66020696663386e+20");
+    }
 }
diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp
index 0c80038..8385a4a 100644
--- a/test/src/unit-serialization.cpp
+++ b/test/src/unit-serialization.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp
index c41c478..92b6e5a 100644
--- a/test/src/unit-testsuites.cpp
+++ b/test/src/unit-testsuites.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp
index 0e49757..4cb51e2 100644
--- a/test/src/unit-unicode.cpp
+++ b/test/src/unit-unicode.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit.cpp b/test/src/unit.cpp
index 7b93c38..1a27886 100644
--- a/test/src/unit.cpp
+++ b/test/src/unit.cpp
@@ -1,7 +1,7 @@
 /*
     __ _____ _____ _____
  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
-|  |  |__   |  |  | | | |  version 2.0.8
+|  |  |__   |  |  | | | |  version 2.0.9
 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
 Licensed under the MIT License <http://opensource.org/licenses/MIT>.