#include <charconv>
#include <deque>
#include <iostream>
#include <map>
#include <random>
#include <unordered_map>

#include "glaze/glaze.hpp"
#include "glaze/util/itoa.hpp"
#include "glaze/util/itoa_40kb.hpp"
#include "ut/ut.hpp"

using namespace ut;

// ==================== Direct to_chars validation ====================
// These tests validate to_chars output against std::to_chars for every possible value

template <class T>
bool validate_to_chars_exhaustive()
{
   char glz_buf[32];
   char std_buf[32];

   auto test_value = [&](T val) -> bool {
      // Test glz::to_chars
      auto glz_end = glz::to_chars(glz_buf, val);
      std::string_view glz_result(glz_buf, glz_end - glz_buf);

      // Test std::to_chars as reference
      auto [std_end, ec] = std::to_chars(std_buf, std_buf + 32, val);
      if (ec != std::errc()) return false;
      std::string_view std_result(std_buf, std_end - std_buf);

      if (glz_result != std_result) {
         std::cerr << "Mismatch for value " << int64_t(val) << ": glz='" << glz_result << "' std='" << std_result
                   << "'\n";
         return false;
      }
      return true;
   };

   if constexpr (std::is_unsigned_v<T>) {
      for (uint64_t i = 0; i <= uint64_t((std::numeric_limits<T>::max)()); ++i) {
         if (!test_value(T(i))) return false;
      }
   }
   else {
      for (int64_t i = int64_t(std::numeric_limits<T>::lowest()); i <= int64_t((std::numeric_limits<T>::max)()); ++i) {
         if (!test_value(T(i))) return false;
      }
   }
   return true;
}

// Also test to_chars_40kb for 32/64-bit types
template <class T>
   requires(sizeof(T) >= 4)
bool validate_to_chars_40kb_samples()
{
   char glz_buf[32];
   char std_buf[32];

   std::mt19937_64 rng(42);
   std::uniform_int_distribution<T> dist(std::numeric_limits<T>::lowest(), (std::numeric_limits<T>::max)());

   auto test_value = [&](T val) -> bool {
      auto glz_end = glz::to_chars_40kb(glz_buf, val);
      std::string_view glz_result(glz_buf, glz_end - glz_buf);

      auto [std_end, ec] = std::to_chars(std_buf, std_buf + 32, val);
      if (ec != std::errc()) return false;
      std::string_view std_result(std_buf, std_end - std_buf);

      if (glz_result != std_result) {
         std::cerr << "Mismatch for value " << val << ": glz='" << glz_result << "' std='" << std_result << "'\n";
         return false;
      }
      return true;
   };

   // Test edge cases
   if (!test_value(0)) return false;
   if (!test_value(1)) return false;
   if (!test_value(T(-1))) return false;
   if (!test_value((std::numeric_limits<T>::max)())) return false;
   if (!test_value(std::numeric_limits<T>::lowest())) return false;

   // Test random samples
   for (size_t i = 0; i < 100000; ++i) {
      if (!test_value(dist(rng))) return false;
   }
   return true;
}

// Test helper that tests both normal mode (to_chars_40kb) and size mode (to_chars)
template <class T, class Opts = glz::opts>
bool test_samples_with_opts()
{
   std::mt19937 gen{std::random_device{}()};
   std::uniform_int_distribution<T> dist{std::numeric_limits<T>::lowest(), (std::numeric_limits<T>::max)()};

   std::string buffer{};
   bool valid = true;
   T sample{};

   for (size_t i = 0; i < 100000; ++i) {
      sample = dist(gen);
      if (glz::write<Opts{}>(sample, buffer)) {
         valid = false;
         break;
      }
      T value{};
      if (glz::read<Opts{}>(value, buffer)) {
         valid = false;
         break;
      }
      if (value != sample) {
         valid = false;
         break;
      }
   }
   expect(valid) << sample;

   // test max and min values
   sample = (std::numeric_limits<T>::max)();
   if (glz::write<Opts{}>(sample, buffer)) {
      valid = false;
   }
   T value{};
   if (glz::read<Opts{}>(value, buffer)) {
      valid = false;
   }
   if (value != sample) {
      valid = false;
   }

   sample = std::numeric_limits<T>::lowest();
   if (glz::write<Opts{}>(sample, buffer)) {
      valid = false;
   }
   value = {};
   if (glz::read<Opts{}>(value, buffer)) {
      valid = false;
   }
   if (value != sample) {
      valid = false;
   }

   expect(valid) << sample;
   return valid;
}

template <class T>
bool test_samples()
{
   // Test both normal mode (to_chars_40kb - 40KB tables) and size mode (to_chars - 400B tables)
   return test_samples_with_opts<T, glz::opts>() && test_samples_with_opts<T, glz::opts_size>();
}

template <class T, class Opts = glz::opts>
bool test_to_max_with_opts()
{
   std::string buffer{};
   bool valid = true;
   if constexpr (std::is_unsigned_v<T>) {
      for (uint64_t i = 0; i < (std::numeric_limits<T>::max)(); ++i) {
         if (glz::write<Opts{}>(i, buffer)) {
            valid = false;
            break;
         }
         T value{};
         if (glz::read<Opts{}>(value, buffer)) {
            valid = false;
            break;
         }
         if (value != T(i)) {
            valid = false;
            break;
         }
      }
   }
   else {
      for (int64_t i = std::numeric_limits<T>::lowest(); i < (std::numeric_limits<T>::max)(); ++i) {
         if (glz::write<Opts{}>(i, buffer)) {
            valid = false;
            break;
         }
         T value{};
         if (glz::read<Opts{}>(value, buffer)) {
            valid = false;
            break;
         }
         if (value != T(i)) {
            valid = false;
            break;
         }
      }
   }
   expect(valid) << buffer;
   return valid;
}

template <class T>
bool test_to_max()
{
   // Test both normal mode (to_chars_40kb) and size mode (to_chars)
   return test_to_max_with_opts<T, glz::opts>() && test_to_max_with_opts<T, glz::opts_size>();
}

template <class T, class Opts = glz::opts>
bool test_performance_with_opts()
{
#ifdef NDEBUG
   constexpr size_t n = 10000000;
#else
   constexpr size_t n = 100000;
#endif

   std::mt19937 gen{};
   std::uniform_int_distribution<T> dist{std::numeric_limits<T>::lowest(), (std::numeric_limits<T>::max)()};

   std::string buffer;
   auto t0 = std::chrono::steady_clock::now();
   bool valid = true;
   for (size_t i = 0; i < n; ++i) {
      const auto sample = dist(gen);
      std::ignore = glz::write<Opts{}>(sample, buffer);
      T v{};
      const auto e = glz::read<Opts{}>(v, buffer);
      if (bool(e)) {
         valid = false;
         break;
      }
      if (v != sample) {
         valid = false;
         break;
      }
   }
   auto t1 = std::chrono::steady_clock::now();
   auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count() * 1e-6;
   constexpr bool is_size_mode = std::same_as<Opts, glz::opts_size>;
   std::cout << glz::name_v<T> << " read/write (" << (is_size_mode ? "size" : "normal") << "): " << duration << '\n';
   return valid;
}

template <class T>
bool test_performance()
{
   // Test both normal mode (to_chars_40kb) and size mode (to_chars)
   return test_performance_with_opts<T, glz::opts>() && test_performance_with_opts<T, glz::opts_size>();
}

template <class T>
struct vector_object
{
   std::vector<T> vec{};
};

template <class T>
void test_struct_with_array_minified()
{
   std::mt19937 gen{};
   std::uniform_int_distribution<T> dist{std::numeric_limits<T>::lowest(), (std::numeric_limits<T>::max)()};

   vector_object<T> obj;

   for (size_t i = 0; i < 1000; ++i) {
      obj.vec.emplace_back(dist(gen));
   }

   std::string buffer{};
   expect(not glz::write_json(obj, buffer));
   expect(not glz::read<glz::opts{.minified = true}>(obj, buffer));
}

template <class T, class Opts = glz::opts>
bool test_single_char_performance_with_opts()
{
#ifdef NDEBUG
   constexpr size_t n = 10000000;
#else
   constexpr size_t n = 100000;
#endif

   std::mt19937 gen{};
   std::uniform_int_distribution<T> dist{0, 9};

   std::string buffer;
   auto t0 = std::chrono::steady_clock::now();
   bool valid = true;
   for (size_t i = 0; i < n; ++i) {
      const auto sample = dist(gen);
      std::ignore = glz::write<Opts{}>(sample, buffer);
      T v{};
      const auto e = glz::read<Opts{}>(v, buffer);
      if (bool(e)) {
         valid = false;
         break;
      }
      if (v != sample) {
         valid = false;
         break;
      }
   }
   auto t1 = std::chrono::steady_clock::now();
   auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count() * 1e-6;
   constexpr bool is_size_mode = std::same_as<Opts, glz::opts_size>;
   std::cout << glz::name_v<T> << " single char read/write (" << (is_size_mode ? "size" : "normal") << "): " << duration
             << '\n';
   return valid;
}

template <class T>
bool test_single_char_performance()
{
   // Test both normal mode (to_chars_40kb) and size mode (to_chars)
   return test_single_char_performance_with_opts<T, glz::opts>() &&
          test_single_char_performance_with_opts<T, glz::opts_size>();
}

template <class T>
bool test_lengths()
{
   using pair = std::pair<std::string_view, uint64_t>;
   static constexpr std::array<pair, 21> samples = {
      pair{"", 0ull}, //
      pair{"1", 1ull}, //
      pair{"12", 12ull}, //
      pair{"123", 123ull}, //
      pair{"1234", 1234ull}, //
      pair{"12345", 12345ull}, //
      pair{"123456", 123456ull}, //
      pair{"1234567", 1234567ull}, //
      pair{"12345678", 12345678ull}, //
      pair{"123456789", 123456789ull}, //
      pair{"1234567890", 1234567890ull}, //
      pair{"12345678901", 12345678901ull}, //
      pair{"123456789012", 123456789012ull}, //
      pair{"1234567890123", 1234567890123ull}, //
      pair{"12345678901234", 12345678901234ull}, //
      pair{"123456789012345", 123456789012345ull}, //
      pair{"1234567890123456", 1234567890123456ull}, //
      pair{"12345678901234567", 12345678901234567ull}, //
      pair{"123456789012345678", 123456789012345678ull}, //
      pair{"1234567890123456789", 1234567890123456789ull}, //
      pair{"12345678901234567890", 12345678901234567890ull}, //
   };

   std::string buffer{};
   bool valid = true;
   size_t max_length{};
   if constexpr (sizeof(T) == 1) {
      max_length = 3;
   }
   else if constexpr (sizeof(T) == 2) {
      max_length = 5;
   }
   else if constexpr (sizeof(T) == 4) {
      max_length = 10;
   }
   else if constexpr (std::same_as<T, uint64_t>) {
      max_length = 20;
   }
   else if constexpr (std::same_as<T, int64_t>) {
      max_length = 19;
   }

   for (size_t i = 1; i <= max_length; ++i) {
      const auto& p = samples[i];
      T value{};
      if (glz::read_json(value, p.first)) {
         valid = false;
         break;
      }
      if (uint64_t(value) != p.second) {
         valid = false;
         break;
      }
   }
   return valid;
}

// ==================== Direct to_chars validation test suite ====================
// Tests that validate glz::to_chars output against std::to_chars for every possible value

suite to_chars_validation = [] {
   // Exhaustive tests for small integer types (every possible value)
   "to_chars uint8_t exhaustive"_test = [] { expect(validate_to_chars_exhaustive<uint8_t>()); };
   "to_chars int8_t exhaustive"_test = [] { expect(validate_to_chars_exhaustive<int8_t>()); };
   "to_chars uint16_t exhaustive"_test = [] { expect(validate_to_chars_exhaustive<uint16_t>()); };
   "to_chars int16_t exhaustive"_test = [] { expect(validate_to_chars_exhaustive<int16_t>()); };

   // Sample tests for larger types (exhaustive would take too long)
   "to_chars uint32_t samples"_test = [] {
      char glz_buf[32], std_buf[32];
      std::mt19937 rng(42);
      std::uniform_int_distribution<uint32_t> dist(0, (std::numeric_limits<uint32_t>::max)());

      auto test = [&](uint32_t val) {
         auto glz_end = glz::to_chars(glz_buf, val);
         auto [std_end, ec] = std::to_chars(std_buf, std_buf + 32, val);
         expect(ec == std::errc{});
         expect(std::string_view(glz_buf, glz_end) == std::string_view(std_buf, std_end)) << val;
      };

      test(0);
      test(1);
      test((std::numeric_limits<uint32_t>::max)());
      for (int i = 0; i < 100000; ++i) test(dist(rng));
   };
   "to_chars int32_t samples"_test = [] {
      // Test edge cases and random samples for to_chars (400B tables)
      char glz_buf[32], std_buf[32];
      std::mt19937 rng(42);
      std::uniform_int_distribution<int32_t> dist(std::numeric_limits<int32_t>::lowest(),
                                                  (std::numeric_limits<int32_t>::max)());

      auto test = [&](int32_t val) {
         auto glz_end = glz::to_chars(glz_buf, val);
         auto [std_end, ec] = std::to_chars(std_buf, std_buf + 32, val);
         expect(ec == std::errc{});
         expect(std::string_view(glz_buf, glz_end) == std::string_view(std_buf, std_end)) << val;
      };

      test(0);
      test(1);
      test(-1);
      test((std::numeric_limits<int32_t>::max)());
      test(std::numeric_limits<int32_t>::lowest());
      for (int i = 0; i < 100000; ++i) test(dist(rng));
   };

   // to_chars_40kb validation for 32/64-bit types
   "to_chars_40kb int32_t samples"_test = [] { expect(validate_to_chars_40kb_samples<int32_t>()); };
   "to_chars_40kb uint32_t samples"_test = [] { expect(validate_to_chars_40kb_samples<uint32_t>()); };
   "to_chars_40kb int64_t samples"_test = [] { expect(validate_to_chars_40kb_samples<int64_t>()); };
   "to_chars_40kb uint64_t samples"_test = [] { expect(validate_to_chars_40kb_samples<uint64_t>()); };
};

// We test parsing an array so that early termination triggers errors
suite u8_test = [] {
   "u8 full"_test = [] { expect(test_to_max<uint8_t>()); };

   "u8 lengths"_test = [] { expect(test_lengths<uint8_t>()); };

   "u8"_test = [] {
      using V = uint8_t;
      std::array<V, 2> value{};
      expect(not glz::read_json(value, "[0, 0]"));
      expect(value == std::array<V, 2>{0, 0});

      expect(not glz::read_json(value, "[1e0, 1e1]"));
      expect(value == std::array<V, 2>{1, 10});

      expect(not glz::read_json(value, "[25e0, 25e1]"));
      expect(value == std::array<V, 2>{25, 250});

      expect(not glz::read_json(value, "[254, 255]"));
      expect(value == std::array<V, 2>{254, 255});

      expect(glz::read_json(value, "[1e-1]"));
      expect(glz::read_json(value, "[1.0]"));
      expect(glz::read_json(value, "[0.1]"));
      expect(glz::read_json(value, "[00]"));
      expect(glz::read_json(value, "[01]"));
      expect(glz::read_json(value, "[256]"));
   };

   "u8 performance"_test = [] {
#ifndef _MSC_VER
      expect(test_performance<uint8_t>());
#endif
   };

   "i8"_test = [] {
      using V = int8_t;
      std::array<V, 2> value{};
      expect(not glz::read_json(value, "[0, 0]"));
      expect(value == std::array<V, 2>{0, 0});

      expect(not glz::read_json(value, "[1e0, 1e1]"));
      expect(value == std::array<V, 2>{1, 10});

      expect(not glz::read_json(value, "[12e0, 12e1]"));
      expect(value == std::array<V, 2>{12, 120});

      expect(not glz::read_json(value, "[126, 127]"));
      expect(value == std::array<V, 2>{126, 127});

      expect(not glz::read_json(value, "[-127, -128]"));
      expect(value == std::array<V, 2>{-127, -128});

      expect(not glz::read_json(value, "[-2e1, -3e0]"));
      expect(value == std::array<V, 2>{-20, -3});

      expect(not glz::read_json(value, "[-99, -100]"));
      expect(value == std::array<V, 2>{-99, -100});

      expect(glz::read_json(value, "[1e-1]"));
      expect(glz::read_json(value, "[1.0]"));
      expect(glz::read_json(value, "[0.1]"));
      expect(glz::read_json(value, "[00]"));
      expect(glz::read_json(value, "[-00]"));
      expect(glz::read_json(value, "[01]"));
      expect(glz::read_json(value, "[128]"));
      expect(glz::read_json(value, "[1e3]"));
   };

   "i8 full"_test = [] { expect(test_to_max<int8_t>()); };

   "i8 lengths"_test = [] { expect(test_lengths<int8_t>()); };

   "u16"_test = [] {
      using V = uint16_t;
      std::array<V, 2> value{};
      expect(not glz::read_json(value, "[0, 0]"));
      expect(value == std::array<V, 2>{0, 0});

      expect(not glz::read_json(value, "[1e0, 1e1]"));
      expect(value == std::array<V, 2>{1, 10});

      expect(not glz::read_json(value, "[25e0, 25e1]"));
      expect(value == std::array<V, 2>{25, 250});

      expect(not glz::read_json(value, "[65534, 65535]"));
      expect(value == std::array<V, 2>{65534, 65535});

      expect(not glz::read_json(value, "[1e3, 1e3]"));
      expect(value == std::array<V, 2>{1000, 1000});

      expect(glz::read_json(value, "[1e-1]"));
      expect(glz::read_json(value, "[1.0]"));
      expect(glz::read_json(value, "[0.1]"));
      expect(glz::read_json(value, "[00]"));
      expect(glz::read_json(value, "[01]"));
      expect(glz::read_json(value, "[65536]"));
      expect(glz::read_json(value, "[65536e0]"));
      expect(glz::read_json(value, "[65535e1]"));
      expect(glz::read_json(value, "[1e7]"));
   };

   "u16 sample"_test = [] { expect(test_to_max<uint16_t>()); };

   "u16 lengths"_test = [] { expect(test_lengths<uint16_t>()); };

   "i16"_test = [] {
      using V = int16_t;
      std::array<V, 2> value{};
      expect(not glz::read_json(value, "[0, 0]"));
      expect(value == std::array<V, 2>{0, 0});

      expect(not glz::read_json(value, "[1e0, 1e1]"));
      expect(value == std::array<V, 2>{1, 10});

      expect(not glz::read_json(value, "[25e0, 25e1]"));
      expect(value == std::array<V, 2>{25, 250});

      expect(not glz::read_json(value, "[32766, 32767]"));
      expect(value == std::array<V, 2>{32766, 32767});

      expect(not glz::read_json(value, "[-32767, -32768]"));
      expect(value == std::array<V, 2>{-32767, -32768});

      expect(not glz::read_json(value, "[1e3, 1e3]"));
      expect(value == std::array<V, 2>{1000, 1000});

      expect(glz::read_json(value, "[1e-1]"));
      expect(glz::read_json(value, "[1.0]"));
      expect(glz::read_json(value, "[0.1]"));
      expect(glz::read_json(value, "[00]"));
      expect(glz::read_json(value, "[01]"));
      expect(glz::read_json(value, "[32768]"));
      expect(glz::read_json(value, "[65536]"));
      expect(glz::read_json(value, "[65536e0]"));
      expect(glz::read_json(value, "[65535e1]"));
      expect(glz::read_json(value, "[1e7]"));
   };

   "i16 full"_test = [] { expect(test_to_max<int16_t>()); };

   "i16 lengths"_test = [] { expect(test_lengths<int16_t>()); };

   "u32"_test = [] {
      using V = uint32_t;
      std::array<V, 2> value{};
      expect(not glz::read_json(value, "[0, 0]"));
      expect(value == std::array<V, 2>{0, 0});

      expect(not glz::read_json(value, "[1e0, 1e1]"));
      expect(value == std::array<V, 2>{1, 10});

      expect(not glz::read_json(value, "[25e0, 25e1]"));
      expect(value == std::array<V, 2>{25, 250});

      expect(not glz::read_json(value, "[4294967294, 4294967295]"));
      expect(value == std::array<V, 2>{4294967294, 4294967295});

      expect(not glz::read_json(value, "[3034613894, 3034613894]"));
      expect(value == std::array<V, 2>{3034613894, 3034613894});

      expect(not glz::read_json(value, "[1e7, 12e7]"));
      expect(value == std::array<V, 2>{10000000, 120000000});

      expect(glz::read_json(value, "[1e-1]"));
      expect(glz::read_json(value, "[1.0]"));
      expect(glz::read_json(value, "[0.1]"));
      expect(glz::read_json(value, "[00]"));
      expect(glz::read_json(value, "[01]"));
      expect(glz::read_json(value, "[4294967296]"));
      expect(glz::read_json(value, "[4294967296e0]"));
      expect(glz::read_json(value, "[1e10]"));
   };

   "u32 samples"_test = [] { expect(test_samples<uint32_t>()); };

   "u32 lengths"_test = [] { expect(test_lengths<uint32_t>()); };

   "i32"_test = [] {
      using V = int32_t;
      std::array<V, 2> value{};
      expect(not glz::read_json(value, "[0, 0]"));
      expect(value == std::array<V, 2>{0, 0});

      expect(not glz::read_json(value, "[1e0, 1e1]"));
      expect(value == std::array<V, 2>{1, 10});

      expect(not glz::read_json(value, "[25e0, 25e1]"));
      expect(value == std::array<V, 2>{25, 250});

      expect(not glz::read_json(value, "[2147483646, 2147483647]"));
      expect(value == std::array<V, 2>{2147483646, 2147483647});

      expect(not glz::read_json(value, "[-2147483647, -2147483648]"));
      expect(value == std::array<V, 2>{-2147483647, -2147483648});

      expect(not glz::read_json(value, "[1e7, 12e7]"));
      expect(value == std::array<V, 2>{10000000, 120000000});

      expect(glz::read_json(value, "[1e-1]"));
      expect(glz::read_json(value, "[1.0]"));
      expect(glz::read_json(value, "[0.1]"));
      expect(glz::read_json(value, "[00]"));
      expect(glz::read_json(value, "[01]"));
      expect(glz::read_json(value, "[2147483648]"));
      expect(glz::read_json(value, "[2147483648e0]"));
      expect(glz::read_json(value, "[1e10]"));
   };

   "i32 samples"_test = [] { expect(test_samples<int32_t>()); };

   "i32 lengths"_test = [] { expect(test_lengths<int32_t>()); };

   "u64"_test = [] {
      using V = uint64_t;
      std::array<V, 2> value{};
      expect(not glz::read_json(value, "[0, 0]"));
      expect(value == std::array<V, 2>{0, 0});

      expect(not glz::read_json(value, "[1e0, 1e1]"));
      expect(value == std::array<V, 2>{1, 10});

      expect(not glz::read_json(value, "[25e0, 25e1]"));
      expect(value == std::array<V, 2>{25, 250});

      expect(not glz::read_json(value, "[18446744073709551614, 18446744073709551615]"));
      expect(value == std::array<V, 2>{18446744073709551614ull, 18446744073709551615ull});

      expect(not glz::read_json(value, "[123456789, 123456789]"));
      expect(value == std::array<V, 2>{123456789, 123456789});

      expect(not glz::read_json(value, "[73241774740596, 73241774740596]"));
      expect(value == std::array<V, 2>{73241774740596, 73241774740596});

      expect(not glz::read_json(value, "[1e10, 12e10]"));
      expect(value == std::array<V, 2>{10000000000, 120000000000});

      expect(not glz::read<glz::opts{.minified = true}>(value, "[4774870093504525206]"));

      expect(glz::read_json(value, "[1e-1]"));
      expect(glz::read_json(value, "[1.0]"));
      expect(glz::read_json(value, "[0.1]"));
      expect(glz::read_json(value, "[00]"));
      expect(glz::read_json(value, "[01]"));
      expect(glz::read_json(value, "[18446744073709551616]"));
      expect(glz::read_json(value, "[18446744073709551616e0]"));
      expect(glz::read_json(value, "[1e20]"));
   };

   "u64 samples"_test = [] { expect(test_samples<uint64_t>()); };

   "u64 lengths"_test = [] { expect(test_lengths<uint64_t>()); };

   "u64 performance"_test = [] { expect(test_performance<uint64_t>()); };

   "u64 single char performance"_test = [] { expect(test_single_char_performance<uint64_t>()); };

   "u64 array minified"_test = [] { test_struct_with_array_minified<uint64_t>(); };

   "i64"_test = [] {
      using V = int64_t;
      std::array<V, 2> value{};
      expect(not glz::read_json(value, "[0, 0]"));
      expect(value == std::array<V, 2>{0, 0});

      expect(not glz::read_json(value, "[1e0, 1e1]"));
      expect(value == std::array<V, 2>{1, 10});

      expect(not glz::read_json(value, "[25e0, 25e1]"));
      expect(value == std::array<V, 2>{25, 250});

      expect(not glz::read_json(value, "[9223372036854775806, 9223372036854775807]"));
      expect(value == std::array<V, 2>{9223372036854775806ull, 9223372036854775807ull});

      expect(not glz::read_json(value, "[-9223372036854775808, -9223372036854775808e0]"));
      expect(value == std::array<V, 2>{std::numeric_limits<V>::lowest(), std::numeric_limits<V>::lowest()});

      expect(not glz::read_json(value, "[1e10, 12e10]"));
      expect(value == std::array<V, 2>{10000000000, 120000000000});

      expect(not glz::read_json(value, "[469490602178186175, 469490602178186175]"));
      expect(value == std::array<V, 2>{469490602178186175ull, 469490602178186175ull});

      expect(not glz::read_json(value, "[-356839120500334504, -356839120500334504]"));
      expect(value == std::array<V, 2>{-356839120500334504, -356839120500334504});

      expect(not glz::read_json(value, "[-5594732989048119398, -5594732989048119398]"));
      expect(value == std::array<V, 2>{-5594732989048119398, -5594732989048119398});

      expect(not glz::read<glz::opts{.minified = true}>(value, "[337184269,337184283]"));
      expect(not glz::read<glz::opts{.minified = true}>(value, "[-5637358391044507426,-4563386007050245647]"));

      expect(glz::read_json(value, "[1e-1]"));
      expect(glz::read_json(value, "[1.0]"));
      expect(glz::read_json(value, "[0.1]"));
      expect(glz::read_json(value, "[00]"));
      expect(glz::read_json(value, "[01]"));
      expect(glz::read_json(value, "[9223372036854775808]"));
      expect(glz::read_json(value, "[9223372036854775808e0]"));
      expect(glz::read_json(value, "[1e19]"));
   };

   "i64 samples"_test = [] {
#ifndef _MSC_VER
      expect(test_samples<int64_t>());
#endif
   };

   "i64 lengths"_test = [] { expect(test_lengths<int64_t>()); };

   "i64 performance"_test = [] { expect(test_performance<int64_t>()); };

   "i64 single char performance"_test = [] { expect(test_single_char_performance<int64_t>()); };

   "i64 array minified"_test = [] { test_struct_with_array_minified<int64_t>(); };
};

int main() { return 0; }
