//     __ _____ _____ _____
//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
// |  |  |__   |  |  | | | |  version 3.12.0
// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT

// cmake/test.cmake selects the C++ standard versions with which to build a
// unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
// When using macros that are only defined for particular versions of the standard
// (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
// version macro in a comment close by, like this:
// JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)

#include "doctest_compatibility.h"

#include <nlohmann/json.hpp>
using nlohmann::json;

#if JSON_HAS_RANGES
    #include <algorithm>
    #include <ranges>
#endif

TEST_CASE("iterators 2")
{
    SECTION("iterator comparisons")
    {
        json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};

        for (json& j : j_values)
        {
            auto it1 = j.begin();
            auto it2 = j.begin();
            auto it3 = j.begin();
            ++it2;
            ++it3;
            ++it3;
            auto it1_c = j.cbegin();
            auto it2_c = j.cbegin();
            auto it3_c = j.cbegin();
            ++it2_c;
            ++it3_c;
            ++it3_c;

            // comparison: equal
            {
                CHECK(it1 == it1);
                CHECK(!(it1 == it2));
                CHECK(!(it1 == it3));
                CHECK(!(it2 == it3));
                CHECK(it1_c == it1_c);
                CHECK(!(it1_c == it2_c));
                CHECK(!(it1_c == it3_c));
                CHECK(!(it2_c == it3_c));
            }

            // comparison: not equal
            {
                // check definition
                CHECK( (it1 != it1) == !(it1 == it1) );
                CHECK( (it1 != it2) == !(it1 == it2) );
                CHECK( (it1 != it3) == !(it1 == it3) );
                CHECK( (it2 != it3) == !(it2 == it3) );
                CHECK( (it1_c != it1_c) == !(it1_c == it1_c) );
                CHECK( (it1_c != it2_c) == !(it1_c == it2_c) );
                CHECK( (it1_c != it3_c) == !(it1_c == it3_c) );
                CHECK( (it2_c != it3_c) == !(it2_c == it3_c) );
            }

            // comparison: smaller
            {
                if (j.type() == json::value_t::object)
                {
#if JSON_DIAGNOSTICS
                    CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
#else
                    CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
#endif
                }
                else
                {
                    CHECK(!(it1 < it1));
                    CHECK(it1 < it2);
                    CHECK(it1 < it3);
                    CHECK(it2 < it3);
                    CHECK(!(it1_c < it1_c));
                    CHECK(it1_c < it2_c);
                    CHECK(it1_c < it3_c);
                    CHECK(it2_c < it3_c);
                }
            }

            // comparison: less than or equal
            {
                if (j.type() == json::value_t::object)
                {
#if JSON_DIAGNOSTICS
                    CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
#else
                    CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
#endif
                }
                else
                {
                    // check definition
                    CHECK( (it1 <= it1) == !(it1 < it1) );
                    CHECK( (it1 <= it2) == !(it2 < it1) );
                    CHECK( (it1 <= it3) == !(it3 < it1) );
                    CHECK( (it2 <= it3) == !(it3 < it2) );
                    CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) );
                    CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) );
                    CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) );
                    CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) );
                }
            }

            // comparison: greater than
            {
                if (j.type() == json::value_t::object)
                {
#if JSON_DIAGNOSTICS
                    CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
#else
                    CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
#endif
                }
                else
                {
                    // check definition
                    CHECK( (it1 > it1) == (it1 < it1) );
                    CHECK( (it1 > it2) == (it2 < it1) );
                    CHECK( (it1 > it3) == (it3 < it1) );
                    CHECK( (it2 > it3) == (it3 < it2) );
                    CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
                    CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
                    CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
                    CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
                }
            }

            // comparison: greater than or equal
            {
                if (j.type() == json::value_t::object)
                {
#if JSON_DIAGNOSTICS
                    CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
#else
                    CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
#endif
                }
                else
                {
                    // check definition
                    CHECK( (it1 >= it1) == !(it1 < it1) );
                    CHECK( (it1 >= it2) == !(it1 < it2) );
                    CHECK( (it1 >= it3) == !(it1 < it3) );
                    CHECK( (it2 >= it3) == !(it2 < it3) );
                    CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) );
                    CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) );
                    CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) );
                    CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) );
                }
            }
        }

        // check exceptions if different objects are compared
        for (auto j : j_values)
        {
            for (auto k : j_values)
            {
                if (j != k)
                {
#if JSON_DIAGNOSTICS
                    // the output differs in each loop, so we cannot fix a string for the expected exception
#else
                    CHECK_THROWS_WITH_AS(j.begin() == k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(j.cbegin() == k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(j.begin() < k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(j.cbegin() < k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
#endif
                }
            }
        }
    }

    SECTION("iterator arithmetic")
    {
        json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
        json j_array = {1, 2, 3, 4, 5, 6};
        json j_null = nullptr;
        json j_value = 42;

        SECTION("addition and subtraction")
        {
            SECTION("object")
            {
                {
                    auto it = j_object.begin();
                    CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.cbegin();
                    CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.begin();
                    CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.cbegin();
                    CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.begin();
                    CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.cbegin();
                    CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.begin();
                    CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.cbegin();
                    CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.begin();
                    CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.cbegin();
                    CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.begin();
                    CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.cbegin();
                    CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
            }

            SECTION("array")
            {
                {
                    auto it = j_array.begin();
                    it += 3;
                    CHECK((j_array.begin() + 3) == it);
                    CHECK((3 + j_array.begin()) == it);
                    CHECK((it - 3) == j_array.begin());
                    CHECK((it - j_array.begin()) == 3);
                    CHECK(*it == json(4));
                    it -= 2;
                    CHECK(*it == json(2));
                }
                {
                    auto it = j_array.cbegin();
                    it += 3;
                    CHECK((j_array.cbegin() + 3) == it);
                    CHECK((3 + j_array.cbegin()) == it);
                    CHECK((it - 3) == j_array.cbegin());
                    CHECK((it - j_array.cbegin()) == 3);
                    CHECK(*it == json(4));
                    it -= 2;
                    CHECK(*it == json(2));
                }
            }

            SECTION("null")
            {
                {
                    auto it = j_null.begin();
                    it += 3;
                    CHECK((j_null.begin() + 3) == it);
                    CHECK((3 + j_null.begin()) == it);
                    CHECK((it - 3) == j_null.begin());
                    CHECK((it - j_null.begin()) == 3);
                    CHECK(it != j_null.end());
                    it -= 3;
                    CHECK(it == j_null.end());
                }
                {
                    auto it = j_null.cbegin();
                    it += 3;
                    CHECK((j_null.cbegin() + 3) == it);
                    CHECK((3 + j_null.cbegin()) == it);
                    CHECK((it - 3) == j_null.cbegin());
                    CHECK((it - j_null.cbegin()) == 3);
                    CHECK(it != j_null.cend());
                    it -= 3;
                    CHECK(it == j_null.cend());
                }
            }

            SECTION("value")
            {
                {
                    auto it = j_value.begin();
                    it += 3;
                    CHECK((j_value.begin() + 3) == it);
                    CHECK((3 + j_value.begin()) == it);
                    CHECK((it - 3) == j_value.begin());
                    CHECK((it - j_value.begin()) == 3);
                    CHECK(it != j_value.end());
                    it -= 3;
                    CHECK(*it == json(42));
                }
                {
                    auto it = j_value.cbegin();
                    it += 3;
                    CHECK((j_value.cbegin() + 3) == it);
                    CHECK((3 + j_value.cbegin()) == it);
                    CHECK((it - 3) == j_value.cbegin());
                    CHECK((it - j_value.cbegin()) == 3);
                    CHECK(it != j_value.cend());
                    it -= 3;
                    CHECK(*it == json(42));
                }
            }
        }

        SECTION("subscript operator")
        {
            SECTION("object")
            {
                {
                    auto it = j_object.begin();
                    CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.cbegin();
                    CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&);
                }
            }

            SECTION("array")
            {
                {
                    auto it = j_array.begin();
                    CHECK(it[0] == json(1));
                    CHECK(it[1] == json(2));
                    CHECK(it[2] == json(3));
                    CHECK(it[3] == json(4));
                    CHECK(it[4] == json(5));
                    CHECK(it[5] == json(6));
                }
                {
                    auto it = j_array.cbegin();
                    CHECK(it[0] == json(1));
                    CHECK(it[1] == json(2));
                    CHECK(it[2] == json(3));
                    CHECK(it[3] == json(4));
                    CHECK(it[4] == json(5));
                    CHECK(it[5] == json(6));
                }
            }

            SECTION("null")
            {
                {
                    auto it = j_null.begin();
                    CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                }
                {
                    auto it = j_null.cbegin();
                    CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                }
            }

            SECTION("value")
            {
                {
                    auto it = j_value.begin();
                    CHECK(it[0] == json(42));
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                }
                {
                    auto it = j_value.cbegin();
                    CHECK(it[0] == json(42));
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                }
            }
        }
    }

    SECTION("reverse iterator comparisons")
    {
        json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};

        for (json& j : j_values)
        {
            auto it1 = j.rbegin();
            auto it2 = j.rbegin();
            auto it3 = j.rbegin();
            ++it2;
            ++it3;
            ++it3;
            auto it1_c = j.crbegin();
            auto it2_c = j.crbegin();
            auto it3_c = j.crbegin();
            ++it2_c;
            ++it3_c;
            ++it3_c;

            // comparison: equal
            {
                CHECK(it1 == it1);
                CHECK(!(it1 == it2));
                CHECK(!(it1 == it3));
                CHECK(!(it2 == it3));
                CHECK(it1_c == it1_c);
                CHECK(!(it1_c == it2_c));
                CHECK(!(it1_c == it3_c));
                CHECK(!(it2_c == it3_c));
            }

            // comparison: not equal
            {
                // check definition
                CHECK( (it1 != it1) == !(it1 == it1) );
                CHECK( (it1 != it2) == !(it1 == it2) );
                CHECK( (it1 != it3) == !(it1 == it3) );
                CHECK( (it2 != it3) == !(it2 == it3) );
                CHECK( (it1_c != it1_c) == !(it1_c == it1_c) );
                CHECK( (it1_c != it2_c) == !(it1_c == it2_c) );
                CHECK( (it1_c != it3_c) == !(it1_c == it3_c) );
                CHECK( (it2_c != it3_c) == !(it2_c == it3_c) );
            }

            // comparison: smaller
            {
                if (j.type() == json::value_t::object)
                {
#if JSON_DIAGNOSTICS
                    CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
#else
                    CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
#endif
                }
                else
                {
                    CHECK(!(it1 < it1));
                    CHECK(it1 < it2);
                    CHECK(it1 < it3);
                    CHECK(it2 < it3);
                    CHECK(!(it1_c < it1_c));
                    CHECK(it1_c < it2_c);
                    CHECK(it1_c < it3_c);
                    CHECK(it2_c < it3_c);
                }
            }

            // comparison: less than or equal
            {
                if (j.type() == json::value_t::object)
                {
#if JSON_DIAGNOSTICS
                    CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
#else
                    CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
#endif
                }
                else
                {
                    // check definition
                    CHECK( (it1 <= it1) == !(it1 < it1) );
                    CHECK( (it1 <= it2) == !(it2 < it1) );
                    CHECK( (it1 <= it3) == !(it3 < it1) );
                    CHECK( (it2 <= it3) == !(it3 < it2) );
                    CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) );
                    CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) );
                    CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) );
                    CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) );
                }
            }

            // comparison: greater than
            {
                if (j.type() == json::value_t::object)
                {
#if JSON_DIAGNOSTICS
                    CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
#else
                    CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
#endif
                }
                else
                {
                    // check definition
                    CHECK( (it1 > it1) == (it1 < it1) );
                    CHECK( (it1 > it2) == (it2 < it1) );
                    CHECK( (it1 > it3) == (it3 < it1) );
                    CHECK( (it2 > it3) == (it3 < it2) );
                    CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
                    CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
                    CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
                    CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
                }
            }

            // comparison: greater than or equal
            {
                if (j.type() == json::value_t::object)
                {
#if JSON_DIAGNOSTICS
                    CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
#else
                    CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
#endif
                }
                else
                {
                    // check definition
                    CHECK( (it1 >= it1) == !(it1 < it1) );
                    CHECK( (it1 >= it2) == !(it1 < it2) );
                    CHECK( (it1 >= it3) == !(it1 < it3) );
                    CHECK( (it2 >= it3) == !(it2 < it3) );
                    CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) );
                    CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) );
                    CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) );
                    CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) );
                }
            }
        }

        // check exceptions if different objects are compared
        for (auto j : j_values)
        {
            for (auto k : j_values)
            {
                if (j != k)
                {
#if JSON_DIAGNOSTICS
                    // the output differs in each loop, so we cannot fix a string for the expected exception
#else
                    CHECK_THROWS_WITH_AS(j.rbegin() == k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(j.crbegin() == k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(j.rbegin() < k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(j.crbegin() < k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
#endif
                }
            }
        }
    }

    SECTION("reverse iterator arithmetic")
    {
        json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
        json j_array = {1, 2, 3, 4, 5, 6};
        json j_null = nullptr;
        json j_value = 42;

        SECTION("addition and subtraction")
        {
            SECTION("object")
            {
                {
                    auto it = j_object.rbegin();
                    CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.crbegin();
                    CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.rbegin();
                    CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.crbegin();
                    CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.rbegin();
                    CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.crbegin();
                    CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.rbegin();
                    CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.crbegin();
                    CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.rbegin();
                    CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.crbegin();
                    CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.rbegin();
                    CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.crbegin();
                    CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
            }

            SECTION("array")
            {
                {
                    auto it = j_array.rbegin();
                    it += 3;
                    CHECK((j_array.rbegin() + 3) == it);
                    CHECK(json::reverse_iterator(3 + j_array.rbegin()) == it);
                    CHECK((it - 3) == j_array.rbegin());
                    CHECK((it - j_array.rbegin()) == 3);
                    CHECK(*it == json(3));
                    it -= 2;
                    CHECK(*it == json(5));
                }
                {
                    auto it = j_array.crbegin();
                    it += 3;
                    CHECK((j_array.crbegin() + 3) == it);
                    CHECK(json::const_reverse_iterator(3 + j_array.crbegin()) == it);
                    CHECK((it - 3) == j_array.crbegin());
                    CHECK((it - j_array.crbegin()) == 3);
                    CHECK(*it == json(3));
                    it -= 2;
                    CHECK(*it == json(5));
                }
            }

            SECTION("null")
            {
                {
                    auto it = j_null.rbegin();
                    it += 3;
                    CHECK((j_null.rbegin() + 3) == it);
                    CHECK(json::reverse_iterator(3 + j_null.rbegin()) == it);
                    CHECK((it - 3) == j_null.rbegin());
                    CHECK((it - j_null.rbegin()) == 3);
                    CHECK(it != j_null.rend());
                    it -= 3;
                    CHECK(it == j_null.rend());
                }
                {
                    auto it = j_null.crbegin();
                    it += 3;
                    CHECK((j_null.crbegin() + 3) == it);
                    CHECK(json::const_reverse_iterator(3 + j_null.crbegin()) == it);
                    CHECK((it - 3) == j_null.crbegin());
                    CHECK((it - j_null.crbegin()) == 3);
                    CHECK(it != j_null.crend());
                    it -= 3;
                    CHECK(it == j_null.crend());
                }
            }

            SECTION("value")
            {
                {
                    auto it = j_value.rbegin();
                    it += 3;
                    CHECK((j_value.rbegin() + 3) == it);
                    CHECK(json::reverse_iterator(3 + j_value.rbegin()) == it);
                    CHECK((it - 3) == j_value.rbegin());
                    CHECK((it - j_value.rbegin()) == 3);
                    CHECK(it != j_value.rend());
                    it -= 3;
                    CHECK(*it == json(42));
                }
                {
                    auto it = j_value.crbegin();
                    it += 3;
                    CHECK((j_value.crbegin() + 3) == it);
                    CHECK(json::const_reverse_iterator(3 + j_value.crbegin()) == it);
                    CHECK((it - 3) == j_value.crbegin());
                    CHECK((it - j_value.crbegin()) == 3);
                    CHECK(it != j_value.crend());
                    it -= 3;
                    CHECK(*it == json(42));
                }
            }
        }

        SECTION("subscript operator")
        {
            SECTION("object")
            {
                {
                    auto it = j_object.rbegin();
                    CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
                {
                    auto it = j_object.crbegin();
                    CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
                }
            }

            SECTION("array")
            {
                {
                    auto it = j_array.rbegin();
                    CHECK(it[0] == json(6));
                    CHECK(it[1] == json(5));
                    CHECK(it[2] == json(4));
                    CHECK(it[3] == json(3));
                    CHECK(it[4] == json(2));
                    CHECK(it[5] == json(1));
                }
                {
                    auto it = j_array.crbegin();
                    CHECK(it[0] == json(6));
                    CHECK(it[1] == json(5));
                    CHECK(it[2] == json(4));
                    CHECK(it[3] == json(3));
                    CHECK(it[4] == json(2));
                    CHECK(it[5] == json(1));
                }
            }

            SECTION("null")
            {
                {
                    auto it = j_null.rbegin();
                    CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                }
                {
                    auto it = j_null.crbegin();
                    CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                }
            }

            SECTION("value")
            {
                {
                    auto it = j_value.rbegin();
                    CHECK(it[0] == json(42));
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                }
                {
                    auto it = j_value.crbegin();
                    CHECK(it[0] == json(42));
                    CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
                }
            }
        }
    }

#if JSON_HAS_RANGES
    // JSON_HAS_CPP_20 (do not remove; see note at top of file)
    SECTION("ranges")
    {
        SECTION("concepts")
        {
            using nlohmann::detail::iteration_proxy_value;
            CHECK(std::bidirectional_iterator<json::iterator>);
            CHECK(std::input_iterator<iteration_proxy_value<json::iterator>>);

            CHECK(std::is_same<json::iterator, std::ranges::iterator_t<json>>::value);
            CHECK(std::ranges::bidirectional_range<json>);

            using nlohmann::detail::iteration_proxy;
            using items_type = decltype(std::declval<json&>().items());
            CHECK(std::is_same<items_type, iteration_proxy<json::iterator>>::value);
            CHECK(std::is_same<iteration_proxy_value<json::iterator>, std::ranges::iterator_t<items_type>>::value);
            CHECK(std::ranges::input_range<items_type>);
        }

        // libstdc++ algorithms don't work with Clang 15 (04/2022)
#if !DOCTEST_CLANG || (DOCTEST_CLANG && defined(__GLIBCXX__))
        SECTION("algorithms")
        {
            SECTION("copy")
            {
                json j{"foo", "bar"};
                auto j_copied = json::array();

                std::ranges::copy(j, std::back_inserter(j_copied));

                CHECK(j == j_copied);
            }

            SECTION("find_if")
            {
                json j{1, 3, 2, 4};
                auto j_even = json::array();

#if JSON_USE_IMPLICIT_CONVERSIONS
                auto it = std::ranges::find_if(j, [](int v) noexcept
                {
                    return (v % 2) == 0;
                });
#else
                auto it = std::ranges::find_if(j, [](const json & j) noexcept
                {
                    int v;
                    j.get_to(v);
                    return (v % 2) == 0;
                });
#endif

                CHECK(*it == 2);
            }
        }
#endif

        // libstdc++ views don't work with Clang 15 (04/2022)
        // libc++ hides limited ranges implementation behind guard macro
#if !(DOCTEST_CLANG && (defined(__GLIBCXX__) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)))
        SECTION("views")
        {
            SECTION("reverse")
            {
                json j{1, 2, 3, 4, 5};
                json j_expected{5, 4, 3, 2, 1};

                auto reversed = j | std::views::reverse;
                CHECK(reversed == j_expected);
            }

            SECTION("transform")
            {
                json j
                {
                    { "a_key", "a_value"},
                    { "b_key", "b_value"},
                    { "c_key", "c_value"},
                };
                json j_expected{"a_key", "b_key", "c_key"};

                // NOLINTNEXTLINE(fuchsia-trailing-return)
                auto transformed = j.items() | std::views::transform([](const auto & item) -> std::string_view
                {
                    return item.key();
                });
                auto j_transformed = json::array();
                std::ranges::copy(transformed, std::back_inserter(j_transformed));

                CHECK(j_transformed == j_expected);
            }
        }
#endif
    }
#endif
}


# create-vite

## Scaffolding Your First Vite Project

> **Compatibility Note:**
> Vite requires [Node.js](https://nodejs.org/en/) version 20.19+, 22.12+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.

With NPM:

```bash
npm create vite@latest
```

With Yarn:

```bash
yarn create vite
```

With PNPM:

```bash
pnpm create vite
```

With Bun:

```bash
bun create vite
```

With Deno:

```bash
deno init --npm vite
```

Then follow the prompts!

You can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run:

```bash
# npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-app -- --template vue

# yarn
yarn create vite my-vue-app --template vue

# pnpm
pnpm create vite my-vue-app --template vue

# Bun
bun create vite my-vue-app --template vue

# Deno
deno init --npm vite my-vue-app --template vue
```

Currently supported template presets include:

- `vanilla`
- `vanilla-ts`
- `vue`
- `vue-ts`
- `react`
- `react-compiler`
- `react-ts`
- `react-compiler-ts`
- `preact`
- `preact-ts`
- `lit`
- `lit-ts`
- `svelte`
- `svelte-ts`
- `solid`
- `solid-ts`
- `qwik`
- `qwik-ts`

You can use `.` for the project name to scaffold in the current directory.

## Community Templates

create-vite is a tool to quickly start a project from a basic template for popular frameworks. Check out Awesome Vite for [community maintained templates](https://github.com/vitejs/awesome-vite#templates) that include other tools or target different frameworks. You can use a tool like [tiged](https://github.com/tiged/tiged) to scaffold your project with one of the templates.

```bash
npx tiged user/project my-project
cd my-project

npm install
npm run dev
```


# <small>nlohmann::basic_json::</small>cbor_tag_handler_t

```cpp
enum class cbor_tag_handler_t
{
    error,
    ignore,
    store
};
```

This enumeration is used in the [`from_cbor`](from_cbor.md) function to choose how to treat tags:

error
:   throw a `parse_error` exception in case of a tag

ignore
:   ignore tags

store
:   store tagged values as binary container with subtype (for bytes 0xd8..0xdb)

## Examples

??? example

    The example below shows how the different values of the `cbor_tag_handler_t` influence the behavior of
    [`from_cbor`](from_cbor.md) when reading a tagged byte string.

    ```cpp
    --8<-- "examples/cbor_tag_handler_t.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/cbor_tag_handler_t.output"
    ```

## Version history

- Added in version 3.9.0. Added value `store` in 3.10.0.


# <small>nlohmann::basic_json::</small>front

```cpp
reference front();
const_reference front() const;
```

Returns a reference to the first element in the container. For a JSON container `#!cpp c`, the expression
`#!cpp c.front()` is equivalent to `#!cpp *c.begin()`.

## Return value

In the case of a structured type (array or object), a reference to the first element is returned. In the case of number,
string, boolean, or binary values, a reference to the value is returned.

## Exception safety

Strong guarantee: if an exception is thrown, there are no changes in the JSON value.

## Exceptions

If the JSON value is `#!json null`, exception
[`invalid_iterator.214`](../../home/exceptions.md#jsonexceptioninvalid_iterator214) is thrown.

## Complexity

Constant.

## Notes

!!! info "Precondition"

    The array or object must not be empty. Calling `front` on an empty array or object yields undefined behavior.

## Examples

??? example

    The following code shows an example for `front()`.

    ```cpp
    --8<-- "examples/front.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/front.output"
    ```

## See also

- [back](back.md) to access the last element

## Version history

- Added in version 1.0.0.
- Adjusted code to return reference to binary values in version 3.8.0.


# JSON Merge Patch

The library supports JSON Merge Patch ([RFC 7386](https://tools.ietf.org/html/rfc7386)) as a patch format.
The merge patch format is primarily intended for use with the HTTP PATCH method as a means of describing a set of modifications to a target resource's content. This function applies a merge patch to the current JSON value.

Instead of using [JSON Pointer](json_pointer.md) to specify values to be manipulated, it describes the changes using a syntax that closely mimics the document being modified.

??? example

    The following code shows how a JSON Merge Patch is applied to a JSON document.

    ```cpp
    --8<-- "examples/merge_patch.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/merge_patch.output"
    ```


// test dynamic import to a cjs dep with __esModule flag from an importer
// explicitly marked as CJS (nearest package.json has "type": "commonjs").
// Node interop semantics apply: `default` is the whole `module.exports`
import('@vitejs/test-dep-cjs-compiled-from-esm').then((ns) => {
  const ok =
    typeof ns.default.default === 'function' && ns.default.default() === 'foo'
  document.querySelector('.cjs-dynamic-importer-cjs').textContent = ok
    ? 'ok'
    : 'fail'
})


# <small>nlohmann::basic_json::</small>object_t

```cpp
using object_t = ObjectType<StringType,
                            basic_json,
                            default_object_comparator_t,
                            AllocatorType<std::pair<const StringType, basic_json>>>;
```

The type used to store JSON objects.

[RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON objects as follows:
> An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a
> string, number, boolean, null, object, or array.

To store objects in C++, a type is defined by the template parameters described below.

## Template parameters

`ObjectType`
:   the container to store objects (e.g., `std::map` or `std::unordered_map`)

`StringType`
:   the type of the keys or names (e.g., `std::string`). The comparison function `std::less<StringType>` is used to
    order elements inside the container.

`AllocatorType`
:   the allocator to use for objects (e.g., `std::allocator`)

## Notes

#### Default type

With the default values for `ObjectType` (`std::map`), `StringType` (`std::string`), and `AllocatorType`
(`std::allocator`), the default value for `object_t` is:

```cpp
// until C++14
std::map<
  std::string, // key_type
  basic_json, // value_type
  std::less<std::string>, // key_compare
  std::allocator<std::pair<const std::string, basic_json>> // allocator_type
>

// since C++14
std::map<
  std::string, // key_type
  basic_json, // value_type
  std::less<>, // key_compare
  std::allocator<std::pair<const std::string, basic_json>> // allocator_type
>
```

See [`default_object_comparator_t`](default_object_comparator_t.md) for more information.

#### Behavior

The choice of `object_t` influences the behavior of the JSON class. With the default type, objects have the following
behavior:

- When all names are unique, objects will be interoperable in the sense that all software implementations receiving that
  object will agree on the name-value mappings.
- When the names within an object are not unique, it is unspecified which one of the values for a given key will be
  chosen. For instance, `#!json {"key": 2, "key": 1}` could be equal to either `#!json {"key": 1}` or
  `#!json {"key": 2}`. To reject duplicate keys instead of silently resolving them one way or another, see
  [this parsing recipe](../../features/parsing/parser_callbacks.md#recipe-rejecting-duplicate-object-keys).
- Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see
  [`dump`](dump.md)) in this order. For instance, `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be stored
  and serialized as `#!json {"a": 2, "b": 1}`.
- When comparing objects, the order of the name/value pairs is irrelevant. This makes objects interoperable in the sense
  that they will not be affected by these differences. For instance, `#!json {"b": 1, "a": 2}` and
  `#!json {"a": 2, "b": 1}` will be treated as equal.

#### Limits

[RFC 8259](https://tools.ietf.org/html/rfc8259) specifies:
> An implementation may set limits on the maximum depth of nesting.

In this class, the object's limit of nesting is not explicitly constrained. However, a maximum depth of nesting may be
introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the
[`max_size`](max_size.md) function of a JSON object.

#### Storage

Objects are stored as pointers in a `basic_json` type. That is, for any access to object values, a pointer of type
`object_t*` must be dereferenced.

#### Object key order

The order name/value pairs are added to the object are *not* preserved by the library. Therefore, iterating an object
may return name/value pairs in a different order than they were originally stored. In fact, keys will be traversed in
alphabetical order as `std::map` with `std::less` is used by default. Please note this behavior conforms to
[RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON
objects.

#### Cross-`basic_json` conversion requirements

When converting an object from one `basic_json` specialization to another via the
[converting constructor](basic_json.md#overload-4), the target `object_t`'s `key_type` must be
directly constructible from the source `basic_json`'s `string_t` type (or more generally, from the
source object's key type). If this requirement is not met, the conversion does not fail; instead,
the object is silently converted as an array of key-value pairs, which is incorrect. See
[issue #3425](https://github.com/nlohmann/json/issues/3425) for details and an example.

## Examples

??? example

    The following code shows that `object_t` is by default, a typedef to `#!cpp std::map<json::string_t, json>`.

    ```cpp
    --8<-- "examples/object_t.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/object_t.output"
    ```

## Version history

- Added in version 1.0.0.


import { LitElement, css, html } from 'lit'
import litLogo from './assets/lit.svg'
import viteLogo from './assets/vite.svg'
import heroImg from './assets/hero.png'

/**
 * An example element.
 *
 * @slot - This element has a slot
 * @csspart button - The button
 */
export class MyElement extends LitElement {
  static get properties() {
    return {
      /**
       * The number of times the button has been clicked.
       */
      count: { type: Number },
    }
  }

  constructor() {
    super()
    this.count = 0
  }

  render() {
    return html`

          <slot></slot>

            Edit src/my-element.js and save to test
            HMR

        <button
          type="button"
          class="counter"
          @click=${this._onClick}
          part="button"
        >
          Count is ${this.count}
        </button>

          <svg class="icon" role="presentation" aria-hidden="true">
            <use href="/icons.svg#documentation-icon"></use>
          </svg>

Documentation

Your questions, answered

                Explore Vite

                Learn more

          <svg class="icon" role="presentation" aria-hidden="true">
            <use href="/icons.svg#social-icon"></use>
          </svg>

Connect with us

Join the Vite community

                <svg class="button-icon" role="presentation" aria-hidden="true">
                  <use href="/icons.svg#github-icon"></use>
                </svg>
                GitHub

                <svg class="button-icon" role="presentation" aria-hidden="true">
                  <use href="/icons.svg#discord-icon"></use>
                </svg>
                Discord

                <svg class="button-icon" role="presentation" aria-hidden="true">
                  <use href="/icons.svg#x-icon"></use>
                </svg>
                X.com

                <svg class="button-icon" role="presentation" aria-hidden="true">
                  <use href="/icons.svg#bluesky-icon"></use>
                </svg>
                Bluesky

    `
  }

  _onClick() {
    this.count++
  }

  static get styles() {
    return css`
      :host {
        --text: #6b6375;
        --text-h: #08060d;
        --bg: #fff;
        --border: #e5e4e7;
        --code-bg: #f4f3ec;
        --accent: #aa3bff;
        --accent-bg: rgba(170, 59, 255, 0.1);
        --accent-border: rgba(170, 59, 255, 0.5);
        --social-bg: rgba(244, 243, 236, 0.5);
        --shadow:
          rgba(0, 0, 0, 0.1) 0 10px 15px -3px,
          rgba(0, 0, 0, 0.05) 0 4px 6px -2px;

        --sans: system-ui, 'Segoe UI', Roboto, sans-serif;
        --heading: system-ui, 'Segoe UI', Roboto, sans-serif;
        --mono: ui-monospace, Consolas, monospace;

        font: 18px/145% var(--sans);
        letter-spacing: 0.18px;

        width: 1126px;
        max-width: 100%;
        margin: 0 auto;
        text-align: center;
        border-inline: 1px solid var(--border);
        min-height: 100svh;
        display: flex;
        flex-direction: column;
        box-sizing: border-box;
        color: var(--text);
      }

      @media (prefers-color-scheme: dark) {
        :host {
          --text: #9ca3af;
          --text-h: #f3f4f6;
          --bg: #16171d;
          --border: #2e303a;
          --code-bg: #1f2028;
          --accent: #c084fc;
          --accent-bg: rgba(192, 132, 252, 0.15);
          --accent-border: rgba(192, 132, 252, 0.5);
          --social-bg: rgba(47, 48, 58, 0.5);
          --shadow:
            rgba(0, 0, 0, 0.4) 0 10px 15px -3px,
            rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
        }

        #social .button-icon {
          filter: invert(1) brightness(2);
        }
      }

      h1,
      h2,
      ::slotted(h1),
      ::slotted(h2) {
        font-family: var(--heading);
        font-weight: 500;
        color: var(--text-h);
      }

      h1,
      ::slotted(h1) {
        font-size: 56px;
        letter-spacing: -1.68px;
        margin: 32px 0;
      }

      h2 {
        font-size: 24px;
        line-height: 118%;
        letter-spacing: -0.24px;
        margin: 0 0 8px;
      }

      p {
        margin: 0;
      }

      code {
        font-family: var(--mono);
        font-size: 15px;
        line-height: 135%;
        display: inline-flex;
        padding: 4px 8px;
        border-radius: 4px;
        color: var(--text-h);
        background: var(--code-bg);
      }

      .counter {
        font-family: var(--mono);
        font-size: 16px;
        display: inline-flex;
        padding: 5px 10px;
        border-radius: 5px;
        color: var(--accent);
        background: var(--accent-bg);
        border: 2px solid transparent;
        transition: border-color 0.3s;
        margin-bottom: 24px;
        cursor: pointer;
      }

      .counter:hover {
        border-color: var(--accent-border);
      }

      .counter:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 2px;
      }

      .hero {
        position: relative;
      }

      .hero .base,
      .hero .framework,
      .hero .vite {
        inset-inline: 0;
        margin: 0 auto;
      }

      .hero .base {
        width: 170px;
        position: relative;
        z-index: 0;
      }

      .hero .framework,
      .hero .vite {
        position: absolute;
      }

      .hero .framework {
        z-index: 1;
        top: 34px;
        height: 28px;
        transform: perspective(2000px) rotateZ(300deg) rotateX(44deg)
          rotateY(39deg) scale(1.4);
      }

      .hero .vite {
        z-index: 0;
        top: 107px;
        height: 26px;
        width: auto;
        transform: perspective(2000px) rotateZ(300deg) rotateX(40deg)
          rotateY(39deg) scale(0.8);
      }

      #center {
        display: flex;
        flex-direction: column;
        gap: 25px;
        place-content: center;
        place-items: center;
        flex-grow: 1;
      }

      #next-steps {
        display: flex;
        border-top: 1px solid var(--border);
        text-align: left;
      }

      #next-steps > div {
        flex: 1 1 0;
        padding: 32px;
      }

      #next-steps .icon {
        margin-bottom: 16px;
        width: 22px;
        height: 22px;
      }

      #docs {
        border-right: 1px solid var(--border);
      }

      #next-steps ul {
        list-style: none;
        padding: 0;
        display: flex;
        gap: 8px;
        margin: 32px 0 0;
      }

      #next-steps ul .logo {
        height: 18px;
      }

      #next-steps ul .logo svg {
        height: 100%;
        width: auto;
      }

      #next-steps ul a {
        color: var(--text-h);
        font-size: 16px;
        border-radius: 6px;
        background: var(--social-bg);
        display: flex;
        padding: 6px 12px;
        align-items: center;
        gap: 8px;
        text-decoration: none;
        transition: box-shadow 0.3s;
      }

      #next-steps ul a:hover {
        box-shadow: var(--shadow);
      }

      #next-steps ul .button-icon {
        height: 18px;
        width: 18px;
      }

      #spacer {
        height: 88px;
        border-top: 1px solid var(--border);
      }

      .ticks {
        position: relative;
        width: 100%;
      }

      .ticks::before,
      .ticks::after {
        content: '';
        position: absolute;
        top: -4.5px;
        border: 5px solid transparent;
      }

      .ticks::before {
        left: 0;
        border-left-color: var(--border);
      }

      .ticks::after {
        right: 0;
        border-right-color: var(--border);
      }

      @media (max-width: 1024px) {
        :host {
          font-size: 16px;
          width: 100%;
          max-width: 100%;
        }

        h1,
        ::slotted(h1) {
          font-size: 36px;
          margin: 20px 0;
        }

        h2,
        ::slotted(h2) {
          font-size: 20px;
        }

        #center {
          padding: 32px 20px 24px;
          gap: 18px;
        }

        #next-steps {
          flex-direction: column;
          text-align: center;
        }

        #next-steps > div {
          padding: 24px 20px;
        }

        #docs {
          border-right: none;
          border-bottom: 1px solid var(--border);
        }

        #next-steps ul {
          margin-top: 20px;
          flex-wrap: wrap;
          justify-content: center;
        }

        #next-steps ul li {
          flex: 1 1 calc(50% - 8px);
        }

        #next-steps ul a {
          width: 100%;
          justify-content: center;
          box-sizing: border-box;
        }

        #spacer {
          height: 48px;
        }
      }
    `
  }
}

window.customElements.define('my-element', MyElement)


:root {
  --text: #6b6375;
  --text-h: #08060d;
  --bg: #fff;
  --border: #e5e4e7;
  --code-bg: #f4f3ec;
  --accent: #aa3bff;
  --accent-bg: rgba(170, 59, 255, 0.1);
  --accent-border: rgba(170, 59, 255, 0.5);
  --social-bg: rgba(244, 243, 236, 0.5);
  --shadow:
    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;

  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;
  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;
  --mono: ui-monospace, Consolas, monospace;

  font: 18px/145% var(--sans);
  letter-spacing: 0.18px;
  color-scheme: light dark;
  color: var(--text);
  background: var(--bg);
  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

  @media (max-width: 1024px) {
    font-size: 16px;
  }
}

@media (prefers-color-scheme: dark) {
  :root {
    --text: #9ca3af;
    --text-h: #f3f4f6;
    --bg: #16171d;
    --border: #2e303a;
    --code-bg: #1f2028;
    --accent: #c084fc;
    --accent-bg: rgba(192, 132, 252, 0.15);
    --accent-border: rgba(192, 132, 252, 0.5);
    --social-bg: rgba(47, 48, 58, 0.5);
    --shadow:
      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
  }

  #social .button-icon {
    filter: invert(1) brightness(2);
  }
}

body {
  margin: 0;
}

h1,
h2 {
  font-family: var(--heading);
  font-weight: 500;
  color: var(--text-h);
}

h1 {
  font-size: 56px;
  letter-spacing: -1.68px;
  margin: 32px 0;
  @media (max-width: 1024px) {
    font-size: 36px;
    margin: 20px 0;
  }
}
h2 {
  font-size: 24px;
  line-height: 118%;
  letter-spacing: -0.24px;
  margin: 0 0 8px;
  @media (max-width: 1024px) {
    font-size: 20px;
  }
}
p {
  margin: 0;
}

code,
.counter {
  font-family: var(--mono);
  display: inline-flex;
  border-radius: 4px;
  color: var(--text-h);
}

code {
  font-size: 15px;
  line-height: 135%;
  padding: 4px 8px;
  background: var(--code-bg);
}

.counter {
  font-size: 16px;
  padding: 5px 10px;
  border-radius: 5px;
  color: var(--accent);
  background: var(--accent-bg);
  border: 2px solid transparent;
  transition: border-color 0.3s;
  margin-bottom: 24px;

  &:hover {
    border-color: var(--accent-border);
  }
  &:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
}

.hero {
  position: relative;

  .base,
  .framework,
  .vite {
    inset-inline: 0;
    margin: 0 auto;
  }

  .base {
    width: 170px;
    position: relative;
    z-index: 0;
  }

  .framework,
  .vite {
    position: absolute;
  }

  .framework {
    z-index: 1;
    top: 34px;
    height: 28px;
    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
      scale(1.4);
  }

  .vite {
    z-index: 0;
    top: 107px;
    height: 26px;
    width: auto;
    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
      scale(0.8);
  }
}

#app {
  width: 1126px;
  max-width: 100%;
  margin: 0 auto;
  text-align: center;
  border-inline: 1px solid var(--border);
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}

#center {
  display: flex;
  flex-direction: column;
  gap: 25px;
  place-content: center;
  place-items: center;
  flex-grow: 1;

  @media (max-width: 1024px) {
    padding: 32px 20px 24px;
    gap: 18px;
  }
}

#next-steps {
  display: flex;
  border-top: 1px solid var(--border);
  text-align: left;

  & > div {
    flex: 1 1 0;
    padding: 32px;
    @media (max-width: 1024px) {
      padding: 24px 20px;
    }
  }

  .icon {
    margin-bottom: 16px;
    width: 22px;
    height: 22px;
  }

  @media (max-width: 1024px) {
    flex-direction: column;
    text-align: center;
  }
}

#docs {
  border-right: 1px solid var(--border);

  @media (max-width: 1024px) {
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
}

#next-steps ul {
  list-style: none;
  padding: 0;
  display: flex;
  gap: 8px;
  margin: 32px 0 0;

  .logo {
    height: 18px;
  }

  a {
    color: var(--text-h);
    font-size: 16px;
    border-radius: 6px;
    background: var(--social-bg);
    display: flex;
    padding: 6px 12px;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    transition: box-shadow 0.3s;

    &:hover {
      box-shadow: var(--shadow);
    }
    .button-icon {
      height: 18px;
      width: 18px;
    }
  }

  @media (max-width: 1024px) {
    margin-top: 20px;
    flex-wrap: wrap;
    justify-content: center;

    li {
      flex: 1 1 calc(50% - 8px);
    }

    a {
      width: 100%;
      justify-content: center;
      box-sizing: border-box;
    }
  }
}

#spacer {
  height: 88px;
  border-top: 1px solid var(--border);
  @media (max-width: 1024px) {
    height: 48px;
  }
}

.ticks {
  position: relative;
  width: 100%;

  &::before,
  &::after {
    content: '';
    position: absolute;
    top: -4.5px;
    border: 5px solid transparent;
  }

  &::before {
    left: 0;
    border-left-color: var(--border);
  }
  &::after {
    right: 0;
    border-right-color: var(--border);
  }
}


#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    // create JSON values
    json j_null;
    json j_boolean = true;
    json j_number_integer = 17;
    json j_number_unsigned_integer = 12345678987654321u;
    json j_number_float = 23.42;
    json j_object = {{"one", 1}, {"two", 2}};
    json j_array = {1, 2, 4, 8, 16};
    json j_string = "Hello, world";
    json j_binary = json::binary({1, 2, 3});

    // call is_null()
    std::cout << std::boolalpha;
    std::cout << j_null.is_null() << '\n';
    std::cout << j_boolean.is_null() << '\n';
    std::cout << j_number_integer.is_null() << '\n';
    std::cout << j_number_unsigned_integer.is_null() << '\n';
    std::cout << j_number_float.is_null() << '\n';
    std::cout << j_object.is_null() << '\n';
    std::cout << j_array.is_null() << '\n';
    std::cout << j_string.is_null() << '\n';
    std::cout << j_binary.is_null() << '\n';
}


#![allow(dead_code)] // we do not read enum fields

use serde_derive::Deserialize;

#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub enum A {
    B {
        c: String,
    },
    D {
        #[serde(flatten)]
        e: E,
    },
}

#[derive(Deserialize)]
pub struct E {}


#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    // different JSON Pointers
    json::json_pointer ptr1("");
    json::json_pointer ptr2("/foo");
    json::json_pointer ptr3("/foo/0");
    json::json_pointer ptr4("/");
    json::json_pointer ptr5("/a~1b");
    json::json_pointer ptr6("/c%d");
    json::json_pointer ptr7("/e^f");
    json::json_pointer ptr8("/g|h");
    json::json_pointer ptr9("/i\\j");
    json::json_pointer ptr10("/k\"l");
    json::json_pointer ptr11("/ ");
    json::json_pointer ptr12("/m~0n");

    std::cout << "\"" << ptr1.to_string() << "\"\n"
              << "\"" << ptr2.to_string() << "\"\n"
              << "\"" << ptr3.to_string() << "\"\n"
              << "\"" << ptr4.to_string() << "\"\n"
              << "\"" << ptr5.to_string() << "\"\n"
              << "\"" << ptr6.to_string() << "\"\n"
              << "\"" << ptr7.to_string() << "\"\n"
              << "\"" << ptr8.to_string() << "\"\n"
              << "\"" << ptr9.to_string() << "\"\n"
              << "\"" << ptr10.to_string() << "\"\n"
              << "\"" << ptr11.to_string() << "\"\n"
              << "\"" << ptr12.to_string() << "\"" << std::endl;
}


use serde_derive::{Deserialize, Serialize};

mod remote {
    pub struct Struct<T, U> {
        pub t: T,
        pub u: U,
    }
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructGeneric<u8>")]
struct StructDef<U> {
    t: u8,
    u: U,
}

fn main() {}


---
title: Cloudflare supports Vite's mission
author:
  name: The Vite Team
date: 2026-06-04
sidebar: false
head:
  - - meta
    - property: og:type
      content: website
  - - meta
    - property: og:title
      content: Cloudflare supports Vite's mission
  - - meta
    - property: og:image
      content: https://vite.dev/og-image-cloudflare-supports-vite.webp
  - - meta
    - property: og:url
      content: https://vite.dev/blog/cloudflare-supports-vite
  - - meta
    - property: og:description
      content: The VoidZero team is joining Cloudflare. Vite remains MIT, vendor-neutral and stewarded by the same wider team.
  - - meta
    - name: twitter:card
      content: summary_large_image
---

# Cloudflare supports Vite's mission

_June 4, 2026_

![Cloudflare Supports Vite's Mission Cover Image](/og-image-cloudflare-supports-vite.webp)

Today marks the start of a new stage for Vite. VoidZero is joining Cloudflare. You can read the full story from Evan You in [VoidZero's announcement](https://voidzero.dev/posts/voidzero-cloudflare). In [Cloudflare's blog post](https://blog.cloudflare.com/voidzero-joins-cloudflare/), they explain why they are investing in the Vite stack, which has now become part of the web's foundational infrastructure. Vite's team governance, mission, and philosophy aren't changing:

- Vite remains open source under the MIT license.
- Vite remains vendor-agnostic, applications built with vite are meant to run anywhere.
- Vite continues to be stewarded by the [Vite team](/team), which includes members employed by different organizations and independent members.
- [Vite's Open Collective](https://opencollective.com/vite) funds are managed by the Vite team and are used to fund independent core team members, dependencies, and other key projects in the ecosystem.
- The Vite team members employed by VoidZero are all joining Cloudflare and will continue to work on Vite.

As stated in the VoidZero and Cloudflare announcements, the same applies to [Vitest](https://vitest.dev/team.html), [Rolldown](https://rolldown.rs/team), [Oxc](https://oxc.rs/team.html), and [Vite+](https://viteplus.dev/team).

## Cloudflare's Vite Ecosystem Open Source Fund

Cloudflare is committed to helping Vite remain neutral and has also announced a new $1M open source fund for the Vite ecosystem. Alongside Vite's Open Collective (which stays managed by the Vite team), these funds will allow us to further improve Vite and its ecosystem, including:

- Fund more popular plugins and toolings in the ecosystem.
- Adopt a core team member stipend to support independent team members.
- Work closely with teams of the Vite stack, including Rolldown, Oxc, and Vite+.
- Work closely with the ecosystem maintainers from frameworks, plugins, and deployment platforms.
- Work with standard bodies and adopt new web platform features faster.
- Audit and release security issues more quickly.

Many of which we had already started working on, which will help accelerate the process.

## Thank You

We want to thank our current sponsors through [GitHub Sponsors](https://github.com/sponsors/vitejs) and [Open Collective](https://opencollective.com/vite), which remain invaluable to us. We'd also like to thank the teams from projects, ecosystem frameworks, and plugins whose collaboration helped Vite reach where it is today. And also to [the 1250+ contributors](https://github.com/vitejs/vite/graphs/contributors) to the Vite repo and the users who keep providing valuable feedback to improve Vite.

We talked about what's next in [Vite 8's announcement](/blog/announcing-vite8#looking-ahead). We have made good progress towards Full Bundle Mode and the new Ecosystem Sync Calls, that gathers members of different frameworks, deploy platforms, and plugins, have become a great motor for new ideas to further expand Vite's capabilities. We think we're on a good trajectory to stabilize Vite's Environment API on Vite 9. As Vite's story continues to unfold, we look forward to the long path ahead to keep building the web together.


import 'node:path'
export default function testStack() {
  innerTestStack()
}
import 'node:util'
function innerTestStack() {
  throw new Error('__TEST_STACK_TRANSPILED_INLINE__')
}
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidHJhbnNwaWxlZC1pbmxpbmUudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCAnbm9kZTpwYXRoJ1xuXG5leHBvcnQgdHlwZSBEdW1teSA9IHtcbiAgZm9vOiBcImZvb1wiLFxufVxuXG4vKipcbiAqIGR1bW15XG4gKiBkdW1teVxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiB0ZXN0U3RhY2soKSB7XG4gIGlubmVyVGVzdFN0YWNrKClcbn1cblxuaW1wb3J0ICdub2RlOnV0aWwnXG5cbi8qKlxuICogYmFyXG4gKiBiYXJcbiAqL1xuZnVuY3Rpb24gaW5uZXJUZXN0U3RhY2soKSB7XG4gIHRocm93IG5ldyBFcnJvcignX19URVNUX1NUQUNLX1RSQU5TUElMRURfSU5MSU5FX18nKVxufSJdLAogICJtYXBwaW5ncyI6ICJBQUFBLE9BQU87QUFVUCx3QkFBd0IsWUFBWTtBQUNsQyxpQkFBZTtBQUNqQjtBQUVBLE9BQU87QUFNUCxTQUFTLGlCQUFpQjtBQUN4QixRQUFNLElBQUksTUFBTSxrQ0FBa0M7QUFDcEQ7IiwKICAibmFtZXMiOiBbXQp9Cg==


#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using namespace nlohmann::literals;

int main()
{
    // create a JSON value
    json j =
    {
        {"number", 1}, {"string", "foo"}, {"array", {1, 2}}
    };

    // read-only access

    // output element with JSON pointer "/number"
    std::cout << j.at("/number"_json_pointer) << '\n';
    // output element with JSON pointer "/string"
    std::cout << j.at("/string"_json_pointer) << '\n';
    // output element with JSON pointer "/array"
    std::cout << j.at("/array"_json_pointer) << '\n';
    // output element with JSON pointer "/array/1"
    std::cout << j.at("/array/1"_json_pointer) << '\n';

    // writing access

    // change the string
    j.at("/string"_json_pointer) = "bar";
    // output the changed string
    std::cout << j["string"] << '\n';

    // change an array element
    j.at("/array/1"_json_pointer) = 21;
    // output the changed array
    std::cout << j["array"] << '\n';

    // out_of_range.106
    try
    {
        // try to use an array index with leading '0'
        json::reference ref = j.at("/array/01"_json_pointer);
    }
    catch (const json::parse_error& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.109
    try
    {
        // try to use an array index that is not a number
        json::reference ref = j.at("/array/one"_json_pointer);
    }
    catch (const json::parse_error& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.401
    try
    {
        // try to use an invalid array index
        json::reference ref = j.at("/array/4"_json_pointer);
    }
    catch (const json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.402
    try
    {
        // try to use the array index '-'
        json::reference ref = j.at("/array/-"_json_pointer);
    }
    catch (const json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.403
    try
    {
        // try to use a JSON pointer to a nonexistent object key
        json::const_reference ref = j.at("/foo"_json_pointer);
    }
    catch (const json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.404
    try
    {
        // try to use a JSON pointer that cannot be resolved
        json::reference ref = j.at("/number/foo"_json_pointer);
    }
    catch (const json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }
}


'use strict'

// Minimal cloneDeep implementation for testing
function cloneDeep(value) {
  if (value == null || typeof value !== 'object') {
    return value
  }

  if (Array.isArray(value)) {
    return value.map(cloneDeep)
  }

  const cloned = {}
  for (const key in value) {
    if (Object.hasOwn(value, key)) {
      cloned[key] = cloneDeep(value[key])
    }
  }
  return cloned
}

module.exports = cloneDeep


#![allow(
    clippy::derive_partial_eq_without_eq,
    clippy::items_after_statements,
    clippy::used_underscore_binding,
    // We use lots of declarations inside function bodies to avoid conflicts,
    // but they aren't used. We just want to make sure they compile.
    dead_code,
)]

use serde::de::value::{BorrowedStrDeserializer, MapDeserializer};
use serde::de::{Deserialize, Deserializer, IntoDeserializer};
use serde_derive::Deserialize;
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
use std::borrow::Cow;

#[test]
fn test_borrowed_str() {
    assert_de_tokens(&"borrowed", &[Token::BorrowedStr("borrowed")]);
}

#[test]
fn test_borrowed_str_from_string() {
    assert_de_tokens_error::<&str>(
        &[Token::String("borrowed")],
        "invalid type: string \"borrowed\", expected a borrowed string",
    );
}

#[test]
fn test_borrowed_str_from_str() {
    assert_de_tokens_error::<&str>(
        &[Token::Str("borrowed")],
        "invalid type: string \"borrowed\", expected a borrowed string",
    );
}

#[test]
fn test_string_from_borrowed_str() {
    assert_de_tokens(&"owned".to_owned(), &[Token::BorrowedStr("owned")]);
}

#[test]
fn test_borrowed_bytes() {
    assert_de_tokens(&&b"borrowed"[..], &[Token::BorrowedBytes(b"borrowed")]);
}

#[test]
fn test_borrowed_bytes_from_bytebuf() {
    assert_de_tokens_error::<&[u8]>(
        &[Token::ByteBuf(b"borrowed")],
        "invalid type: byte array, expected a borrowed byte array",
    );
}

#[test]
fn test_borrowed_bytes_from_bytes() {
    assert_de_tokens_error::<&[u8]>(
        &[Token::Bytes(b"borrowed")],
        "invalid type: byte array, expected a borrowed byte array",
    );
}

#[test]
fn test_tuple() {
    assert_de_tokens(
        &("str", &b"bytes"[..]),
        &[
            Token::Tuple { len: 2 },
            Token::BorrowedStr("str"),
            Token::BorrowedBytes(b"bytes"),
            Token::TupleEnd,
        ],
    );
}

#[test]
fn test_struct() {
    #[derive(Deserialize, Debug, PartialEq)]
    struct Borrowing<'a, 'b> {
        bs: &'a str,
        bb: &'b [u8],
    }

    assert_de_tokens(
        &Borrowing {
            bs: "str",
            bb: b"bytes",
        },
        &[
            Token::Struct {
                name: "Borrowing",
                len: 2,
            },
            Token::BorrowedStr("bs"),
            Token::BorrowedStr("str"),
            Token::BorrowedStr("bb"),
            Token::BorrowedBytes(b"bytes"),
            Token::StructEnd,
        ],
    );
}

#[test]
fn test_field_identifier() {
    #[derive(Deserialize, Debug, PartialEq)]
    #[serde(field_identifier)]
    enum FieldStr<'a> {
        #[serde(borrow)]
        Str(&'a str),
    }

    assert_de_tokens(&FieldStr::Str("value"), &[Token::BorrowedStr("value")]);

    #[derive(Deserialize, Debug, PartialEq)]
    #[serde(field_identifier)]
    enum FieldBytes<'a> {
        #[serde(borrow)]
        Bytes(&'a [u8]),
    }

    assert_de_tokens(
        &FieldBytes::Bytes(b"value"),
        &[Token::BorrowedBytes(b"value")],
    );
}

#[test]
fn test_cow() {
    #[derive(Deserialize)]
    struct Cows<'a, 'b> {
        copied: Cow<'a, str>,

        #[serde(borrow)]
        borrowed: Cow<'b, str>,
    }

    struct BorrowedStr(&'static str);

    impl<'de> IntoDeserializer<'de> for BorrowedStr {
        type Deserializer = BorrowedStrDeserializer<'de, serde::de::value::Error>;

        fn into_deserializer(self) -> Self::Deserializer {
            BorrowedStrDeserializer::new(self.0)
        }
    }

    let de = MapDeserializer::new(IntoIterator::into_iter([
        ("copied", BorrowedStr("copied")),
        ("borrowed", BorrowedStr("borrowed")),
    ]));

    let cows = Cows::deserialize(de).unwrap();

    match cows.copied {
        Cow::Owned(ref s) if s == "copied" => {}
        _ => panic!("expected a copied string"),
    }

    match cows.borrowed {
        Cow::Borrowed("borrowed") => {}
        _ => panic!("expected a borrowed string"),
    }
}

#[test]
fn test_lifetimes() {
    #[derive(Deserialize)]
    pub struct Cows<'a, 'b> {
        _copied: Cow<'a, str>,

        #[serde(borrow)]
        _borrowed: Cow<'b, str>,
    }

    // Tests that `'de: 'a` is not required by the Deserialize impl.
    fn _cows_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Cows<'a, 'b>
    where
        D: Deserializer<'de>,
    {
        Deserialize::deserialize(deserializer).unwrap()
    }

    #[derive(Deserialize)]
    pub struct Wrap<'a, 'b> {
        #[serde(borrow = "'b")]
        _cows: Cows<'a, 'b>,
    }

    // Tests that `'de: 'a` is not required by the Deserialize impl.
    fn _wrap_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Wrap<'a, 'b>
    where
        D: Deserializer<'de>,
    {
        Deserialize::deserialize(deserializer).unwrap()
    }
}


# JSON_DIAGNOSTICS

```cpp
#define JSON_DIAGNOSTICS /* value */
```

This macro enables [extended diagnostics for exception messages](../../home/exceptions.md#extended-diagnostic-messages).
Possible values are `1` to enable or `0` to disable (default).

When enabled, exception messages contain a [JSON Pointer](../json_pointer/json_pointer.md) to the JSON value that
triggered the exception. Note that enabling this macro increases the size of every JSON value by one pointer and adds
some runtime overhead.

## Default definition

The default value is `0` (extended diagnostics are switched off).

```cpp
#define JSON_DIAGNOSTICS 0
```

When the macro is not defined, the library will define it to its default value.

## Notes

!!! note "ABI compatibility"

    As of version 3.11.0, this macro is no longer required to be defined consistently throughout a codebase to avoid
    One Definition Rule (ODR) violations, as the value of this macro is encoded in the namespace, resulting in distinct
    symbol names.

    This allows different parts of a codebase to use different versions or configurations of this library without
    causing improper behavior.

    Where possible, it is still recommended that all code define this the same way for maximum interoperability.

!!! hint "CMake option"

    Diagnostic messages can also be controlled with the CMake option
    [`JSON_Diagnostics`](../../integration/cmake.md#json_diagnostics) (`OFF` by default)
    which defines `JSON_DIAGNOSTICS` accordingly. Note this only applies when building the
    library from source — see the pre-installed-package caveat on that page.

## Examples

??? example "Example 1: default behavior"

    ```cpp
    --8<-- "examples/diagnostics_standard.cpp"
    ```

    Output:

    ```
    --8<-- "examples/diagnostics_standard.output"
    ```

    This exception can be hard to debug if storing the value `#!c "12"` and accessing it is further apart.

??? example "Example 2: extended diagnostic messages"

    ```cpp
    --8<-- "examples/diagnostics_extended.cpp"
    ```

    Output:

    ```
    --8<-- "examples/diagnostics_extended.output"
    ```

    Now the exception message contains a JSON Pointer `/address/housenumber` that indicates which value has the wrong type.

??? example "Example 3: using only diagnostic positions in exceptions"

    ```cpp
    --8<-- "examples/diagnostic_positions_exception.cpp"
    ```

    Output:

    ```
    --8<-- "examples/diagnostic_positions_exception.output"
    ```
        The output shows the exception with start/end positions only.

## See also

- [:simple-cmake: JSON_Diagnostics](../../integration/cmake.md#json_diagnostics) - CMake option to control the macro
- [JSON_DIAGNOSTIC_POSITIONS](json_diagnostic_positions.md) - macro to access positions of elements

## Version history

- Added in version 3.10.0.
- As of version 3.11.0, the definition is allowed to vary between translation units.


# <small>nlohmann::json_sax::</small>parse_error

```cpp
virtual bool parse_error(std::size_t position,
                         const std::string& last_token,
                         const detail::exception& ex) = 0;
```

A parse error occurred.

## Parameters

`position` (in)
:   the position in the input where the error occurs

`last_token` (in)
:   the last read token

`ex` (in)
:   an exception object describing the error

## Return value

Whether parsing should proceed (**must return `#!cpp false`**).

## Examples

??? example

    The example below shows how the SAX interface is used.

    ```cpp
    --8<-- "examples/sax_parse.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/sax_parse.output"
    ```

## Version history

- Added in version 3.2.0.