LLVMFuzzerTestOneInput:
    7|  11.3k|{
    8|       |   // non-null terminated
    9|  11.3k|   {
   10|  11.3k|      const std::vector<char> buffer{Data, Data + Size};
   11|       |
   12|  11.3k|      static constexpr glz::opts opts{.null_terminated = false};
   13|  11.3k|      glz::generic json{};
   14|  11.3k|      auto ec = glz::read<opts>(json, buffer);
   15|  11.3k|      if (!ec) {
  ------------------
  |  Branch (15:11): [True: 2.78k, False: 8.53k]
  ------------------
   16|  2.78k|         [[maybe_unused]] auto s = json.size();
   17|  2.78k|      }
   18|  11.3k|   }
   19|       |
   20|       |   // use a vector with null termination instead of a std::string to avoid
   21|       |   // small string optimization to hide bounds problems
   22|  11.3k|   std::vector<char> buffer{Data, Data + Size};
   23|  11.3k|   buffer.push_back('\0');
   24|       |
   25|       |   // const qualified input buffer
   26|  11.3k|   {
   27|  11.3k|      const auto& input = buffer;
   28|  11.3k|      glz::generic json{};
   29|  11.3k|      auto ec = glz::read_json(json, input);
   30|  11.3k|      if (!ec) {
  ------------------
  |  Branch (30:11): [True: 2.78k, False: 8.53k]
  ------------------
   31|  2.78k|         [[maybe_unused]] auto s = json.size();
   32|  2.78k|      }
   33|  11.3k|   }
   34|       |
   35|       |   // non-const input buffer
   36|  11.3k|   {
   37|  11.3k|      glz::generic json{};
   38|  11.3k|      auto ec = glz::read_json(json, buffer);
   39|  11.3k|      if (!ec) {
  ------------------
  |  Branch (39:11): [True: 2.78k, False: 8.53k]
  ------------------
   40|  2.78k|         [[maybe_unused]] auto s = json.size();
   41|  2.78k|      }
   42|  11.3k|   }
   43|       |
   44|  11.3k|   return 0;
   45|  11.3k|}

_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEED2Ev:
  569|   169k|      {
  570|   169k|         free_data();
  571|   169k|         free_index();
  572|   169k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE9free_dataEv:
  266|   169k|      {
  267|   169k|         destroy_all();
  268|   169k|         ::operator delete(data_);
  269|   169k|         data_ = nullptr;
  270|   169k|         size_ = 0;
  271|   169k|         capacity_ = 0;
  272|   169k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE11destroy_allEv:
  259|   433k|      {
  260|  6.67M|         for (uint32_t i = 0; i < size_; ++i) {
  ------------------
  |  Branch (260:31): [True: 6.23M, False: 433k]
  ------------------
  261|  6.23M|            std::destroy_at(data_ + i);
  262|  6.23M|         }
  263|   433k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE10free_indexEv:
  308|   169k|      {
  309|   169k|         std::free(index_);
  310|   169k|         index_ = nullptr;
  311|   169k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEEC2Ev:
  566|  81.3k|      ordered_small_map() = default;
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEEC2EOS4_:
  610|  88.3k|         : data_(other.data_), size_(other.size_), capacity_(other.capacity_), index_(other.index_)
  611|  88.3k|      {
  612|  88.3k|         other.data_ = nullptr;
  613|  88.3k|         other.size_ = 0;
  614|  88.3k|         other.capacity_ = 0;
  615|  88.3k|         other.index_ = nullptr;
  616|  88.3k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEEixERKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEE:
  932|  3.33M|      {
  933|  3.33M|         return subscript_or_insert(key, [&] { emplace_back_impl(key, mapped_type{}); });
  934|  3.33M|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE19subscript_or_insertINSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEZNS4_ixERKSC_EUlvE_EERS3_RKT_OT0_:
  491|  3.33M|      {
  492|  3.33M|         if (size_ <= linear_search_threshold) {
  ------------------
  |  Branch (492:14): [True: 525k, False: 2.81M]
  ------------------
  493|   525k|            auto it = linear_find(key);
  494|   525k|            if (it != end()) return it->second;
  ------------------
  |  Branch (494:17): [True: 21.0k, False: 504k]
  ------------------
  495|   504k|            append_fn();
  496|   504k|            return data_[size_ - 1].second;
  497|   525k|         }
  498|       |
  499|  2.81M|         const uint32_t h = hash_key(key);
  500|  2.81M|         if (try_bloom_insert(h, append_fn)) {
  ------------------
  |  Branch (500:14): [True: 1.82M, False: 985k]
  ------------------
  501|  1.82M|            return data_[size_ - 1].second;
  502|  1.82M|         }
  503|       |
  504|   985k|         auto [it, pos, _] = index_find_or_pos(key, h);
  505|   985k|         if (it != end()) return it->second;
  ------------------
  |  Branch (505:14): [True: 809k, False: 175k]
  ------------------
  506|       |
  507|   175k|         append_fn();
  508|   175k|         bloom_set(h);
  509|   175k|         if (index_size() > 0) {
  ------------------
  |  Branch (509:14): [True: 175k, False: 0]
  ------------------
  510|   175k|            const uint32_t n = index_->size;
  511|   175k|            ensure_index_capacity(static_cast<size_type>(n) + 1);
  512|   175k|            auto* entries = index_entries();
  513|   175k|            if (pos < n) {
  ------------------
  |  Branch (513:17): [True: 170k, False: 5.78k]
  ------------------
  514|   170k|               std::memmove(entries + pos + 1, entries + pos, (n - pos) * sizeof(hash_index_entry));
  515|   170k|            }
  516|   175k|            entries[pos] = {h, size_ - 1};
  517|   175k|            index_->size = size_;
  518|   175k|         }
  519|   175k|         return data_[size_ - 1].second;
  520|   985k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE11linear_findINSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEPNS6_4pairISC_S3_EERKT_:
  421|   525k|      {
  422|  2.46M|         for (uint32_t i = 0; i < size_; ++i) {
  ------------------
  |  Branch (422:31): [True: 1.95M, False: 504k]
  ------------------
  423|  1.95M|            if (data_[i].first == key) return data_ + i;
  ------------------
  |  Branch (423:17): [True: 21.0k, False: 1.93M]
  ------------------
  424|  1.95M|         }
  425|   504k|         return data_ + size_;
  426|   525k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE3endEv:
  649|  1.51M|      iterator end() noexcept { return data_ + size_; }
_ZZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEEixERKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEENKUlvE_clEv:
  933|  2.50M|         return subscript_or_insert(key, [&] { emplace_back_impl(key, mapped_type{}); });
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE17emplace_back_implIJRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEES3_EEEvDpOT_:
  243|  2.50M|      {
  244|  2.50M|         grow_if_needed();
  245|  2.50M|         std::construct_at(data_ + size_, std::forward<Args>(args)...);
  246|  2.50M|         ++size_;
  247|  2.50M|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE14grow_if_neededEv:
  217|  2.50M|      {
  218|  2.50M|         if (size_ == capacity_) {
  ------------------
  |  Branch (218:14): [True: 263k, False: 2.24M]
  ------------------
  219|   263k|            if (size_ == max_u32) {
  ------------------
  |  Branch (219:17): [True: 0, False: 263k]
  ------------------
  220|      0|               throw_capacity_overflow();
  221|      0|            }
  222|   263k|            const uint32_t new_cap = next_data_capacity(capacity_);
  223|   263k|            reallocate_data(new_cap);
  224|   263k|         }
  225|  2.50M|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE18next_data_capacityEj:
  120|   263k|      {
  121|   263k|         if (current == 0) return 4;
  ------------------
  |  Branch (121:14): [True: 73.6k, False: 190k]
  ------------------
  122|   190k|         if (current > (max_u32 / 2)) return max_u32;
  ------------------
  |  Branch (122:14): [True: 0, False: 190k]
  ------------------
  123|   190k|         return current * 2;
  124|   190k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE15reallocate_dataEj:
  205|   263k|      {
  206|   263k|         if (new_cap < size_) {
  ------------------
  |  Branch (206:14): [True: 0, False: 263k]
  ------------------
  207|      0|            throw_capacity_overflow();
  208|      0|         }
  209|   263k|         auto* new_data = allocate_and_relocate(new_cap);
  210|   263k|         destroy_all();
  211|   263k|         ::operator delete(data_);
  212|   263k|         data_ = new_data;
  213|   263k|         capacity_ = new_cap;
  214|   263k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE21allocate_and_relocateEj:
  159|   263k|      {
  160|   263k|         auto* new_data = static_cast<value_type*>(::operator new(checked_data_allocation_bytes(new_cap)));
  161|   263k|#if __cpp_exceptions
  162|   263k|         uint32_t constructed = 0;
  163|   263k|         try {
  164|  3.99M|            for (; constructed < size_; ++constructed) {
  ------------------
  |  Branch (164:20): [True: 3.73M, False: 263k]
  ------------------
  165|  3.73M|               std::construct_at(new_data + constructed, std::move_if_noexcept(data_[constructed]));
  166|  3.73M|            }
  167|   263k|         }
  168|   263k|         catch (...) {
  169|      0|            destroy_range(new_data, constructed);
  170|      0|            ::operator delete(new_data);
  171|      0|            throw;
  172|      0|         }
  173|       |#else
  174|       |         for (uint32_t i = 0; i < size_; ++i) {
  175|       |            std::construct_at(new_data + i, std::move_if_noexcept(data_[i]));
  176|       |         }
  177|       |#endif
  178|   263k|         return new_data;
  179|   263k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE29checked_data_allocation_bytesEj:
  134|   263k|      {
  135|   263k|         if (count > ((std::numeric_limits<size_t>::max)() / sizeof(value_type))) {
  ------------------
  |  Branch (135:14): [True: 0, False: 263k]
  ------------------
  136|      0|            GLZ_THROW_OR_ABORT(std::bad_alloc{});
  ------------------
  |  |    8|      0|#define GLZ_THROW_OR_ABORT(EXC) (throw(EXC))
  ------------------
  137|      0|         }
  138|   263k|         return static_cast<size_t>(count) * sizeof(value_type);
  139|   263k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE8hash_keyENSt3__117basic_string_viewIcNS5_11char_traitsIcEEEE:
   97|  8.70M|      static uint32_t hash_key(std::string_view key) noexcept { return sweethash::sweet32(key); }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE16try_bloom_insertIRZNS4_ixERKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEUlvE_EEbjOT_:
  529|  2.81M|      {
  530|  2.81M|         if (index_ && size_ <= bloom_threshold && !bloom_maybe_contains(h)) {
  ------------------
  |  Branch (530:14): [True: 2.76M, False: 51.1k]
  |  Branch (530:24): [True: 2.63M, False: 121k]
  |  Branch (530:52): [True: 1.82M, False: 812k]
  ------------------
  531|       |            // Definitely not present — skip the search
  532|  1.82M|            append_fn();
  533|  1.82M|            bloom_set(h);
  534|       |            // Index is now stale (index_->size < size_), will rebuild on next lookup or false positive
  535|  1.82M|            return true;
  536|  1.82M|         }
  537|   985k|         return false;
  538|  2.81M|      }
_ZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE20bloom_maybe_containsEj:
  285|  2.63M|      {
  286|  2.63M|         const uint32_t a = h & bloom_mask;
  287|  2.63M|         const uint32_t b = (h >> 10) & bloom_mask;
  288|  2.63M|         return (index_->bloom[a >> 3] & (uint8_t(1) << (a & 7))) && (index_->bloom[b >> 3] & (uint8_t(1) << (b & 7)));
  ------------------
  |  Branch (288:17): [True: 959k, False: 1.67M]
  |  Branch (288:70): [True: 812k, False: 146k]
  ------------------
  289|  2.63M|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE17index_find_or_posINSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEENS4_17index_find_resultERKT_j:
  400|   985k|      {
  401|   985k|         ensure_index();
  402|       |
  403|   985k|         const auto* base = index_entries();
  404|   985k|         const auto* idx_end = base + index_->size;
  405|   985k|         const auto* p = branchless_lower_bound(base, index_->size, h);
  406|   985k|         const size_t pos = static_cast<size_t>(p - base);
  407|       |
  408|       |         // Scan adjacent entries with matching hash
  409|   992k|         for (auto* scan = p; scan != idx_end && scan->key_hash == h; ++scan) {
  ------------------
  |  Branch (409:31): [True: 986k, False: 5.78k]
  |  Branch (409:50): [True: 816k, False: 170k]
  ------------------
  410|   816k|            if (data_[scan->index].first == key) {
  ------------------
  |  Branch (410:17): [True: 809k, False: 6.76k]
  ------------------
  411|   809k|               return {data_ + scan->index, pos, h};
  412|   809k|            }
  413|   816k|         }
  414|       |
  415|   175k|         return {data_ + size_, pos, h};
  416|   985k|      }
_ZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE12ensure_indexEv:
  360|   985k|      {
  361|   985k|         if (size_ <= linear_search_threshold) return;
  ------------------
  |  Branch (361:14): [True: 0, False: 985k]
  ------------------
  362|   985k|         const auto current = index_size();
  363|   985k|         if (current == size_) return; // fully current
  ------------------
  |  Branch (363:14): [True: 650k, False: 334k]
  ------------------
  364|       |
  365|   334k|         if (current == 0 || (size_ - current) > linear_search_threshold) {
  ------------------
  |  Branch (365:14): [True: 51.1k, False: 283k]
  |  Branch (365:30): [True: 90.5k, False: 193k]
  ------------------
  366|   141k|            rebuild_index(); // full rebuild
  367|   141k|            return;
  368|   141k|         }
  369|       |
  370|       |         // Incrementally insert-sort the few new entries
  371|   608k|         for (uint32_t i = current; i < size_; ++i) {
  ------------------
  |  Branch (371:37): [True: 415k, False: 193k]
  ------------------
  372|   415k|            const hash_index_entry entry{hash_key(data_[i].first), i};
  373|   415k|            const auto* base = index_entries();
  374|   415k|            const auto* p = branchless_lower_bound(base, index_->size, entry.key_hash);
  375|   415k|            auto pos = static_cast<size_t>(p - base);
  376|       |
  377|   415k|            const uint32_t m = index_->size;
  378|   415k|            ensure_index_capacity(static_cast<size_type>(m) + 1);
  379|   415k|            auto* entries = index_entries();
  380|   415k|            if (pos < m) {
  ------------------
  |  Branch (380:17): [True: 398k, False: 17.1k]
  ------------------
  381|   398k|               std::memmove(entries + pos + 1, entries + pos, (m - pos) * sizeof(hash_index_entry));
  382|   398k|            }
  383|   415k|            entries[pos] = entry;
  384|   415k|            index_->size = i + 1;
  385|   415k|         }
  386|   193k|      }
_ZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE13rebuild_indexEv:
  343|   141k|      {
  344|   141k|         ensure_index_capacity(static_cast<size_type>(size_));
  345|   141k|         bloom_clear();
  346|   141k|         auto* entries = index_entries();
  347|  5.61M|         for (uint32_t i = 0; i < size_; ++i) {
  ------------------
  |  Branch (347:31): [True: 5.47M, False: 141k]
  ------------------
  348|  5.47M|            const uint32_t h = hash_key(data_[i].first);
  349|  5.47M|            entries[i] = {h, i};
  350|  5.47M|            bloom_set(h);
  351|  5.47M|         }
  352|   141k|         std::sort(entries, entries + size_, [](const auto& a, const auto& b) { return a.key_hash < b.key_hash; });
  353|   141k|         index_->size = size_;
  354|   141k|      }
_ZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE11bloom_clearEv:
  291|   141k|      void bloom_clear() const noexcept { std::memset(index_->bloom, 0, bloom_bytes); }
_ZZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE13rebuild_indexEvENKUlRKT_RKT0_E_clINS4_16hash_index_entryESD_EEDaS7_SA_:
  352|  37.6M|         std::sort(entries, entries + size_, [](const auto& a, const auto& b) { return a.key_hash < b.key_hash; });
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE22branchless_lower_boundEPKNS4_16hash_index_entryEmj:
  440|  1.40M|      {
  441|  10.3M|         while (len > 1) {
  ------------------
  |  Branch (441:17): [True: 8.92M, False: 1.40M]
  ------------------
  442|  8.92M|            size_t half = len / 2;
  443|  8.92M|            p += (p[half - 1].key_hash < target) * half;
  444|  8.92M|            len -= half;
  445|  8.92M|         }
  446|       |         // Final element check: advance past it if it's less than target
  447|  1.40M|         p += (len == 1 && p->key_hash < target);
  ------------------
  |  Branch (447:16): [True: 1.40M, False: 0]
  |  Branch (447:28): [True: 22.9k, False: 1.37M]
  ------------------
  448|  1.40M|         return p;
  449|  1.40M|      }
_ZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE9bloom_setEj:
  277|  7.47M|      {
  278|  7.47M|         const uint32_t a = h & bloom_mask;
  279|  7.47M|         const uint32_t b = (h >> 10) & bloom_mask;
  280|  7.47M|         index_->bloom[a >> 3] |= uint8_t(1) << (a & 7);
  281|  7.47M|         index_->bloom[b >> 3] |= uint8_t(1) << (b & 7);
  282|  7.47M|      }
_ZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE10index_sizeEv:
  300|  1.16M|      uint32_t index_size() const noexcept { return index_ ? index_->size : 0; }
  ------------------
  |  Branch (300:53): [True: 1.11M, False: 51.1k]
  ------------------
_ZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE21ensure_index_capacityEm:
  314|   733k|      {
  315|   733k|         if (needed == 0) return;
  ------------------
  |  Branch (315:14): [True: 0, False: 733k]
  ------------------
  316|   733k|         if (needed > static_cast<size_type>(max_u32)) {
  ------------------
  |  Branch (316:14): [True: 0, False: 733k]
  ------------------
  317|      0|            throw_index_overflow();
  318|      0|         }
  319|   733k|         const auto needed_u32 = static_cast<uint32_t>(needed);
  320|   733k|         if (index_ && index_->capacity >= needed_u32) return;
  ------------------
  |  Branch (320:14): [True: 682k, False: 51.1k]
  |  Branch (320:24): [True: 605k, False: 77.0k]
  ------------------
  321|   128k|         uint32_t cap = index_ ? index_->capacity : 0;
  ------------------
  |  Branch (321:25): [True: 77.0k, False: 51.1k]
  ------------------
  322|   261k|         while (cap < needed_u32) {
  ------------------
  |  Branch (322:17): [True: 132k, False: 128k]
  ------------------
  323|   132k|            const uint32_t next = next_index_capacity(cap);
  324|   132k|            if (next <= cap) {
  ------------------
  |  Branch (324:17): [True: 0, False: 132k]
  ------------------
  325|      0|               throw_index_overflow();
  326|      0|            }
  327|   132k|            cap = next;
  328|   132k|         }
  329|   128k|         auto* block = static_cast<index_header*>(std::realloc(index_, checked_index_allocation_bytes(cap)));
  330|   128k|         if (!block) GLZ_THROW_OR_ABORT(std::bad_alloc{});
  ------------------
  |  |    8|      0|#define GLZ_THROW_OR_ABORT(EXC) (throw(EXC))
  ------------------
  |  Branch (330:14): [True: 0, False: 128k]
  ------------------
  331|   128k|         if (!index_) {
  ------------------
  |  Branch (331:14): [True: 51.1k, False: 77.0k]
  ------------------
  332|  51.1k|            block->size = 0;
  333|  51.1k|            std::memset(block->bloom, 0, bloom_bytes);
  334|  51.1k|         }
  335|   128k|         block->capacity = cap;
  336|   128k|         index_ = block;
  337|   128k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE19next_index_capacityEj:
  127|   132k|      {
  128|   132k|         if (current == 0) return 16;
  ------------------
  |  Branch (128:14): [True: 51.1k, False: 81.8k]
  ------------------
  129|  81.8k|         if (current > (max_u32 / 2)) return max_u32;
  ------------------
  |  Branch (129:14): [True: 0, False: 81.8k]
  ------------------
  130|  81.8k|         return current * 2;
  131|  81.8k|      }
_ZN3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE30checked_index_allocation_bytesEj:
  142|   128k|      {
  143|   128k|         constexpr size_t header = sizeof(index_header);
  144|   128k|         constexpr size_t entry = sizeof(hash_index_entry);
  145|   128k|         if (count > (((std::numeric_limits<size_t>::max)() - header) / entry)) {
  ------------------
  |  Branch (145:14): [True: 0, False: 128k]
  ------------------
  146|      0|            GLZ_THROW_OR_ABORT(std::bad_alloc{});
  ------------------
  |  |    8|      0|#define GLZ_THROW_OR_ABORT(EXC) (throw(EXC))
  ------------------
  147|      0|         }
  148|   128k|         return header + static_cast<size_t>(count) * entry;
  149|   128k|      }
_ZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE13index_entriesEv:
  296|  2.13M|      {
  297|  2.13M|         return static_cast<hash_index_entry*>(static_cast<void*>(index_ + 1));
  298|  2.13M|      }
_ZNK3glz17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES0_EEE4sizeEv:
  663|      9|      size_type size() const noexcept { return size_; }

_ZN3glz10get_memberIRNS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEERKMS4_NSt3__17variantIJDndNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEbNS6_6vectorIS4_NSB_IS4_EEEENS3_IS4_EEEEEEEDcOT_OT0_:
  616|  8.47M|   {
  617|  8.47M|      using V = std::decay_t<decltype(element)>;
  618|  8.47M|      if constexpr (std::is_member_object_pointer_v<V>) {
  619|  8.47M|         return value.*element;
  620|       |      }
  621|       |      else if constexpr (std::is_member_function_pointer_v<V>) {
  622|       |         return element;
  623|       |      }
  624|       |      else if constexpr (std::invocable<Element, Value> && not eigen_t<Element>) {
  625|       |         // Eigen places a static_assert inside of the operator()(), so we must target
  626|       |         // matrix types and reject them from the invocable check
  627|       |         // Eigen ought to put the check in the `enable_if` for operator()()
  628|       |         return std::invoke(std::forward<Element>(element), std::forward<Value>(value));
  629|       |      }
  630|       |      else if constexpr (std::is_pointer_v<V> && !std::is_reference_v<Element>) {
  631|       |         if constexpr (std::invocable<decltype(*element), Value>) {
  632|       |            return std::invoke(*element, std::forward<Value>(value));
  633|       |         }
  634|       |         else {
  635|       |            return *element;
  636|       |         }
  637|       |      }
  638|       |      else {
  639|       |         return element;
  640|       |      }
  641|  8.47M|   }

_ZNK3glz9error_ctxcvbEv:
  136|  33.9k|      operator bool() const noexcept { return ec != error_code::none; }
_ZN3glz11enter_depthITkNS_10is_contextENS_7contextEEEbRT_:
  281|  1.87M|   {
  282|  1.87M|      if (ctx.depth >= max_recursive_depth_limit) [[unlikely]] {
  ------------------
  |  Branch (282:11): [True: 47, False: 1.87M]
  ------------------
  283|     47|         ctx.error = error_code::exceeded_max_recursive_depth;
  284|     47|         return true;
  285|     47|      }
  286|  1.87M|      ++ctx.depth;
  287|  1.87M|      return false;
  288|  1.87M|   }
_ZN3glz18charge_speculationITkNS_10is_contextENS_7contextEEEbRT_m:
  249|  51.1k|   {
  250|  51.1k|      if constexpr (requires { ctx.speculation_budget; }) {
  251|  51.1k|         if (ctx.speculation_budget == 0) {
  ------------------
  |  Branch (251:14): [True: 0, False: 51.1k]
  ------------------
  252|      0|            return true;
  253|      0|         }
  254|  51.1k|         ctx.speculation_budget = consumed >= ctx.speculation_budget ? 1 : ctx.speculation_budget - consumed;
  ------------------
  |  Branch (254:35): [True: 0, False: 51.1k]
  ------------------
  255|  51.1k|         return ctx.speculation_budget > 1;
  256|       |      }
  257|       |      else {
  258|       |         return true;
  259|       |      }
  260|  51.1k|   }
_ZN3glz21speculation_exhaustedITkNS_10is_contextENS_7contextEEEbRT_:
  266|  3.02k|   {
  267|  3.02k|      if constexpr (requires { ctx.speculation_budget; }) {
  268|  3.02k|         return ctx.speculation_budget == 1; // the latched floor; 0 means unbudgeted
  269|       |      }
  270|       |      else {
  271|       |         return false;
  272|       |      }
  273|  3.02k|   }

_ZN3glz4readITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10contiguousERKNSt3__16vectorIcNS6_9allocatorIcEEEEQaa14read_supportedIT0_XdtT_6formatEEnt18is_input_streamingIT1_EEENS_9error_ctxERSD_OSE_:
  219|  11.3k|   {
  220|  11.3k|      format_context_t<Opts.format> ctx{};
  221|  11.3k|      return read<Opts>(value, buffer, ctx);
  222|  11.3k|   }
_ZN3glz4readITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10contiguousERKNSt3__16vectorIcNS6_9allocatorIcEEEETkNS_10is_contextERNS_7contextEQaa14read_supportedIT0_XdtT_6formatEEnt18is_input_streamingIT1_EEENS_9error_ctxERSF_OSG_OT2_:
  136|  11.3k|   {
  137|  11.3k|      static_assert(sizeof(decltype(*buffer.data())) == 1);
  138|  11.3k|      using Buffer = std::remove_reference_t<decltype(buffer)>;
  139|       |
  140|  11.3k|      if constexpr (Opts.format != NDJSON) {
  141|  11.3k|         if (buffer.empty()) [[unlikely]] {
  ------------------
  |  Branch (141:14): [True: 0, False: 11.3k]
  ------------------
  142|      0|            ctx.error = error_code::no_read_input;
  143|      0|            return {0, ctx.error, ctx.custom_error_message};
  144|      0|         }
  145|  11.3k|      }
  146|       |
  147|  11.3k|      constexpr bool use_padded = resizable<Buffer> && non_const_buffer<Buffer> && !check_disable_padding(Opts);
  ------------------
  |  Branch (147:35): [Folded, False: 11.3k]
  |  Branch (147:56): [Folded, False: 0]
  |  Branch (147:84): [True: 0, Folded]
  ------------------
  148|       |
  149|  11.3k|      [[maybe_unused]] size_t original_size{};
  150|       |      if constexpr (use_padded) {
  151|       |         // Pad the buffer for SWAR
  152|       |         original_size = buffer.size();
  153|       |         buffer.resize(original_size + padding_bytes);
  154|       |      }
  155|       |
  156|  11.3k|      auto [it, end] = read_iterators<Opts, use_padded>(buffer);
  157|  11.3k|      auto start = it;
  158|  11.3k|      if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (158:11): [True: 0, False: 11.3k]
  ------------------
  159|      0|         goto finish;
  160|      0|      }
  161|       |
  162|       |      // Bound the speculative re-parsing a variant resolution may do, in bytes, relative to this
  163|       |      // input. Seeded per read so a reused context starts fresh. See charge_speculation.
  164|  11.3k|      if constexpr (requires { ctx.speculation_budget; }) {
  165|  11.3k|         const size_t proportional = max_speculative_parse_factor * size_t(end - it);
  166|  11.3k|         ctx.speculation_budget =
  167|  11.3k|            (proportional > min_speculative_parse_bytes ? proportional : min_speculative_parse_bytes) + 2;
  ------------------
  |  Branch (167:14): [True: 307, False: 11.0k]
  ------------------
  168|  11.3k|      }
  169|       |
  170|       |      // A YAML context marks its outermost parse with stream_begin and seeds its expansion budgets
  171|       |      // there, so clearing it here is what makes those budgets per-read like the one above. A
  172|       |      // reused context would otherwise carry a spent budget into the next document and reject a
  173|       |      // valid one, and would leave stream_begin pointing into the buffer of the previous read.
  174|       |      // Nested YAML parses do not route through glz::read, so they still cannot reseed themselves.
  175|       |      if constexpr (requires { ctx.stream_begin; }) {
  176|       |         ctx.stream_begin = nullptr;
  177|       |      }
  178|       |
  179|       |      if constexpr (use_padded) {
  180|       |         parse<Opts.format>::template op<is_padded_on<Opts>()>(value, ctx, it, end);
  181|       |      }
  182|  11.3k|      else {
  183|  11.3k|         parse<Opts.format>::template op<is_padded_off<Opts>()>(value, ctx, it, end);
  184|  11.3k|      }
  185|       |
  186|  11.3k|      if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (186:11): [True: 8.53k, False: 2.78k]
  ------------------
  187|  8.53k|         goto finish;
  188|  8.53k|      }
  189|       |
  190|       |      // The JSON RFC 8259 defines: JSON-text = ws value ws
  191|       |      // So, trailing whitespace is permitted and sometimes we want to
  192|       |      // validate this, even though this memory will not affect Glaze.
  193|       |      if constexpr (check_validate_trailing_whitespace(Opts)) {
  194|       |         if (it < end) {
  195|       |            skip_ws<Opts>(ctx, it, end);
  196|       |            if (bool(ctx.error)) [[unlikely]] {
  197|       |               goto finish;
  198|       |            }
  199|       |            if (it != end) [[unlikely]] {
  200|       |               ctx.error = error_code::syntax_error;
  201|       |            }
  202|       |         }
  203|       |      }
  204|       |
  205|  11.3k|   finish:
  206|  11.3k|      finalize_top_level_read<Opts>(ctx, start, it, end);
  207|       |
  208|       |      if constexpr (use_padded) {
  209|       |         // Restore the original buffer state
  210|       |         buffer.resize(original_size);
  211|       |      }
  212|       |
  213|  11.3k|      return {size_t(it - start), ctx.error, ctx.custom_error_message};
  214|  2.78k|   }
_ZN3glz14read_iteratorsITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEELb0ETkNS_10contiguousERKNSt3__16vectorIcNS2_9allocatorIcEEEEEEDaOT1_:
   40|  11.3k|   {
   41|  11.3k|      static_assert(sizeof(decltype(*buffer.data())) == 1);
   42|       |
   43|  11.3k|      auto it = reinterpret_cast<const char*>(buffer.data());
   44|  11.3k|      auto end = reinterpret_cast<const char*>(buffer.data()); // to be incremented
   45|       |
   46|       |      if constexpr (Padded) {
   47|       |         end += buffer.size() - padding_bytes;
   48|       |      }
   49|  11.3k|      else {
   50|  11.3k|         end += buffer.size();
   51|  11.3k|      }
   52|       |
   53|  11.3k|      return std::pair{it, end};
   54|  11.3k|   }
_ZN3glz23finalize_top_level_readITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextEEEvOT0_PKcS7_S7_:
  115|  11.3k|   {
  116|  11.3k|      if constexpr (Opts.format == JSON && !check_null_terminated(Opts)) {
  117|       |         // Deliberately not [[unlikely]]: a body that ends with the buffer lands here on every
  118|       |         // successful read, which is the ordinary case for a registry parsing a wire span.
  119|       |         // start < it, not !=, because a streaming origin can be empty or overshoot on an error
  120|       |         // path; neither is an absent value.
  121|  11.3k|         if (ctx.error == error_code::end_reached && ctx.depth == 0 && it == end && start < it) {
  ------------------
  |  Branch (121:14): [True: 1.68k, False: 9.63k]
  |  Branch (121:54): [True: 15, False: 1.67k]
  |  Branch (121:72): [True: 15, False: 0]
  |  Branch (121:85): [True: 15, False: 0]
  ------------------
  122|     15|            context ws_ctx{}; // only written to when skip_ws parses a comment; the result is unused
  123|     15|            const char* consumed = start;
  124|     15|            skip_ws<Opts>(ws_ctx, consumed, it);
  125|     15|            if (consumed == it) {
  ------------------
  |  Branch (125:17): [True: 13, False: 2]
  ------------------
  126|     13|               ctx.error = error_code::no_read_input;
  127|     13|            }
  128|     15|         }
  129|  11.3k|      }
  130|  11.3k|      finalize_read_context<Opts>(ctx);
  131|  11.3k|   }
_ZN3glz21finalize_read_contextITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextEEEvOT0_:
   76|  11.3k|   {
   77|       |      // A partial read stops as soon as it has the fields it was asked for, so it unwinds through
   78|       |      // its enclosing containers on an error code rather than through their closing braces, and
   79|       |      // none of them decrement depth on the way out. Depth is left standing at whatever nesting the
   80|       |      // last field sat at.
   81|       |      //
   82|       |      // That has to be cleared here rather than left for the next read to trip over. This is the
   83|       |      // one path that reports success with depth still raised, and depth is what settle_end_reached
   84|       |      // reads to tell a completed parse from a truncated one -- so a context reused after a partial
   85|       |      // read would see a later well-formed buffer settle to unexpected_end. Reads that end any
   86|       |      // other way either return depth to zero themselves or carry an error, and a context holding
   87|       |      // an error short-circuits the next read before it parses anything.
   88|       |      if constexpr (check_partial_read(Opts)) {
   89|       |         if (ctx.error == error_code::partial_read_complete) [[likely]] {
   90|       |            ctx.error = error_code::none;
   91|       |            ctx.depth = 0;
   92|       |            return;
   93|       |         }
   94|       |      }
   95|  11.3k|      settle_end_reached(ctx);
   96|  11.3k|   }
_ZN3glz18settle_end_reachedITkNS_10is_contextERNS_7contextEEEvOT_:
   68|  33.9k|   {
   69|  33.9k|      if (ctx.error == error_code::end_reached) {
  ------------------
  |  Branch (69:11): [True: 1.67k, False: 32.2k]
  ------------------
   70|  1.67k|         ctx.error = (ctx.depth == 0) ? error_code::none : error_code::unexpected_end;
  ------------------
  |  Branch (70:22): [True: 2, False: 1.67k]
  ------------------
   71|  1.67k|      }
   72|  33.9k|   }
_ZN3glz4readITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10contiguousERKNSt3__16vectorIcNS6_9allocatorIcEEEETkNS_10is_contextERNS_7contextEQaa14read_supportedIT0_XdtT_6formatEEnt18is_input_streamingIT1_EEENS_9error_ctxERSF_OSG_OT2_:
  136|  11.3k|   {
  137|  11.3k|      static_assert(sizeof(decltype(*buffer.data())) == 1);
  138|  11.3k|      using Buffer = std::remove_reference_t<decltype(buffer)>;
  139|       |
  140|  11.3k|      if constexpr (Opts.format != NDJSON) {
  141|  11.3k|         if (buffer.empty()) [[unlikely]] {
  ------------------
  |  Branch (141:14): [True: 0, False: 11.3k]
  ------------------
  142|      0|            ctx.error = error_code::no_read_input;
  143|      0|            return {0, ctx.error, ctx.custom_error_message};
  144|      0|         }
  145|  11.3k|      }
  146|       |
  147|  11.3k|      constexpr bool use_padded = resizable<Buffer> && non_const_buffer<Buffer> && !check_disable_padding(Opts);
  ------------------
  |  Branch (147:35): [Folded, False: 11.3k]
  |  Branch (147:56): [Folded, False: 0]
  |  Branch (147:84): [True: 0, Folded]
  ------------------
  148|       |
  149|  11.3k|      [[maybe_unused]] size_t original_size{};
  150|       |      if constexpr (use_padded) {
  151|       |         // Pad the buffer for SWAR
  152|       |         original_size = buffer.size();
  153|       |         buffer.resize(original_size + padding_bytes);
  154|       |      }
  155|       |
  156|  11.3k|      auto [it, end] = read_iterators<Opts, use_padded>(buffer);
  157|  11.3k|      auto start = it;
  158|  11.3k|      if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (158:11): [True: 0, False: 11.3k]
  ------------------
  159|      0|         goto finish;
  160|      0|      }
  161|       |
  162|       |      // Bound the speculative re-parsing a variant resolution may do, in bytes, relative to this
  163|       |      // input. Seeded per read so a reused context starts fresh. See charge_speculation.
  164|  11.3k|      if constexpr (requires { ctx.speculation_budget; }) {
  165|  11.3k|         const size_t proportional = max_speculative_parse_factor * size_t(end - it);
  166|  11.3k|         ctx.speculation_budget =
  167|  11.3k|            (proportional > min_speculative_parse_bytes ? proportional : min_speculative_parse_bytes) + 2;
  ------------------
  |  Branch (167:14): [True: 310, False: 11.0k]
  ------------------
  168|  11.3k|      }
  169|       |
  170|       |      // A YAML context marks its outermost parse with stream_begin and seeds its expansion budgets
  171|       |      // there, so clearing it here is what makes those budgets per-read like the one above. A
  172|       |      // reused context would otherwise carry a spent budget into the next document and reject a
  173|       |      // valid one, and would leave stream_begin pointing into the buffer of the previous read.
  174|       |      // Nested YAML parses do not route through glz::read, so they still cannot reseed themselves.
  175|       |      if constexpr (requires { ctx.stream_begin; }) {
  176|       |         ctx.stream_begin = nullptr;
  177|       |      }
  178|       |
  179|       |      if constexpr (use_padded) {
  180|       |         parse<Opts.format>::template op<is_padded_on<Opts>()>(value, ctx, it, end);
  181|       |      }
  182|  11.3k|      else {
  183|  11.3k|         parse<Opts.format>::template op<is_padded_off<Opts>()>(value, ctx, it, end);
  184|  11.3k|      }
  185|       |
  186|  11.3k|      if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (186:11): [True: 8.53k, False: 2.78k]
  ------------------
  187|  8.53k|         goto finish;
  188|  8.53k|      }
  189|       |
  190|       |      // The JSON RFC 8259 defines: JSON-text = ws value ws
  191|       |      // So, trailing whitespace is permitted and sometimes we want to
  192|       |      // validate this, even though this memory will not affect Glaze.
  193|       |      if constexpr (check_validate_trailing_whitespace(Opts)) {
  194|       |         if (it < end) {
  195|       |            skip_ws<Opts>(ctx, it, end);
  196|       |            if (bool(ctx.error)) [[unlikely]] {
  197|       |               goto finish;
  198|       |            }
  199|       |            if (it != end) [[unlikely]] {
  200|       |               ctx.error = error_code::syntax_error;
  201|       |            }
  202|       |         }
  203|       |      }
  204|       |
  205|  11.3k|   finish:
  206|  11.3k|      finalize_top_level_read<Opts>(ctx, start, it, end);
  207|       |
  208|       |      if constexpr (use_padded) {
  209|       |         // Restore the original buffer state
  210|       |         buffer.resize(original_size);
  211|       |      }
  212|       |
  213|  11.3k|      return {size_t(it - start), ctx.error, ctx.custom_error_message};
  214|  2.78k|   }
_ZN3glz14read_iteratorsITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEELb0ETkNS_10contiguousERKNSt3__16vectorIcNS2_9allocatorIcEEEEEEDaOT1_:
   40|  11.3k|   {
   41|  11.3k|      static_assert(sizeof(decltype(*buffer.data())) == 1);
   42|       |
   43|  11.3k|      auto it = reinterpret_cast<const char*>(buffer.data());
   44|  11.3k|      auto end = reinterpret_cast<const char*>(buffer.data()); // to be incremented
   45|       |
   46|       |      if constexpr (Padded) {
   47|       |         end += buffer.size() - padding_bytes;
   48|       |      }
   49|  11.3k|      else {
   50|  11.3k|         end += buffer.size();
   51|  11.3k|      }
   52|       |
   53|  11.3k|      return std::pair{it, end};
   54|  11.3k|   }
_ZN3glz23finalize_top_level_readITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextEEEvOT0_PKcS7_S7_:
  115|  22.6k|   {
  116|       |      if constexpr (Opts.format == JSON && !check_null_terminated(Opts)) {
  117|       |         // Deliberately not [[unlikely]]: a body that ends with the buffer lands here on every
  118|       |         // successful read, which is the ordinary case for a registry parsing a wire span.
  119|       |         // start < it, not !=, because a streaming origin can be empty or overshoot on an error
  120|       |         // path; neither is an absent value.
  121|       |         if (ctx.error == error_code::end_reached && ctx.depth == 0 && it == end && start < it) {
  122|       |            context ws_ctx{}; // only written to when skip_ws parses a comment; the result is unused
  123|       |            const char* consumed = start;
  124|       |            skip_ws<Opts>(ws_ctx, consumed, it);
  125|       |            if (consumed == it) {
  126|       |               ctx.error = error_code::no_read_input;
  127|       |            }
  128|       |         }
  129|       |      }
  130|  22.6k|      finalize_read_context<Opts>(ctx);
  131|  22.6k|   }
_ZN3glz21finalize_read_contextITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextEEEvOT0_:
   76|  22.6k|   {
   77|       |      // A partial read stops as soon as it has the fields it was asked for, so it unwinds through
   78|       |      // its enclosing containers on an error code rather than through their closing braces, and
   79|       |      // none of them decrement depth on the way out. Depth is left standing at whatever nesting the
   80|       |      // last field sat at.
   81|       |      //
   82|       |      // That has to be cleared here rather than left for the next read to trip over. This is the
   83|       |      // one path that reports success with depth still raised, and depth is what settle_end_reached
   84|       |      // reads to tell a completed parse from a truncated one -- so a context reused after a partial
   85|       |      // read would see a later well-formed buffer settle to unexpected_end. Reads that end any
   86|       |      // other way either return depth to zero themselves or carry an error, and a context holding
   87|       |      // an error short-circuits the next read before it parses anything.
   88|       |      if constexpr (check_partial_read(Opts)) {
   89|       |         if (ctx.error == error_code::partial_read_complete) [[likely]] {
   90|       |            ctx.error = error_code::none;
   91|       |            ctx.depth = 0;
   92|       |            return;
   93|       |         }
   94|       |      }
   95|  22.6k|      settle_end_reached(ctx);
   96|  22.6k|   }
_ZN3glz4readITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10contiguousERNSt3__16vectorIcNS6_9allocatorIcEEEETkNS_10is_contextERNS_7contextEQaa14read_supportedIT0_XdtT_6formatEEnt18is_input_streamingIT1_EEENS_9error_ctxERSE_OSF_OT2_:
  136|  11.3k|   {
  137|  11.3k|      static_assert(sizeof(decltype(*buffer.data())) == 1);
  138|  11.3k|      using Buffer = std::remove_reference_t<decltype(buffer)>;
  139|       |
  140|  11.3k|      if constexpr (Opts.format != NDJSON) {
  141|  11.3k|         if (buffer.empty()) [[unlikely]] {
  ------------------
  |  Branch (141:14): [True: 0, False: 11.3k]
  ------------------
  142|      0|            ctx.error = error_code::no_read_input;
  143|      0|            return {0, ctx.error, ctx.custom_error_message};
  144|      0|         }
  145|  11.3k|      }
  146|       |
  147|  11.3k|      constexpr bool use_padded = resizable<Buffer> && non_const_buffer<Buffer> && !check_disable_padding(Opts);
  ------------------
  |  Branch (147:35): [True: 0, Folded]
  |  Branch (147:56): [True: 0, Folded]
  |  Branch (147:84): [True: 0, Folded]
  ------------------
  148|       |
  149|  11.3k|      [[maybe_unused]] size_t original_size{};
  150|  11.3k|      if constexpr (use_padded) {
  151|       |         // Pad the buffer for SWAR
  152|  11.3k|         original_size = buffer.size();
  153|  11.3k|         buffer.resize(original_size + padding_bytes);
  154|  11.3k|      }
  155|       |
  156|  11.3k|      auto [it, end] = read_iterators<Opts, use_padded>(buffer);
  157|  11.3k|      auto start = it;
  158|  11.3k|      if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (158:11): [True: 0, False: 11.3k]
  ------------------
  159|      0|         goto finish;
  160|      0|      }
  161|       |
  162|       |      // Bound the speculative re-parsing a variant resolution may do, in bytes, relative to this
  163|       |      // input. Seeded per read so a reused context starts fresh. See charge_speculation.
  164|  11.3k|      if constexpr (requires { ctx.speculation_budget; }) {
  165|  11.3k|         const size_t proportional = max_speculative_parse_factor * size_t(end - it);
  166|  11.3k|         ctx.speculation_budget =
  167|  11.3k|            (proportional > min_speculative_parse_bytes ? proportional : min_speculative_parse_bytes) + 2;
  ------------------
  |  Branch (167:14): [True: 310, False: 11.0k]
  ------------------
  168|  11.3k|      }
  169|       |
  170|       |      // A YAML context marks its outermost parse with stream_begin and seeds its expansion budgets
  171|       |      // there, so clearing it here is what makes those budgets per-read like the one above. A
  172|       |      // reused context would otherwise carry a spent budget into the next document and reject a
  173|       |      // valid one, and would leave stream_begin pointing into the buffer of the previous read.
  174|       |      // Nested YAML parses do not route through glz::read, so they still cannot reseed themselves.
  175|       |      if constexpr (requires { ctx.stream_begin; }) {
  176|       |         ctx.stream_begin = nullptr;
  177|       |      }
  178|       |
  179|  11.3k|      if constexpr (use_padded) {
  180|  11.3k|         parse<Opts.format>::template op<is_padded_on<Opts>()>(value, ctx, it, end);
  181|       |      }
  182|       |      else {
  183|       |         parse<Opts.format>::template op<is_padded_off<Opts>()>(value, ctx, it, end);
  184|       |      }
  185|       |
  186|  11.3k|      if (bool(ctx.error)) [[unlikely]] {
  ------------------
  |  Branch (186:11): [True: 8.53k, False: 2.78k]
  ------------------
  187|  8.53k|         goto finish;
  188|  8.53k|      }
  189|       |
  190|       |      // The JSON RFC 8259 defines: JSON-text = ws value ws
  191|       |      // So, trailing whitespace is permitted and sometimes we want to
  192|       |      // validate this, even though this memory will not affect Glaze.
  193|       |      if constexpr (check_validate_trailing_whitespace(Opts)) {
  194|       |         if (it < end) {
  195|       |            skip_ws<Opts>(ctx, it, end);
  196|       |            if (bool(ctx.error)) [[unlikely]] {
  197|       |               goto finish;
  198|       |            }
  199|       |            if (it != end) [[unlikely]] {
  200|       |               ctx.error = error_code::syntax_error;
  201|       |            }
  202|       |         }
  203|       |      }
  204|       |
  205|  11.3k|   finish:
  206|  11.3k|      finalize_top_level_read<Opts>(ctx, start, it, end);
  207|       |
  208|  11.3k|      if constexpr (use_padded) {
  209|       |         // Restore the original buffer state
  210|  11.3k|         buffer.resize(original_size);
  211|  11.3k|      }
  212|       |
  213|  11.3k|      return {size_t(it - start), ctx.error, ctx.custom_error_message};
  214|  2.78k|   }
_ZN3glz14read_iteratorsITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEELb1ETkNS_10contiguousERNSt3__16vectorIcNS2_9allocatorIcEEEEEEDaOT1_:
   40|  11.3k|   {
   41|  11.3k|      static_assert(sizeof(decltype(*buffer.data())) == 1);
   42|       |
   43|  11.3k|      auto it = reinterpret_cast<const char*>(buffer.data());
   44|  11.3k|      auto end = reinterpret_cast<const char*>(buffer.data()); // to be incremented
   45|       |
   46|  11.3k|      if constexpr (Padded) {
   47|  11.3k|         end += buffer.size() - padding_bytes;
   48|       |      }
   49|       |      else {
   50|       |         end += buffer.size();
   51|       |      }
   52|       |
   53|  11.3k|      return std::pair{it, end};
   54|  11.3k|   }

_ZN3glz9sweethash7sweet32ITkNS0_16contiguous_rangeENSt3__117basic_string_viewIcNS2_11char_traitsIcEEEEEEjRKT_j:
  270|  8.70M|   {
  271|  8.70M|      return sweet32(static_cast<const void*>(s.data()), s.size(), seed);
  272|  8.70M|   }
_ZN3glz9sweethash7sweet32EPKvmj:
  154|  8.70M|   {
  155|  8.70M|      const uint8_t* p = static_cast<const uint8_t*>(data);
  156|       |
  157|       |      // For inputs <= 8 bytes, use simple hash (tail handler requires len >= 9)
  158|  8.70M|      if (len <= 8) {
  ------------------
  |  Branch (158:11): [True: 5.88M, False: 2.82M]
  ------------------
  159|  5.88M|         uint64_t v = 0;
  160|  5.88M|         switch (len) {
  161|   447k|         case 8:
  ------------------
  |  Branch (161:10): [True: 447k, False: 5.43M]
  ------------------
  162|   447k|            std::memcpy(&v, p, 8);
  163|   447k|            break;
  164|   525k|         case 7:
  ------------------
  |  Branch (164:10): [True: 525k, False: 5.35M]
  ------------------
  165|   525k|            std::memcpy(&v, p, 7);
  166|   525k|            break;
  167|   321k|         case 6:
  ------------------
  |  Branch (167:10): [True: 321k, False: 5.56M]
  ------------------
  168|   321k|            std::memcpy(&v, p, 6);
  169|   321k|            break;
  170|   138k|         case 5:
  ------------------
  |  Branch (170:10): [True: 138k, False: 5.74M]
  ------------------
  171|   138k|            std::memcpy(&v, p, 5);
  172|   138k|            break;
  173|   817k|         case 4:
  ------------------
  |  Branch (173:10): [True: 817k, False: 5.06M]
  ------------------
  174|   817k|            std::memcpy(&v, p, 4);
  175|   817k|            break;
  176|   293k|         case 3:
  ------------------
  |  Branch (176:10): [True: 293k, False: 5.59M]
  ------------------
  177|   293k|            std::memcpy(&v, p, 3);
  178|   293k|            break;
  179|  1.74M|         case 2:
  ------------------
  |  Branch (179:10): [True: 1.74M, False: 4.14M]
  ------------------
  180|  1.74M|            std::memcpy(&v, p, 2);
  181|  1.74M|            break;
  182|  1.49M|         case 1:
  ------------------
  |  Branch (182:10): [True: 1.49M, False: 4.39M]
  ------------------
  183|  1.49M|            v = p[0];
  184|  1.49M|            break;
  185|   104k|         default:
  ------------------
  |  Branch (185:10): [True: 104k, False: 5.78M]
  ------------------
  186|   104k|            break;
  187|  5.88M|         }
  188|  5.88M|         v = v ^ seed ^ (len + 1);
  189|  5.88M|         return static_cast<uint32_t>(v) ^ static_cast<uint32_t>(v >> 32);
  190|  5.88M|      }
  191|       |
  192|       |      // Full hash for inputs > 8 bytes
  193|  2.82M|      uint64_t seed64 = (static_cast<uint64_t>(seed) << 32) | static_cast<uint64_t>(seed);
  194|  2.82M|      uint64_t h = (seed64 ^ prime4) + (len * prime1);
  195|  2.82M|      const uint8_t* const end = p + len;
  196|       |
  197|  2.82M|      if (len >= 32) {
  ------------------
  |  Branch (197:11): [True: 783k, False: 2.03M]
  ------------------
  198|   783k|         uint64_t h1 = h;
  199|   783k|         uint64_t h2 = (seed64 * prime2) ^ prime3;
  200|   783k|         uint64_t h3 = (seed64 * prime3) ^ prime4;
  201|   783k|         uint64_t h4 = (seed64 * prime4) ^ prime5;
  202|       |
  203|  2.76M|         do {
  204|  2.76M|            uint64_t k1, k2, k3, k4;
  205|  2.76M|            std::memcpy(&k1, p, 8);
  206|  2.76M|            std::memcpy(&k2, p + 8, 8);
  207|  2.76M|            std::memcpy(&k3, p + 16, 8);
  208|  2.76M|            std::memcpy(&k4, p + 24, 8);
  209|       |
  210|  2.76M|            k1 = k1 * prime2;
  211|  2.76M|            k1 = k1 ^ (k1 >> 47);
  212|  2.76M|            h1 = h1 ^ k1;
  213|  2.76M|            h1 = h1 * prime1;
  214|       |
  215|  2.76M|            k2 = k2 * prime3;
  216|  2.76M|            k2 = k2 ^ (k2 >> 47);
  217|  2.76M|            h2 = h2 ^ k2;
  218|  2.76M|            h2 = h2 * prime2;
  219|       |
  220|  2.76M|            k3 = k3 * prime4;
  221|  2.76M|            k3 = k3 ^ (k3 >> 47);
  222|  2.76M|            h3 = h3 ^ k3;
  223|  2.76M|            h3 = h3 * prime3;
  224|       |
  225|  2.76M|            k4 = k4 * prime5;
  226|  2.76M|            k4 = k4 ^ (k4 >> 47);
  227|  2.76M|            h4 = h4 ^ k4;
  228|  2.76M|            h4 = h4 * prime4;
  229|       |
  230|  2.76M|            p = p + 32;
  231|  2.76M|            len = len - 32;
  232|  2.76M|         } while (len >= 32);
  ------------------
  |  Branch (232:19): [True: 1.98M, False: 783k]
  ------------------
  233|       |
  234|   783k|         h = h1 + h2 + h3 + h4;
  235|   783k|      }
  236|       |
  237|  7.12M|      while (len >= 8) {
  ------------------
  |  Branch (237:14): [True: 4.30M, False: 2.82M]
  ------------------
  238|  4.30M|         uint64_t k;
  239|  4.30M|         std::memcpy(&k, p, 8);
  240|  4.30M|         k = k * prime2;
  241|  4.30M|         k = k ^ (k >> 47);
  242|  4.30M|         h = h ^ k;
  243|  4.30M|         h = h * prime1;
  244|  4.30M|         p = p + 8;
  245|  4.30M|         len = len - 8;
  246|  4.30M|      }
  247|       |
  248|  2.82M|      if (len > 0) {
  ------------------
  |  Branch (248:11): [True: 2.54M, False: 275k]
  ------------------
  249|  2.54M|         uint64_t k;
  250|  2.54M|         std::memcpy(&k, end - 8, 8);
  251|  2.54M|         k = k * prime2;
  252|  2.54M|         k = k ^ (k >> 47);
  253|  2.54M|         k = k * prime3;
  254|  2.54M|         h = h ^ k;
  255|  2.54M|      }
  256|       |
  257|  2.82M|      h = mix64(h);
  258|  2.82M|      return static_cast<uint32_t>(h) ^ static_cast<uint32_t>(h >> 32);
  259|  8.70M|   }
_ZN3glz9sweethash5mix64Em:
   33|  2.82M|   {
   34|  2.82M|      v = v ^ (v >> 33);
   35|  2.82M|      v = v * prime2;
   36|  2.82M|      v = v ^ (v >> 29);
   37|  2.82M|      v = v * prime3;
   38|  2.82M|      return v;
   39|  2.82M|   }

_ZN3glz12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEC2Ev:
  338|  7.25M|      generic_json() = default;
_ZN3glz12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEED2Ev:
  114|  18.4M|      ~generic_json() = default;
_ZN3glz12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEC2EOS3_:
  341|  11.1M|      generic_json(generic_json&& other) noexcept : data(std::move(other.data)) {}
_ZNK3glz12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEE4sizeEv:
  534|  8.36k|      {
  535|  8.36k|         if (auto* v = get_if<object_t>()) {
  ------------------
  |  Branch (535:20): [True: 9, False: 8.35k]
  ------------------
  536|      9|            return v->size();
  537|      9|         }
  538|  8.35k|         else if (auto* v = get_if<array_t>()) {
  ------------------
  |  Branch (538:25): [True: 51, False: 8.30k]
  ------------------
  539|     51|            return v->size();
  540|     51|         }
  541|  8.30k|         else if (auto* v = get_if<std::string>()) {
  ------------------
  |  Branch (541:25): [True: 1.43k, False: 6.87k]
  ------------------
  542|  1.43k|            return v->size();
  543|  1.43k|         }
  544|  6.87k|         else {
  545|  6.87k|            return 0;
  546|  6.87k|         }
  547|  8.36k|      }
_ZNK3glz12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEE6get_ifINS2_IS3_EEEEPKT_v:
  159|  8.36k|      {
  160|  8.36k|         return std::get_if<T>(&data);
  161|  8.36k|      }
_ZNK3glz12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEE6get_ifINSt3__16vectorIS3_NS5_9allocatorIS3_EEEEEEPKT_v:
  159|  8.35k|      {
  160|  8.35k|         return std::get_if<T>(&data);
  161|  8.35k|      }
_ZNK3glz12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEE6get_ifINSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEPKT_v:
  159|  8.30k|      {
  160|  8.30k|         return std::get_if<T>(&data);
  161|  8.30k|      }

_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERNS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
   49|  11.3k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  11.3k|         else {
   60|  11.3k|            using V = std::remove_cvref_t<T>;
   61|  11.3k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  11.3k|                                             end);
   63|  11.3k|         }
   64|  11.3k|      }
_ZN3glz4fromILj10ENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERS4_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
  150|  11.3k|      {
  151|  11.3k|         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
  152|  11.3k|         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
  153|  11.3k|                                          std::forward<Ctx>(ctx), std::forward<It0>(it), end);
  154|  11.3k|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4065|  11.3k|      {
 4066|       |         if constexpr (tagging == variant_tagging_kind::adjacent) {
 4067|       |            read_adjacent<Options>(value, ctx, it, end);
 4068|       |         }
 4069|  11.3k|         else {
 4070|  11.3k|            read_deduced<Options>(value, ctx, it, end);
 4071|  11.3k|         }
 4072|  11.3k|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE12read_deducedITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4076|  11.3k|      {
 4077|  11.3k|         constexpr auto Opts = ws_handled_off<Options>();
 4078|  11.3k|         if constexpr (variant_is_auto_deducible<T>()) {
 4079|  11.3k|            if constexpr (not check_ws_handled(Options)) {
 4080|  11.3k|               if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (4080:20): [True: 13, False: 11.3k]
  ------------------
 4081|     13|                  return;
 4082|     13|               }
 4083|  11.3k|            }
 4084|       |
 4085|  11.3k|            switch (*it) {
 4086|      2|            case '\0':
  ------------------
  |  Branch (4086:13): [True: 2, False: 11.3k]
  ------------------
 4087|      2|               ctx.error = error_code::unexpected_end;
 4088|      2|               return;
 4089|  5.14k|            case '{': {
  ------------------
  |  Branch (4089:13): [True: 5.14k, False: 6.17k]
  ------------------
 4090|       |               // This branch consumes the brace itself and hands the object to a reader with
 4091|       |               // `opening_handled`, which therefore does not count the level -- but does release it at
 4092|       |               // the closing brace. So the level is taken here, in both buffer modes, and paid back by
 4093|       |               // the reader below.
 4094|  5.14k|               if (enter_depth(ctx)) [[unlikely]] {
  ------------------
  |  Branch (4094:20): [True: 0, False: 5.14k]
  ------------------
 4095|      0|                  return;
 4096|      0|               }
 4097|       |
 4098|  5.14k|               ++it;
 4099|  5.14k|               if constexpr (not Opts.null_terminated) {
 4100|  5.14k|                  if (it == end) [[unlikely]] {
  ------------------
  |  Branch (4100:23): [True: 2, False: 5.14k]
  ------------------
 4101|      2|                     ctx.error = error_code::unexpected_end;
 4102|      2|                     return;
 4103|      2|                  }
 4104|  5.14k|               }
 4105|  5.14k|               using type_counts = variant_type_count<T>;
 4106|  5.14k|               constexpr auto n_object_candidates = variant_object_candidate_count_v<Opts, T>;
 4107|       |               if constexpr (n_object_candidates < 1) {
 4108|       |                  ctx.error = error_code::no_matching_variant_type;
 4109|       |                  return;
 4110|       |               }
 4111|  5.14k|               else if constexpr (n_object_candidates == 1 && tag_v<T>.empty()) {
 4112|  5.14k|                  constexpr auto first_idx = variant_first_object_candidate_v<Opts, T>;
 4113|  5.14k|                  using V = std::variant_alternative_t<first_idx, T>;
 4114|  5.14k|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4114:23): [True: 5.14k, False: 2]
  ------------------
 4115|  5.14k|                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
 4116|  5.14k|                  return;
 4117|       |               }
 4118|       |               else {
 4119|       |                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
 4120|       |                  static constexpr auto& deduction_bits = variant_deduction_bits<T>;
 4121|       |                  static constexpr size_t deduction_key_count = variant_deduction_key_count<T>;
 4122|       |                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
 4123|       |
 4124|       |                  // Track if we've encountered a tag and what value it had
 4125|       |                  std::optional<size_t> tag_specified_index{};
 4126|       |
 4127|       |                  if (skip_ws<Opts>(ctx, it, end)) {
 4128|       |                     return;
 4129|       |                  }
 4130|       |                  // Once the reader knows which alternative this object holds it may have to read
 4131|       |                  // it again from here. Anchor the position rather than keep the pointer: the scan
 4132|       |                  // below skips values, and a streaming skip refills, which moves the window out
 4133|       |                  // from under a raw pointer (see rewind_anchor).
 4134|       |                  auto start = make_rewind_anchor(ctx, it);
 4135|       |                  bool first_key = true;
 4136|       |                  // Parse bifurcation for tagged variants:
 4137|       |                  //
 4138|       |                  // Without this optimization, tagged variant parsing always uses two passes:
 4139|       |                  //   1. Scan all keys to find the tag (e.g. "type"), skipping values
 4140|       |                  //   2. Reset `it = start` and re-parse the entire object into the resolved type
 4141|       |                  //
 4142|       |                  // When the tag is the first key, the second pass redundantly re-reads every
 4143|       |                  // field that follows it. This lambda avoids that: if the tag was the first key,
 4144|       |                  // it advances past the trailing comma so the object parser picks up at the
 4145|       |                  // second field. If the tag was found later, it falls back to the full re-parse.
 4146|       |                  //
 4147|       |                  // One exception: if the tag name is also a field on the resolved struct
 4148|       |                  // (contains_tag), we must re-parse regardless so the value is stored in
 4149|       |                  // the struct field. This override is applied inside each std::visit lambda.
 4150|       |                  //
 4151|       |                  // Either way the rewind can fail under a streaming read: the window only holds so
 4152|       |                  // much, and an object wider than it has no start left to return to.
 4153|       |                  auto position_after_tag = [&] {
 4154|       |                     if (first_key) {
 4155|       |                        if (*it == ',') ++it; // skip comma; handles tag-only objects where *it == '}'
 4156|       |                        return true;
 4157|       |                     }
 4158|       |                     return start.rewind(ctx, it, end); // tag came later, re-parse from the beginning
 4159|       |                  };
 4160|       |                  // `first_key` also answers "were we reset to the object start", which is what
 4161|       |                  // position_after_tag does for every key but the first.
 4162|       |                  for (; *it != '}'; first_key = false) {
 4163|       |                     if (!first_key) {
 4164|       |                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
 4165|       |                           return;
 4166|       |                        }
 4167|       |                     }
 4168|       |
 4169|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4170|       |                        return;
 4171|       |                     }
 4172|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4173|       |                        return;
 4174|       |                     }
 4175|       |
 4176|       |                     auto* key_start = it;
 4177|       |                     skip_string_view(ctx, it, end);
 4178|       |                     if (bool(ctx.error)) [[unlikely]]
 4179|       |                        return;
 4180|       |                     if (validate_utf8_span<Opts>(ctx, key_start, it)) [[unlikely]]
 4181|       |                        return;
 4182|       |                     const sv key = {key_start, size_t(it - key_start)};
 4183|       |
 4184|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4185|       |                        return;
 4186|       |                     }
 4187|       |
 4188|       |                     if constexpr (deduction_key_count > 0) {
 4189|       |                        // We first check if a tag is defined and see if the key matches the tag
 4190|       |                        if constexpr (not tag_v<T>.empty()) {
 4191|       |                           if (key == tag_v<T>) {
 4192|       |                              if (parse_ws_colon<Opts>(ctx, it, end)) {
 4193|       |                                 return;
 4194|       |                              }
 4195|       |
 4196|       |                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
 4197|       |
 4198|       |                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
 4199|       |                              if constexpr (std::integral<id_type>) {
 4200|       |                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
 4201|       |                              }
 4202|       |                              else {
 4203|       |                                 // The id is turned into an index below and never leaves this
 4204|       |                                 // reader, so the view of the window it borrows cannot outlive it.
 4205|       |                                 parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4206|       |                              }
 4207|       |                              if (bool(ctx.error)) [[unlikely]]
 4208|       |                                 return;
 4209|       |                              if (skip_ws<Opts>(ctx, it, end)) {
 4210|       |                                 return;
 4211|       |                              }
 4212|       |                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
 4213|       |                                 ctx.error = error_code::syntax_error;
 4214|       |                                 return;
 4215|       |                              }
 4216|       |
 4217|       |                              size_t type_index;
 4218|       |                              if constexpr (std::integral<id_type>) {
 4219|       |                                 type_index = variant_id_to_index<T>::op(type_id);
 4220|       |                              }
 4221|       |                              else {
 4222|       |                                 type_index = variant_id_to_index<T>::op(
 4223|       |                                    type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4224|       |                              }
 4225|       |                              if (type_index < ids_v<T>.size()) [[likely]] {
 4226|       |                                 // Check if the deduced types include the tag-specified type
 4227|       |                                 // If not, the tag doesn't match the fields
 4228|       |                                 // We're already inside if constexpr (deduction_registry.size()), so we know deduction
 4229|       |                                 // is happening. At this point, possible_types has been narrowed by field deduction.
 4230|       |                                 // Check if the tag-specified type is still possible
 4231|       |                                 const bool type_is_possible = possible_types[type_index];
 4232|       |                                 if (!type_is_possible) {
 4233|       |                                    // Tag specifies a type that doesn't match the fields seen so far
 4234|       |                                    ctx.error = error_code::no_matching_variant_type;
 4235|       |                                    return;
 4236|       |                                 }
 4237|       |
 4238|       |                                 if (!position_after_tag()) return;
 4239|       |                                 tag_specified_index = type_index; // Store the tag-specified type
 4240|       |                                 if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4241|       |                                 std::visit(
 4242|       |                                    [&](auto&& v) {
 4243|       |                                       using V = std::decay_t<decltype(v)>;
 4244|       |                                       constexpr bool is_object =
 4245|       |                                          (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4246|       |                                       if constexpr (variant_unit_alternative<V>) {
 4247|       |                                          // A unit alternative carries no data; its object holds only the
 4248|       |                                          // discriminator. Consume that body through an empty reflected object so
 4249|       |                                          // unknown-key policy and terminator handling match every other alternative.
 4250|       |                                          detail::variant_unit_body unit_body{};
 4251|       |                                          from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4252|       |                                                                                             tag_literal>(unit_body,
 4253|       |                                                                                                          ctx, it, end);
 4254|       |                                       }
 4255|       |                                       else if constexpr (is_object) {
 4256|       |                                          if constexpr (contains_tag<V, tag_literal>()) {
 4257|       |                                             // tag is a struct field, must re-parse
 4258|       |                                             if (!start.rewind(ctx, it, end)) return;
 4259|       |                                          }
 4260|       |                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
 4261|       |                                                                                                           end);
 4262|       |                                       }
 4263|       |                                       else if constexpr (is_memory_object<V>) {
 4264|       |                                          if (!v) {
 4265|       |                                             if constexpr (is_specialization_v<V, std::optional>) {
 4266|       |                                                if constexpr (requires { v.emplace(); }) {
 4267|       |                                                   v.emplace();
 4268|       |                                                }
 4269|       |                                                else {
 4270|       |                                                   v = typename V::value_type{};
 4271|       |                                                }
 4272|       |                                             }
 4273|       |                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4274|       |                                                v = std::make_unique<typename V::element_type>();
 4275|       |                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4276|       |                                                v = std::make_shared<typename V::element_type>();
 4277|       |                                             else if constexpr (constructible<V>) {
 4278|       |                                                v = meta_construct_v<V>();
 4279|       |                                             }
 4280|       |                                             else if constexpr (std::is_pointer_v<V> &&
 4281|       |                                                                can_allocate_raw_pointer<Opts,
 4282|       |                                                                                         std::decay_t<decltype(ctx)>>) {
 4283|       |                                                if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4284|       |                                                   return;
 4285|       |                                                }
 4286|       |                                             }
 4287|       |                                             else {
 4288|       |                                                ctx.error = error_code::invalid_nullable_read;
 4289|       |                                                return;
 4290|       |                                                // Cannot read into unset nullable that is not std::optional,
 4291|       |                                                // std::unique_ptr, or std::shared_ptr
 4292|       |                                             }
 4293|       |                                          }
 4294|       |                                          if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4295|       |                                             // tag is a struct field, must re-parse
 4296|       |                                             if (!start.rewind(ctx, it, end)) return;
 4297|       |                                          }
 4298|       |                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4299|       |                                             *v, ctx, it, end);
 4300|       |                                       }
 4301|       |                                       else if constexpr (custom_read<V>) {
 4302|       |                                          // Custom handlers parse the remaining body themselves and do not
 4303|       |                                          // accept the tag template parameter; the tag was already consumed.
 4304|       |                                          // This only works when the tag was the first key. If it came later,
 4305|       |                                          // we were reset to the object start and the custom handler would
 4306|       |                                          // absorb the tag, so error rather than corrupt the value.
 4307|       |                                          if (!first_key) {
 4308|       |                                             ctx.error = error_code::feature_not_supported;
 4309|       |                                             ctx.custom_error_message =
 4310|       |                                                "the tag must be the first key for a custom variant alternative";
 4311|       |                                             return;
 4312|       |                                          }
 4313|       |                                          from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4314|       |                                       }
 4315|       |                                    },
 4316|       |                                    value);
 4317|       |
 4318|       |                                 return; // we've decoded our target type
 4319|       |                              }
 4320|       |                              else [[unlikely]] {
 4321|       |                                 // Check if we have a default type (ids array shorter than variant)
 4322|       |                                 constexpr auto ids_size = ids_v<T>.size();
 4323|       |                                 constexpr auto variant_size = std::variant_size_v<T>;
 4324|       |                                 if constexpr (ids_size < variant_size) {
 4325|       |                                    // Use the first unlabeled type as the default
 4326|       |                                    const auto default_type_index = ids_size;
 4327|       |
 4328|       |                                    if (!position_after_tag()) return;
 4329|       |                                    tag_specified_index = default_type_index; // Store the default type index
 4330|       |                                    if (value.index() != default_type_index)
 4331|       |                                       emplace_runtime_variant(value, default_type_index);
 4332|       |                                    std::visit(
 4333|       |                                       [&](auto&& v) {
 4334|       |                                          using V = std::decay_t<decltype(v)>;
 4335|       |                                          constexpr bool is_object =
 4336|       |                                             (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4337|       |                                          if constexpr (variant_unit_alternative<V>) {
 4338|       |                                             // A unit alternative carries no data; its object holds only the
 4339|       |                                             // discriminator. Consume that body through an empty reflected object so
 4340|       |                                             // unknown-key policy and terminator handling match every other
 4341|       |                                             // alternative.
 4342|       |                                             detail::variant_unit_body unit_body{};
 4343|       |                                             from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4344|       |                                                                                                tag_literal>(
 4345|       |                                                unit_body, ctx, it, end);
 4346|       |                                          }
 4347|       |                                          else if constexpr (is_object) {
 4348|       |                                             if constexpr (contains_tag<V, tag_literal>()) {
 4349|       |                                                // tag is a struct field, must re-parse
 4350|       |                                                if (!start.rewind(ctx, it, end)) return;
 4351|       |                                             }
 4352|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4353|       |                                          }
 4354|       |                                          else if constexpr (is_memory_object<V>) {
 4355|       |                                             if (!v) {
 4356|       |                                                if constexpr (is_specialization_v<V, std::optional>) {
 4357|       |                                                   if constexpr (requires { v.emplace(); }) {
 4358|       |                                                      v.emplace();
 4359|       |                                                   }
 4360|       |                                                   else {
 4361|       |                                                      v = typename V::value_type{};
 4362|       |                                                   }
 4363|       |                                                }
 4364|       |                                                else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4365|       |                                                   v = std::make_unique<typename V::element_type>();
 4366|       |                                                else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4367|       |                                                   v = std::make_shared<typename V::element_type>();
 4368|       |                                                else if constexpr (constructible<V>) {
 4369|       |                                                   v = meta_construct_v<V>();
 4370|       |                                                }
 4371|       |                                                else if constexpr (std::is_pointer_v<V> &&
 4372|       |                                                                   can_allocate_raw_pointer<
 4373|       |                                                                      Opts, std::decay_t<decltype(ctx)>>) {
 4374|       |                                                   if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4375|       |                                                      return;
 4376|       |                                                   }
 4377|       |                                                }
 4378|       |                                                else {
 4379|       |                                                   ctx.error = error_code::invalid_nullable_read;
 4380|       |                                                   return;
 4381|       |                                                }
 4382|       |                                             }
 4383|       |                                             if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4384|       |                                                // tag is a struct field, must re-parse
 4385|       |                                                if (!start.rewind(ctx, it, end)) return;
 4386|       |                                             }
 4387|       |                                             from<JSON, memory_type<V>>::template op<opening_handled<Opts>()>(*v, ctx,
 4388|       |                                                                                                              it, end);
 4389|       |                                          }
 4390|       |                                          else if constexpr (custom_read<V>) {
 4391|       |                                             // Custom handlers parse the remaining body themselves; this only
 4392|       |                                             // works when the tag was the first key (see above). If it came
 4393|       |                                             // later we were reset to the object start, so error rather than
 4394|       |                                             // let the custom handler absorb the tag.
 4395|       |                                             if (!first_key) {
 4396|       |                                                ctx.error = error_code::feature_not_supported;
 4397|       |                                                ctx.custom_error_message =
 4398|       |                                                   "the tag must be the first key for a custom variant alternative";
 4399|       |                                                return;
 4400|       |                                             }
 4401|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4402|       |                                          }
 4403|       |                                       },
 4404|       |                                       value);
 4405|       |
 4406|       |                                    return;
 4407|       |                                 }
 4408|       |                                 else {
 4409|       |                                    ctx.error = error_code::no_matching_variant_type;
 4410|       |                                    ctx.custom_error_message = variant_ids_string_v<T>;
 4411|       |                                    return;
 4412|       |                                 }
 4413|       |                              }
 4414|       |                           }
 4415|       |                        }
 4416|       |
 4417|       |                        // Inline decode_hash lookup for variant deduction
 4418|       |                        using deduction_keys_t = keys_wrapper<variant_deduction_keys<T>>;
 4419|       |                        constexpr auto& DeductionHashInfo = hash_info<deduction_keys_t>;
 4420|       |                        const auto deduction_index =
 4421|       |                           decode_hash_with_size<JSON, deduction_keys_t, DeductionHashInfo, DeductionHashInfo.type>::op(
 4422|       |                              key.data(), key.data() + key.size(), key.size());
 4423|       |                        if (deduction_index < deduction_key_count && variant_deduction_keys<T>[deduction_index] == key)
 4424|       |                           [[likely]] {
 4425|       |                           possible_types &= deduction_bits[deduction_index];
 4426|       |                        }
 4427|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4428|       |                           ctx.error = error_code::unknown_key;
 4429|       |                           return;
 4430|       |                        }
 4431|       |                     }
 4432|       |                     else if constexpr (not tag_v<T>.empty()) {
 4433|       |                        // empty object case for variant, if there are no normal elements
 4434|       |                        if (key == tag_v<T>) {
 4435|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4436|       |                              return;
 4437|       |                           }
 4438|       |
 4439|       |                           // The id is turned into an index below and never leaves this reader,
 4440|       |                           // so the view of the window it borrows cannot outlive that window.
 4441|       |                           std::string_view type_id{};
 4442|       |                           parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4443|       |                           if (bool(ctx.error)) [[unlikely]]
 4444|       |                              return;
 4445|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4446|       |                              return;
 4447|       |                           }
 4448|       |
 4449|       |                           const auto type_index = variant_id_to_index<T>::op(
 4450|       |                              type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4451|       |                           if (type_index < ids_v<T>.size()) [[likely]] {
 4452|       |                              if (!position_after_tag()) return;
 4453|       |                              tag_specified_index = type_index; // Store the tag-specified type
 4454|       |                              if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4455|       |                           }
 4456|       |                           else {
 4457|       |                              // Check if we have a default type (ids array shorter than variant)
 4458|       |                              constexpr auto ids_size = ids_v<T>.size();
 4459|       |                              constexpr auto variant_size = std::variant_size_v<T>;
 4460|       |                              if constexpr (ids_size < variant_size) {
 4461|       |                                 // Use the first unlabeled type as the default
 4462|       |                                 if (!position_after_tag()) return;
 4463|       |                                 const auto default_index = ids_size;
 4464|       |                                 tag_specified_index = default_index; // Store the default type index
 4465|       |                                 if (value.index() != default_index) emplace_runtime_variant(value, default_index);
 4466|       |                              }
 4467|       |                              else {
 4468|       |                                 ctx.error = error_code::no_matching_variant_type;
 4469|       |                                 ctx.custom_error_message = variant_ids_string_v<T>;
 4470|       |                                 return;
 4471|       |                              }
 4472|       |                           }
 4473|       |                           // Parse the type (handles tag skipping and unknown keys)
 4474|       |                           std::visit(
 4475|       |                              [&](auto&& v) {
 4476|       |                                 using V = std::decay_t<decltype(v)>;
 4477|       |                                 if constexpr (custom_read<V>) {
 4478|       |                                    // Custom handlers parse the remaining object body themselves and do not
 4479|       |                                    // accept the tag template parameter that reflected objects use to skip an
 4480|       |                                    // interior tag key. That only works when the tag is the first key (it was
 4481|       |                                    // just consumed). If the tag came after other keys, position_after_tag()
 4482|       |                                    // reset us to the object start and the custom handler would absorb the tag
 4483|       |                                    // into its value, so error here rather than corrupt the result.
 4484|       |                                    if (!first_key) {
 4485|       |                                       ctx.error = error_code::feature_not_supported;
 4486|       |                                       ctx.custom_error_message =
 4487|       |                                          "the tag must be the first key for a custom variant alternative";
 4488|       |                                       return;
 4489|       |                                    }
 4490|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4491|       |                                 }
 4492|       |                                 else {
 4493|       |                                    if constexpr (contains_tag<V, tag_literal>()) {
 4494|       |                                       // tag is a struct field, must re-parse
 4495|       |                                       if (!start.rewind(ctx, it, end)) return;
 4496|       |                                    }
 4497|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4498|       |                                 }
 4499|       |                              },
 4500|       |                              value);
 4501|       |                           return;
 4502|       |                        }
 4503|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4504|       |                           ctx.error = error_code::unknown_key;
 4505|       |                           return;
 4506|       |                        }
 4507|       |                        else {
 4508|       |                           // Skip unknown key's value (non-tag key in empty variant)
 4509|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4510|       |                              return;
 4511|       |                           }
 4512|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 4513|       |                           if (bool(ctx.error)) [[unlikely]]
 4514|       |                              return;
 4515|       |                           resync_window_end(ctx, end); // a streaming skip refills
 4516|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4517|       |                              return;
 4518|       |                           }
 4519|       |                           continue; // Continue loop to find the tag
 4520|       |                        }
 4521|       |                     }
 4522|       |                     else if constexpr (Opts.error_on_unknown_keys) {
 4523|       |                        ctx.error = error_code::unknown_key;
 4524|       |                        return;
 4525|       |                     }
 4526|       |
 4527|       |                     auto matching_types = possible_types.popcount();
 4528|       |                     if (matching_types == 0) {
 4529|       |                        ctx.error = error_code::no_matching_variant_type;
 4530|       |                        return;
 4531|       |                     }
 4532|       |                     // Only short-circuit for variants without tags
 4533|       |                     else if constexpr (tag_v<T>.empty()) {
 4534|       |                        if (matching_types == 1) {
 4535|       |                           if (!start.rewind(ctx, it, end)) return;
 4536|       |                           const auto type_index = possible_types.countr_zero();
 4537|       |
 4538|       |                           if (value.index() != static_cast<size_t>(type_index))
 4539|       |                              emplace_runtime_variant(value, type_index);
 4540|       |                           std::visit(
 4541|       |                              [&](auto&& v) {
 4542|       |                                 using V = std::decay_t<decltype(v)>;
 4543|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4544|       |                                 if constexpr (variant_unit_alternative<V>) {
 4545|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4546|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4547|       |                                    // terminator handling match every other alternative.
 4548|       |                                    detail::variant_unit_body unit_body{};
 4549|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4550|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4551|       |                                                                                                    end);
 4552|       |                                 }
 4553|       |                                 else if constexpr (is_object) {
 4554|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4555|       |                                 }
 4556|       |                                 else if constexpr (is_memory_object<V>) {
 4557|       |                                    if (!v) {
 4558|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4559|       |                                          if constexpr (requires { v.emplace(); }) {
 4560|       |                                             v.emplace();
 4561|       |                                          }
 4562|       |                                          else {
 4563|       |                                             v = typename V::value_type{};
 4564|       |                                          }
 4565|       |                                       }
 4566|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4567|       |                                          v = std::make_unique<typename V::element_type>();
 4568|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4569|       |                                          v = std::make_shared<typename V::element_type>();
 4570|       |                                       else if constexpr (constructible<V>) {
 4571|       |                                          v = meta_construct_v<V>();
 4572|       |                                       }
 4573|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4574|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4575|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4576|       |                                             return;
 4577|       |                                          }
 4578|       |                                       }
 4579|       |                                       else {
 4580|       |                                          ctx.error = error_code::invalid_nullable_read;
 4581|       |                                          return;
 4582|       |                                          // Cannot read into unset nullable that is not std::optional,
 4583|       |                                          // std::unique_ptr, or std::shared_ptr
 4584|       |                                       }
 4585|       |                                    }
 4586|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4587|       |                                       *v, ctx, it, end);
 4588|       |                                 }
 4589|       |                                 else if constexpr (custom_read<V>) {
 4590|       |                                    // Custom handlers parse the remaining body themselves.
 4591|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4592|       |                                 }
 4593|       |                              },
 4594|       |                              value);
 4595|       |
 4596|       |                           return; // we've decoded our target type
 4597|       |                        }
 4598|       |                     }
 4599|       |                     // For tagged variants, continue processing to validate tags
 4600|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 4601|       |                        return;
 4602|       |                     }
 4603|       |
 4604|       |                     skip_value<JSON>::op<Opts>(ctx, it, end);
 4605|       |                     if (bool(ctx.error)) [[unlikely]]
 4606|       |                        return;
 4607|       |                     resync_window_end(ctx, end); // a streaming skip refills
 4608|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4609|       |                        return;
 4610|       |                     }
 4611|       |                  }
 4612|       |                  // Only apply ambiguous variant resolution if we have multiple object types
 4613|       |                  if constexpr ((type_counts::n_object + type_counts::n_nullable_object) > 1) {
 4614|       |                     // After parsing all keys, check if we have multiple matching types
 4615|       |                     // If so, choose the one with the fewest fields
 4616|       |                     auto final_matching = possible_types.popcount();
 4617|       |                     if (final_matching == 0) {
 4618|       |                        ctx.error = error_code::no_matching_variant_type;
 4619|       |                     }
 4620|       |                     else if (final_matching == 1) {
 4621|       |                        // Single type remains after field deduction
 4622|       |                        const auto type_index = possible_types.countr_zero();
 4623|       |
 4624|       |                        // Validate against tag if one was specified
 4625|       |                        if (tag_specified_index.has_value() &&
 4626|       |                            tag_specified_index.value() != static_cast<size_t>(type_index)) {
 4627|       |                           ctx.error = error_code::no_matching_variant_type;
 4628|       |                           return;
 4629|       |                        }
 4630|       |
 4631|       |                        if (!start.rewind(ctx, it, end)) return;
 4632|       |                        if (value.index() != static_cast<size_t>(type_index))
 4633|       |                           emplace_runtime_variant(value, type_index);
 4634|       |                        std::visit(
 4635|       |                           [&](auto&& v) {
 4636|       |                              using V = std::decay_t<decltype(v)>;
 4637|       |                              constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4638|       |                              if constexpr (variant_unit_alternative<V>) {
 4639|       |                                 // A unit alternative carries no data; its object holds only the discriminator.
 4640|       |                                 // Consume that body through an empty reflected object so unknown-key policy and
 4641|       |                                 // terminator handling match every other alternative.
 4642|       |                                 detail::variant_unit_body unit_body{};
 4643|       |                                 from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4644|       |                                                                                    tag_literal>(unit_body, ctx, it,
 4645|       |                                                                                                 end);
 4646|       |                              }
 4647|       |                              else if constexpr (is_object) {
 4648|       |                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4649|       |                              }
 4650|       |                              else if constexpr (is_memory_object<V>) {
 4651|       |                                 if (!v) {
 4652|       |                                    if constexpr (is_specialization_v<V, std::optional>) {
 4653|       |                                       if constexpr (requires { v.emplace(); }) {
 4654|       |                                          v.emplace();
 4655|       |                                       }
 4656|       |                                       else {
 4657|       |                                          v = typename V::value_type{};
 4658|       |                                       }
 4659|       |                                    }
 4660|       |                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4661|       |                                       v = std::make_unique<typename V::element_type>();
 4662|       |                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4663|       |                                       v = std::make_shared<typename V::element_type>();
 4664|       |                                    else if constexpr (constructible<V>) {
 4665|       |                                       v = meta_construct_v<V>();
 4666|       |                                    }
 4667|       |                                    else if constexpr (std::is_pointer_v<V> &&
 4668|       |                                                       can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4669|       |                                       if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4670|       |                                          return;
 4671|       |                                       }
 4672|       |                                    }
 4673|       |                                    else {
 4674|       |                                       ctx.error = error_code::invalid_nullable_read;
 4675|       |                                       return;
 4676|       |                                    }
 4677|       |                                 }
 4678|       |                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
 4679|       |                                                                                                               it, end);
 4680|       |                              }
 4681|       |                              else if constexpr (custom_read<V>) {
 4682|       |                                 // Custom handlers parse the remaining body themselves.
 4683|       |                                 from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4684|       |                              }
 4685|       |                           },
 4686|       |                           value);
 4687|       |                     }
 4688|       |                     else if (final_matching > 1) {
 4689|       |                        constexpr auto N = std::variant_size_v<T>;
 4690|       |
 4691|       |                        // Compile-time array of field counts for each variant type
 4692|       |                        constexpr auto field_counts = []<size_t... I>(std::index_sequence<I...>) {
 4693|       |                           return std::array<size_t, N> {
 4694|       |                              ([]<size_t J = I>() -> size_t {
 4695|       |                                 using V = std::decay_t<std::variant_alternative_t<J, T>>;
 4696|       |                                 if constexpr (glaze_object_t<V> || reflectable<V>) {
 4697|       |                                    return reflect<V>::size;
 4698|       |                                 }
 4699|       |                                 else if constexpr (is_memory_object<V>) {
 4700|       |                                    using X = memory_type<V>;
 4701|       |                                    if constexpr (glaze_object_t<X> || reflectable<X>) {
 4702|       |                                       return reflect<X>::size;
 4703|       |                                    }
 4704|       |                                    else {
 4705|       |                                       return (std::numeric_limits<size_t>::max)();
 4706|       |                                    }
 4707|       |                                 }
 4708|       |                                 else {
 4709|       |                                    return (std::numeric_limits<size_t>::max)();
 4710|       |                                 }
 4711|       |                              }.template operator()<I>())...
 4712|       |                           };
 4713|       |                        }(std::make_index_sequence<N>{});
 4714|       |
 4715|       |                        // Find the type with minimum field count among the possible types
 4716|       |                        size_t min_fields = (std::numeric_limits<size_t>::max)();
 4717|       |                        size_t chosen_index = N; // Invalid index initially
 4718|       |
 4719|       |                        for (size_t i = 0; i < N; ++i) {
 4720|       |                           if (possible_types[i] && field_counts[i] < min_fields) {
 4721|       |                              min_fields = field_counts[i];
 4722|       |                              chosen_index = i;
 4723|       |                           }
 4724|       |                        }
 4725|       |
 4726|       |                        if (chosen_index < N) {
 4727|       |                           // Validate against tag if one was specified
 4728|       |                           if (tag_specified_index.has_value() && tag_specified_index.value() != chosen_index) {
 4729|       |                              ctx.error = error_code::no_matching_variant_type;
 4730|       |                              return;
 4731|       |                           }
 4732|       |
 4733|       |                           if (!start.rewind(ctx, it, end)) return;
 4734|       |                           if (value.index() != chosen_index) emplace_runtime_variant(value, chosen_index);
 4735|       |                           std::visit(
 4736|       |                              [&](auto&& v) {
 4737|       |                                 using V = std::decay_t<decltype(v)>;
 4738|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4739|       |                                 if constexpr (variant_unit_alternative<V>) {
 4740|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4741|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4742|       |                                    // terminator handling match every other alternative.
 4743|       |                                    detail::variant_unit_body unit_body{};
 4744|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4745|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4746|       |                                                                                                    end);
 4747|       |                                 }
 4748|       |                                 else if constexpr (is_object) {
 4749|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4750|       |                                 }
 4751|       |                                 else if constexpr (is_memory_object<V>) {
 4752|       |                                    if (!v) {
 4753|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4754|       |                                          if constexpr (requires { v.emplace(); }) {
 4755|       |                                             v.emplace();
 4756|       |                                          }
 4757|       |                                          else {
 4758|       |                                             v = typename V::value_type{};
 4759|       |                                          }
 4760|       |                                       }
 4761|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4762|       |                                          v = std::make_unique<typename V::element_type>();
 4763|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4764|       |                                          v = std::make_shared<typename V::element_type>();
 4765|       |                                       else if constexpr (constructible<V>) {
 4766|       |                                          v = meta_construct_v<V>();
 4767|       |                                       }
 4768|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4769|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4770|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4771|       |                                             return;
 4772|       |                                          }
 4773|       |                                       }
 4774|       |                                       else {
 4775|       |                                          ctx.error = error_code::invalid_nullable_read;
 4776|       |                                          return;
 4777|       |                                       }
 4778|       |                                    }
 4779|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4780|       |                                       *v, ctx, it, end);
 4781|       |                                 }
 4782|       |                                 else if constexpr (custom_read<V>) {
 4783|       |                                    // Custom handlers parse the remaining body themselves.
 4784|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4785|       |                                 }
 4786|       |                              },
 4787|       |                              value);
 4788|       |                        }
 4789|       |                        else {
 4790|       |                           ctx.error = error_code::no_matching_variant_type;
 4791|       |                        }
 4792|       |                     }
 4793|       |                  }
 4794|       |                  else {
 4795|       |                     // For variants with 0 or 1 object types, use the original error handling
 4796|       |                     ctx.error = error_code::no_matching_variant_type;
 4797|       |                  }
 4798|       |               }
 4799|      0|               break;
 4800|  5.14k|            }
 4801|  2.19k|            case '[':
  ------------------
  |  Branch (4801:13): [True: 2.19k, False: 9.12k]
  ------------------
 4802|       |               // As with '{' above: the array reader each alternative goes through counts the level.
 4803|  2.19k|               process_variant_alternatives<T, is_variant_array>::template op<Opts>(value, ctx, it, end);
 4804|  2.19k|               break;
 4805|  1.15k|            case '"': {
  ------------------
  |  Branch (4805:13): [True: 1.15k, False: 10.1k]
  ------------------
 4806|  1.15k|               process_variant_alternatives<T, is_variant_str>::template op<Opts>(value, ctx, it, end);
 4807|  1.15k|               break;
 4808|  5.14k|            }
 4809|     78|            case 't':
  ------------------
  |  Branch (4809:13): [True: 78, False: 11.2k]
  ------------------
 4810|    184|            case 'f': {
  ------------------
  |  Branch (4810:13): [True: 106, False: 11.2k]
  ------------------
 4811|    184|               process_variant_alternatives<T, is_variant_bool>::template op<Opts>(value, ctx, it, end);
 4812|    184|               break;
 4813|     78|            }
 4814|     74|            case 'n':
  ------------------
  |  Branch (4814:13): [True: 74, False: 11.2k]
  ------------------
 4815|       |               if constexpr (variant_count_v<T, is_variant_null> == 0) {
 4816|       |                  ctx.error = error_code::no_matching_variant_type;
 4817|       |               }
 4818|     74|               else {
 4819|     74|                  constexpr auto first_idx = variant_first_index_v<T, is_variant_null>;
 4820|     74|                  using V = std::variant_alternative_t<first_idx, T>;
 4821|     74|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4821:23): [True: 0, False: 74]
  ------------------
 4822|     74|                  match<"null", Opts>(ctx, it, end);
 4823|     74|               }
 4824|     74|               break;
 4825|  2.55k|            default: {
  ------------------
  |  Branch (4825:13): [True: 2.55k, False: 8.76k]
  ------------------
 4826|       |               // Not bool, string, object, or array so must be number or null
 4827|  2.55k|               process_variant_alternatives<T, is_variant_num>::template op<Opts>(value, ctx, it, end);
 4828|  2.55k|            }
 4829|  11.3k|            }
 4830|       |         }
 4831|       |         else {
 4832|       |            // For non-auto-deducible variants, try each type until one succeeds
 4833|       |            constexpr auto N = std::variant_size_v<T>;
 4834|       |            bool parsed = false;
 4835|       |            bool exhausted = false; // speculation budget spent; see charge_speculation
 4836|       |
 4837|       |            for_each<N>([&]<size_t I>() {
 4838|       |               if (parsed || exhausted || variant_alternative_exhausted(ctx)) return;
 4839|       |
 4840|       |               auto copy_it = it;
 4841|       |               // A rejected alternative may have bailed out inside a container, which leaves its
 4842|       |               // nesting level counted (see enter_depth), so the depth rewinds with the iterator.
 4843|       |               const auto copy_depth = ctx.depth;
 4844|       |
 4845|       |               // Try parsing as this type
 4846|       |               if (value.index() != I) {
 4847|       |                  emplace_runtime_variant(value, I);
 4848|       |               }
 4849|       |
 4850|       |               std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
 4851|       |               if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 4852|       |                  exhausted = true; // only rejected attempts are charged; see charge_speculation
 4853|       |               }
 4854|       |
 4855|       |               if (!bool(ctx.error)) {
 4856|       |                  parsed = true;
 4857|       |               }
 4858|       |               else if constexpr (not Options.null_terminated) {
 4859|       |                  // In non-null-terminated mode, if we hit end_reached after advancing the iterator,
 4860|       |                  // it means we successfully parsed the value but couldn't skip trailing whitespace
 4861|       |                  if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 4862|       |                     // We advanced the iterator, so we did parse something -- unless what advanced it
 4863|       |                     // was an abandoned attempt, which is what a spent speculation budget means.
 4864|       |                     parsed = true;
 4865|       |                     ctx.error = error_code::none;
 4866|       |                  }
 4867|       |                  else {
 4868|       |                     // Reset for next attempt (unless this is the last type)
 4869|       |                     it = copy_it;
 4870|       |                     rewind_depth<Options>(ctx, copy_depth);
 4871|       |                     if constexpr (I + 1 < N) {
 4872|       |                        if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4873|       |                           ctx.error = error_code::none; // Clear error for next attempt
 4874|       |                        }
 4875|       |                     }
 4876|       |                  }
 4877|       |               }
 4878|       |               else {
 4879|       |                  // Reset for next attempt (unless this is the last type)
 4880|       |                  it = copy_it;
 4881|       |                  rewind_depth<Options>(ctx, copy_depth);
 4882|       |                  if constexpr (I + 1 < N) {
 4883|       |                     if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4884|       |                        ctx.error = error_code::none; // Clear error for next attempt
 4885|       |                     }
 4886|       |                  }
 4887|       |               }
 4888|       |            });
 4889|       |         }
 4890|  11.3k|      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj1EEERNS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES4_EEEETkNS_10is_contextERNS_7contextERPKcSD_EEvOT0_OT1_OT2_T3_:
   49|  27.4k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  27.4k|         else {
   60|  27.4k|            using V = std::remove_cvref_t<T>;
   61|  27.4k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  27.4k|                                             end);
   63|  27.4k|         }
   64|  27.4k|      }
_ZN3glz4fromILj10ENS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES1_EEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNS9_ILm1EEEEERS5_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT1_OT2_OT3_T4_:
 3044|  27.4k|      {
 3045|  27.4k|         static constexpr auto num_members = reflect<T>::size;
 3046|       |
 3047|  27.4k|         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
 3048|       |         if constexpr (!check_opening_handled(Options)) {
 3049|       |            if constexpr (!check_ws_handled(Options)) {
 3050|       |               if (skip_ws<Opts>(ctx, it, end)) {
 3051|       |                  return;
 3052|       |               }
 3053|       |            }
 3054|       |            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
 3055|       |               return;
 3056|       |            }
 3057|       |            if constexpr (not Opts.null_terminated) {
 3058|       |               if (it == end) [[unlikely]] {
 3059|       |                  ctx.error = error_code::unexpected_end;
 3060|       |                  return;
 3061|       |               }
 3062|       |            }
 3063|       |            // one nesting level (see enter_depth): counted in both modes so the limit binds,
 3064|       |            // released at each syntactic close below
 3065|       |            if (enter_depth(ctx)) [[unlikely]] {
 3066|       |               return;
 3067|       |            }
 3068|       |         }
 3069|  27.4k|         const auto ws_start = it;
 3070|  27.4k|         if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3070:14): [True: 21, False: 27.4k]
  ------------------
 3071|     21|            return;
 3072|     21|         }
 3073|  27.4k|         const size_t ws_size = size_t(it - ws_start);
 3074|       |
 3075|       |         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
 3076|       |            if constexpr (not tag.sv().empty()) {
 3077|       |               if (*it == '"') {
 3078|       |                  ++it;
 3079|       |                  if constexpr (not Opts.null_terminated) {
 3080|       |                     if (it == end) [[unlikely]] {
 3081|       |                        ctx.error = error_code::unexpected_end;
 3082|       |                        return;
 3083|       |                     }
 3084|       |                  }
 3085|       |
 3086|       |                  const auto start = it;
 3087|       |                  skip_string_view(ctx, it, end);
 3088|       |                  if (bool(ctx.error)) [[unlikely]]
 3089|       |                     return;
 3090|       |                  if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]]
 3091|       |                     return;
 3092|       |                  const sv key{start, size_t(it - start)};
 3093|       |                  ++it;
 3094|       |                  if constexpr (not Opts.null_terminated) {
 3095|       |                     if (it == end) [[unlikely]] {
 3096|       |                        ctx.error = error_code::unexpected_end;
 3097|       |                        return;
 3098|       |                     }
 3099|       |                  }
 3100|       |
 3101|       |                  if (key == tag.sv()) {
 3102|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3103|       |                        return;
 3104|       |                     }
 3105|       |
 3106|       |                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
 3107|       |                     if (bool(ctx.error)) [[unlikely]]
 3108|       |                        return;
 3109|       |
 3110|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 3111|       |                        return;
 3112|       |                     }
 3113|       |                  }
 3114|       |                  else {
 3115|       |                     ctx.error = error_code::unknown_key;
 3116|       |                     return;
 3117|       |                  }
 3118|       |               }
 3119|       |            }
 3120|       |
 3121|       |            if (*it == '}') [[likely]] {
 3122|       |               --ctx.depth;
 3123|       |               if constexpr (glaze_object_t<T> || reflectable<T>) {
 3124|       |                  if constexpr (has_self_constraint_v<T> && !check_skip_self_constraint(Opts)) {
 3125|       |                     auto wrapper = self_constraint_v<T>(value);
 3126|       |                     from<JSON, decltype(wrapper)>::template op<ws_handled<Opts>()>(wrapper, ctx, it, end);
 3127|       |                     if (bool(ctx.error)) {
 3128|       |                        return;
 3129|       |                     }
 3130|       |                  }
 3131|       |               }
 3132|       |               ++it;
 3133|       |               if constexpr (not Opts.null_terminated) {
 3134|       |                  if (it == end) {
 3135|       |                     ctx.error = error_code::end_reached;
 3136|       |                     return;
 3137|       |                  }
 3138|       |               }
 3139|       |               if constexpr (Opts.partial_read) {
 3140|       |                  ctx.error = error_code::partial_read_complete;
 3141|       |               }
 3142|       |               return;
 3143|       |            }
 3144|       |            ctx.error = error_code::unknown_key;
 3145|       |            return;
 3146|       |         }
 3147|  27.4k|         else {
 3148|  27.4k|            decltype(auto) fields = [&]() -> decltype(auto) {
 3149|  27.4k|               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
 3150|  27.4k|                             (Opts.error_on_missing_keys || Opts.partial_read)) {
 3151|  27.4k|                  return bit_array<num_members>{};
 3152|  27.4k|               }
 3153|  27.4k|               else {
 3154|  27.4k|                  return nullptr;
 3155|  27.4k|               }
 3156|  27.4k|            }();
 3157|       |
 3158|  27.4k|            size_t read_count{}; // for partial_read
 3159|       |
 3160|  27.4k|            bool first = true;
 3161|  1.14M|            while (true) {
  ------------------
  |  Branch (3161:20): [True: 1.11M, Folded]
  ------------------
 3162|       |               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
 3163|       |                  static constexpr bit_array<num_members> all_fields = [] {
 3164|       |                     bit_array<num_members> arr{};
 3165|       |                     for (size_t i = 0; i < num_members; ++i) {
 3166|       |                        arr[i] = true;
 3167|       |                     }
 3168|       |                     return arr;
 3169|       |                  }();
 3170|       |
 3171|       |                  if ((all_fields & fields) == all_fields) {
 3172|       |                     ctx.error = error_code::partial_read_complete;
 3173|       |                     --ctx.depth; // as above: an early success still closes this level
 3174|       |                     return;
 3175|       |                  }
 3176|       |               }
 3177|       |
 3178|       |               // Streaming refill point: at start of each iteration, ensure buffer has data
 3179|       |               if constexpr (has_streaming_state<decltype(ctx)>) {
 3180|       |                  if (ctx.stream.enabled()) {
 3181|       |                     const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 3182|       |                     const size_t remaining = ctx.stream.size() - consumed;
 3183|       |                     // Refill when less than half of buffer remains to ensure space for next key-value pair
 3184|       |                     if (remaining <= ctx.stream.size() / 2 || it >= end) {
 3185|       |                        const char* new_it;
 3186|       |                        const char* new_end;
 3187|       |                        ctx.stream.consume_and_refill(consumed, new_it, new_end);
 3188|       |                        it = new_it;
 3189|       |                        end = new_end;
 3190|       |                        if (it >= end && ctx.stream.at_eof()) {
 3191|       |                           ctx.error = error_code::unexpected_end;
 3192|       |                           return;
 3193|       |                        }
 3194|       |                     }
 3195|       |                  }
 3196|       |               }
 3197|       |
 3198|  1.11M|               if (*it == '}') {
  ------------------
  |  Branch (3198:20): [True: 2.05k, False: 1.11M]
  ------------------
 3199|  2.05k|                  --ctx.depth;
 3200|       |                  if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
 3201|       |                     constexpr auto req_fields = required_fields<T, Opts>();
 3202|       |                     if ((req_fields & fields) != req_fields) {
 3203|       |                        for (size_t i = 0; i < num_members; ++i) {
 3204|       |                           if (not fields[i] && req_fields[i]) {
 3205|       |                              ctx.custom_error_message = reflect<T>::keys[i];
 3206|       |                              // We just return the first missing key in order to avoid heap allocations
 3207|       |                              break;
 3208|       |                           }
 3209|       |                        }
 3210|       |
 3211|       |                        ctx.error = error_code::missing_key;
 3212|       |                        return;
 3213|       |                     }
 3214|       |                  }
 3215|       |                  if constexpr (glaze_object_t<T> || reflectable<T>) {
 3216|       |                     if constexpr (has_self_constraint_v<T> && !check_skip_self_constraint(Opts)) {
 3217|       |                        auto wrapper = self_constraint_v<T>(value);
 3218|       |                        from<JSON, decltype(wrapper)>::template op<ws_handled<Opts>()>(wrapper, ctx, it, end);
 3219|       |                        if (bool(ctx.error)) {
 3220|       |                           return;
 3221|       |                        }
 3222|       |                     }
 3223|       |                  }
 3224|  2.05k|                  ++it; // Increment after checking for missing keys so errors are within buffer bounds
 3225|  2.05k|                  if constexpr (not Opts.null_terminated) {
 3226|  2.05k|                     if (it == end) {
  ------------------
  |  Branch (3226:26): [True: 13, False: 2.04k]
  ------------------
 3227|     13|                        ctx.error = error_code::end_reached;
 3228|     13|                        return;
 3229|     13|                     }
 3230|  2.05k|                  }
 3231|  2.04k|                  return;
 3232|  2.05k|               }
 3233|  1.11M|               else if (first) {
  ------------------
  |  Branch (3233:25): [True: 25.7k, False: 1.08M]
  ------------------
 3234|  25.7k|                  first = false;
 3235|  25.7k|               }
 3236|  1.08M|               else {
 3237|  1.08M|                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3237:23): [True: 349, False: 1.08M]
  ------------------
 3238|    349|                     return;
 3239|    349|                  }
 3240|  1.08M|                  if constexpr (not Opts.null_terminated) {
 3241|  1.08M|                     if (it == end) [[unlikely]] {
  ------------------
  |  Branch (3241:26): [True: 0, False: 1.08M]
  ------------------
 3242|      0|                        ctx.error = error_code::unexpected_end;
 3243|      0|                        return;
 3244|      0|                     }
 3245|  1.08M|                  }
 3246|       |
 3247|       |                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys) &&
 3248|       |                                (!Opts.comments)) {
 3249|       |                     if (ws_size && ws_size < size_t(end - it)) {
 3250|       |                        skip_matching_ws(ws_start, it, ws_size);
 3251|       |                     }
 3252|       |                  }
 3253|       |
 3254|  1.08M|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3254:23): [True: 21, False: 1.08M]
  ------------------
 3255|     21|                     return;
 3256|     21|                  }
 3257|  1.08M|               }
 3258|       |
 3259|  1.11M|               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
  ------------------
  |  Branch (3259:49): [Folded, False: 0]
  |  Branch (3259:70): [Folded, False: 0]
  ------------------
 3260|       |
 3261|       |               if constexpr (reflection_type && (num_members == 0)) {
 3262|       |                  if constexpr (Opts.error_on_unknown_keys) {
 3263|       |                     static_assert(false_v<T>, "This should be unreachable");
 3264|       |                  }
 3265|       |                  else {
 3266|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 3267|       |                        return;
 3268|       |                     }
 3269|       |
 3270|       |                     // parsing to an empty object, but at this point the JSON presents keys
 3271|       |
 3272|       |                     // Unknown key handler does not unescape keys. Unknown escaped keys are
 3273|       |                     // handled by the user.
 3274|       |
 3275|       |                     const auto start = it;
 3276|       |                     skip_string_view(ctx, it, end);
 3277|       |                     if (bool(ctx.error)) [[unlikely]]
 3278|       |                        return;
 3279|       |                     if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]]
 3280|       |                        return;
 3281|       |                     const sv key{start, size_t(it - start)};
 3282|       |                     ++it;
 3283|       |                     if constexpr (not Opts.null_terminated) {
 3284|       |                        if (it == end) [[unlikely]] {
 3285|       |                           ctx.error = error_code::unexpected_end;
 3286|       |                           return;
 3287|       |                        }
 3288|       |                     }
 3289|       |
 3290|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3291|       |                        return;
 3292|       |                     }
 3293|       |
 3294|       |                     // Check if this key is the variant tag that should be skipped
 3295|       |                     if constexpr (not tag.sv().empty()) {
 3296|       |                        if (key == tag.sv()) {
 3297|       |                           // Skip the tag value
 3298|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 3299|       |                           if (bool(ctx.error)) [[unlikely]]
 3300|       |                              return;
 3301|       |                           resync_window_end(ctx, end); // a streaming skip refills
 3302|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 3303|       |                              return;
 3304|       |                           }
 3305|       |                           continue;
 3306|       |                        }
 3307|       |                     }
 3308|       |
 3309|       |                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
 3310|       |                     if (bool(ctx.error)) [[unlikely]]
 3311|       |                        return;
 3312|       |                     if constexpr (not Opts.null_terminated) {
 3313|       |                        if (it == end) [[unlikely]] {
 3314|       |                           ctx.error = error_code::unexpected_end;
 3315|       |                           return;
 3316|       |                        }
 3317|       |                     }
 3318|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 3319|       |                        return;
 3320|       |                     }
 3321|       |                  }
 3322|       |               }
 3323|       |               else if constexpr (reflection_type) {
 3324|       |                  static_assert(bool(hash_info<T>.type));
 3325|       |
 3326|       |                  if (*it != '"') [[unlikely]] {
 3327|       |                     ctx.error = error_code::expected_quote;
 3328|       |                     return;
 3329|       |                  }
 3330|       |                  ++it;
 3331|       |                  if constexpr (not Opts.null_terminated) {
 3332|       |                     if (it == end) [[unlikely]] {
 3333|       |                        ctx.error = error_code::unexpected_end;
 3334|       |                        return;
 3335|       |                     }
 3336|       |                  }
 3337|       |
 3338|       |                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
 3339|       |                     // For tagged variants we first check to see if the key matches the tag
 3340|       |                     // We only need to do this if the tag is not part of the keys
 3341|       |
 3342|       |                     const auto start = it;
 3343|       |                     skip_string_view(ctx, it, end);
 3344|       |                     if (bool(ctx.error)) [[unlikely]]
 3345|       |                        return;
 3346|       |                     if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]]
 3347|       |                        return;
 3348|       |                     const sv key{start, size_t(it - start)};
 3349|       |                     ++it;
 3350|       |                     if constexpr (not Opts.null_terminated) {
 3351|       |                        if (it == end) [[unlikely]] {
 3352|       |                           ctx.error = error_code::unexpected_end;
 3353|       |                           return;
 3354|       |                        }
 3355|       |                     }
 3356|       |
 3357|       |                     if (key == tag.sv()) {
 3358|       |                        if (parse_ws_colon<Opts>(ctx, it, end)) {
 3359|       |                           return;
 3360|       |                        }
 3361|       |
 3362|       |                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
 3363|       |                        if (bool(ctx.error)) [[unlikely]]
 3364|       |                           return;
 3365|       |
 3366|       |                        if (skip_ws<Opts>(ctx, it, end)) {
 3367|       |                           return;
 3368|       |                        }
 3369|       |                        continue;
 3370|       |                     }
 3371|       |                     else {
 3372|       |                        it = start; // reset the iterator
 3373|       |                     }
 3374|       |                  }
 3375|       |
 3376|       |                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
 3377|       |                     size_t index = num_members;
 3378|       |                     parse_and_invoke<Opts, T>(value, ctx, it, end, index);
 3379|       |                     if (bool(ctx.error)) [[unlikely]]
 3380|       |                        return;
 3381|       |                     if (index < num_members) {
 3382|       |                        fields[index] = true;
 3383|       |                     }
 3384|       |                  }
 3385|       |                  else {
 3386|       |                     parse_and_invoke<Opts, T>(value, ctx, it, end);
 3387|       |                     if (bool(ctx.error)) [[unlikely]]
 3388|       |                        return;
 3389|       |                  }
 3390|       |               }
 3391|  1.11M|               else {
 3392|       |                  // For types like std::map, std::unordered_map
 3393|       |
 3394|  1.11M|                  auto reading = [&](auto&& key) {
 3395|  1.11M|                     if constexpr (Opts.partial_read) {
 3396|  1.11M|                        if (auto element = value.find(key); element != value.end()) {
 3397|  1.11M|                           ++read_count;
 3398|  1.11M|                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
 3399|  1.11M|                        }
 3400|  1.11M|                        else {
 3401|  1.11M|                           skip_value<JSON>::op<Opts>(ctx, it, end);
 3402|  1.11M|                        }
 3403|  1.11M|                     }
 3404|  1.11M|                     else {
 3405|  1.11M|                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
 3406|  1.11M|                     }
 3407|  1.11M|                  };
 3408|       |
 3409|       |                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
 3410|  1.11M|                  using Key = typename T::key_type;
 3411|  1.11M|                  if constexpr (std::is_same_v<Key, std::string>) {
 3412|  1.11M|                     ctx.scratch.clear();
 3413|  1.11M|                     parse<JSON>::op<Opts>(ctx.scratch, ctx, it, end);
 3414|  1.11M|                     if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (3414:26): [True: 1.40k, False: 1.11M]
  ------------------
 3415|  1.40k|                        return;
 3416|       |
 3417|  1.11M|                     if (parse_ws_colon<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3417:26): [True: 1.72k, False: 1.11M]
  ------------------
 3418|  1.72k|                        return;
 3419|  1.72k|                     }
 3420|       |
 3421|  1.11M|                     reading(ctx.scratch);
 3422|       |                     if constexpr (Opts.partial_read) {
 3423|       |                        if (read_count == value.size()) {
 3424|       |                           return;
 3425|       |                        }
 3426|       |                     }
 3427|  1.11M|                     if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (3427:26): [True: 21.7k, False: 1.09M]
  ------------------
 3428|  21.7k|                        return;
 3429|       |                  }
 3430|       |                  else if constexpr (str_t<Key>) {
 3431|       |                     Key key;
 3432|       |                     parse<JSON>::op<Opts>(key, ctx, it, end);
 3433|       |                     if (bool(ctx.error)) [[unlikely]]
 3434|       |                        return;
 3435|       |
 3436|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3437|       |                        return;
 3438|       |                     }
 3439|       |
 3440|       |                     reading(key);
 3441|       |                     if constexpr (Opts.partial_read) {
 3442|       |                        if (read_count == value.size()) {
 3443|       |                           return;
 3444|       |                        }
 3445|       |                     }
 3446|       |                     if (bool(ctx.error)) [[unlikely]]
 3447|       |                        return;
 3448|       |                  }
 3449|       |                  else {
 3450|       |                     Key key_value{};
 3451|       |                     if constexpr (is_named_enum<Key> || mimics_str_t<Key>) {
 3452|       |                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
 3453|       |                     }
 3454|       |                     else if constexpr (std::is_arithmetic_v<Key>) {
 3455|       |                        // prefer over quoted_t below to avoid double parsing of quoted_t
 3456|       |                        parse<JSON>::op<opt_true<Opts, quoted_num_opt_tag{}>>(key_value, ctx, it, end);
 3457|       |                     }
 3458|       |                     else {
 3459|       |                        parse<JSON>::op<opt_false<Opts, raw_string_opt_tag{}>>(quoted_t<Key>{key_value}, ctx, it, end);
 3460|       |                     }
 3461|       |                     if (bool(ctx.error)) [[unlikely]]
 3462|       |                        return;
 3463|       |
 3464|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3465|       |                        return;
 3466|       |                     }
 3467|       |
 3468|       |                     reading(key_value);
 3469|       |                     if constexpr (Opts.partial_read) {
 3470|       |                        if (read_count == value.size()) {
 3471|       |                           return;
 3472|       |                        }
 3473|       |                     }
 3474|       |                     if (bool(ctx.error)) [[unlikely]]
 3475|       |                        return;
 3476|       |                  }
 3477|  1.11M|               }
 3478|       |
 3479|       |               // Streaming refill point: after parsing each key-value pair, refill if buffer is low
 3480|       |               if constexpr (has_streaming_state<decltype(ctx)>) {
 3481|       |                  if (ctx.stream.enabled()) {
 3482|       |                     const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 3483|       |                     // Refill when less than 25% of buffer remains to ensure enough space for next element
 3484|       |                     if (ctx.stream.size() - consumed <= ctx.stream.size() / 4 || it >= end) {
 3485|       |                        const char* new_it;
 3486|       |                        const char* new_end;
 3487|       |                        ctx.stream.consume_and_refill(consumed, new_it, new_end);
 3488|       |                        it = new_it;
 3489|       |                        end = new_end;
 3490|       |                        if (it >= end && ctx.stream.at_eof()) {
 3491|       |                           ctx.error = error_code::unexpected_end;
 3492|       |                           return;
 3493|       |                        }
 3494|       |                     }
 3495|       |                  }
 3496|       |               }
 3497|       |
 3498|  1.11M|               if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3498:20): [True: 208, False: 1.11M]
  ------------------
 3499|    208|                  return;
 3500|    208|               }
 3501|  1.11M|            }
 3502|  27.4k|         }
 3503|  27.4k|      }
_ZZN3glz4fromILj10ENS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES1_EEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNS9_ILm1EEEEERS5_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT1_OT2_OT3_T4_ENKUlvE_clEv:
 3148|  27.4k|            decltype(auto) fields = [&]() -> decltype(auto) {
 3149|       |               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
 3150|       |                             (Opts.error_on_missing_keys || Opts.partial_read)) {
 3151|       |                  return bit_array<num_members>{};
 3152|       |               }
 3153|  27.4k|               else {
 3154|  27.4k|                  return nullptr;
 3155|  27.4k|               }
 3156|  27.4k|            }();
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_T3_:
   49|  1.11M|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  1.11M|         else {
   60|  1.11M|            using V = std::remove_cvref_t<T>;
   61|  1.11M|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  1.11M|                                             end);
   63|  1.11M|         }
   64|  1.11M|      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERPKcSC_S7_TkNS_10is_contextERNS_7contextEQntcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_T1_:
 1043|  1.11M|      {
 1044|       |         if constexpr (check_string_as_number(Opts)) {
 1045|       |            auto start = it;
 1046|       |            skip_number<Opts>(ctx, it, end);
 1047|       |            if (bool(ctx.error)) [[unlikely]] {
 1048|       |               return;
 1049|       |            }
 1050|       |            if (start == it) [[unlikely]] {
 1051|       |               ctx.error = error_code::parse_number_failure;
 1052|       |               return;
 1053|       |            }
 1054|       |            value.append(start, size_t(it - start));
 1055|       |         }
 1056|  1.11M|         else {
 1057|  1.11M|            if constexpr (!check_opening_handled(Opts)) {
 1058|  1.11M|               if constexpr (!check_ws_handled(Opts)) {
 1059|  1.11M|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (1059:23): [True: 0, False: 1.11M]
  ------------------
 1060|      0|                     return;
 1061|      0|                  }
 1062|  1.11M|               }
 1063|       |
 1064|  1.11M|               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (1064:20): [True: 292, False: 1.11M]
  ------------------
 1065|    292|                  return;
 1066|    292|               }
 1067|  1.11M|            }
 1068|       |
 1069|  1.11M|            if constexpr (not check_raw_string(Opts)) {
 1070|  1.11M|               static constexpr auto string_padding_bytes = 8;
 1071|       |
 1072|  1.11M|               if (size_t(end - it) >= 8) {
  ------------------
  |  Branch (1072:20): [True: 1.11M, False: 3.04k]
  ------------------
 1073|  1.11M|                  auto start = it;
 1074|  1.11M|                  uint64_t ascii_acc{};
 1075|  1.11M|                  const auto end8 = end - 8;
 1076|  4.12M|                  while (true) {
  ------------------
  |  Branch (1076:26): [True: 4.12M, Folded]
  ------------------
 1077|  4.12M|                     if (it >= end8) [[unlikely]] {
  ------------------
  |  Branch (1077:26): [True: 1.07k, False: 4.12M]
  ------------------
 1078|  1.07k|                        break;
 1079|  1.07k|                     }
 1080|       |
 1081|  4.12M|                     uint64_t chunk;
 1082|  4.12M|                     std::memcpy(&chunk, it, 8);
 1083|       |                     if constexpr (std::endian::native == std::endian::big) {
 1084|       |                        chunk = std::byteswap(chunk);
 1085|       |                     }
 1086|  4.12M|                     ascii_acc |= chunk;
 1087|  4.12M|                     const uint64_t test_chars = has_quote(chunk);
 1088|  4.12M|                     if (test_chars) {
  ------------------
  |  Branch (1088:26): [True: 1.11M, False: 3.01M]
  ------------------
 1089|  1.11M|                        it += (countr_zero(test_chars) >> 3);
 1090|       |
 1091|  1.11M|                        auto* prev = it - 1;
 1092|  1.11M|                        while (*prev == '\\') {
  ------------------
  |  Branch (1092:32): [True: 1.72k, False: 1.11M]
  ------------------
 1093|  1.72k|                           --prev;
 1094|  1.72k|                        }
 1095|  1.11M|                        if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (1095:29): [True: 1.11M, False: 1.38k]
  ------------------
 1096|  1.11M|                           goto continue_decode;
 1097|  1.11M|                        }
 1098|  1.38k|                        ++it; // skip the escaped quote
 1099|  1.38k|                     }
 1100|  3.01M|                     else {
 1101|  3.01M|                        it += 8;
 1102|  3.01M|                     }
 1103|  4.12M|                  }
 1104|       |
 1105|  3.29k|                  while (it[-1] == '\\') [[unlikely]] {
  ------------------
  |  Branch (1105:26): [True: 2.22k, False: 1.07k]
  ------------------
 1106|       |                     // if we ended on an escape character then we need to rewind
 1107|       |                     // because we lost our context
 1108|  2.22k|                     --it;
 1109|  2.22k|                  }
 1110|       |
 1111|       |                  // The byte-wise tail keeps feeding the accumulator: it has to cover every byte of
 1112|       |                  // the string, or a non-ASCII byte reached here would be waved through unvalidated.
 1113|  5.99k|                  for (; it < end; ++it) {
  ------------------
  |  Branch (1113:26): [True: 5.85k, False: 144]
  ------------------
 1114|  5.85k|                     ascii_acc |= uint8_t(*it);
 1115|  5.85k|                     if (*it == '"') {
  ------------------
  |  Branch (1115:26): [True: 998, False: 4.85k]
  ------------------
 1116|    998|                        auto* prev = it - 1;
 1117|  2.15k|                        while (*prev == '\\') {
  ------------------
  |  Branch (1117:32): [True: 1.16k, False: 998]
  ------------------
 1118|  1.16k|                           --prev;
 1119|  1.16k|                        }
 1120|    998|                        if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (1120:29): [True: 927, False: 71]
  ------------------
 1121|    927|                           goto continue_decode;
 1122|    927|                        }
 1123|    998|                     }
 1124|  5.85k|                  }
 1125|       |
 1126|    144|                  ctx.error = error_code::unexpected_end;
 1127|    144|                  return;
 1128|       |
 1129|  1.11M|               continue_decode:
 1130|       |
 1131|  1.11M|                  if (validate_utf8_span<Opts>(ctx, start, it, ascii_acc)) [[unlikely]] {
  ------------------
  |  Branch (1131:23): [True: 129, False: 1.11M]
  ------------------
 1132|    129|                     return;
 1133|    129|                  }
 1134|       |
 1135|  1.11M|                  const auto available_padding = size_t(end - it);
 1136|  1.11M|                  auto n = size_t(it - start);
 1137|  1.11M|                  if (available_padding >= 8) [[likely]] {
  ------------------
  |  Branch (1137:23): [True: 1.11M, False: 1.19k]
  ------------------
 1138|  1.11M|                     value.resize(n + string_padding_bytes);
 1139|       |
 1140|  1.11M|                     auto* p = value.data();
 1141|       |
 1142|  4.73M|                     while (true) {
  ------------------
  |  Branch (1142:29): [True: 4.73M, Folded]
  ------------------
 1143|  4.73M|                        if (start >= it) {
  ------------------
  |  Branch (1143:29): [True: 1.10M, False: 3.62M]
  ------------------
 1144|  1.10M|                           break;
 1145|  1.10M|                        }
 1146|       |
 1147|  3.62M|                        std::memcpy(p, start, 8);
 1148|  3.62M|                        uint64_t swar;
 1149|  3.62M|                        std::memcpy(&swar, p, 8);
 1150|       |                        if constexpr (std::endian::native == std::endian::big) {
 1151|       |                           swar = std::byteswap(swar);
 1152|       |                        }
 1153|       |
 1154|  3.62M|                        constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
 1155|  3.62M|                        const uint64_t lo7 = swar & lo7_mask;
 1156|  3.62M|                        const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
 1157|  3.62M|                        const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
 1158|  3.62M|                        uint64_t next = ~((backslash & less_32) | swar);
 1159|       |
 1160|  3.62M|                        next &= repeat_byte8(0b10000000);
 1161|  3.62M|                        if (next == 0) {
  ------------------
  |  Branch (1161:29): [True: 3.62M, False: 9.30k]
  ------------------
 1162|  3.62M|                           start += 8;
 1163|  3.62M|                           p += 8;
 1164|  3.62M|                           continue;
 1165|  3.62M|                        }
 1166|       |
 1167|  9.30k|                        next = countr_zero(next) >> 3;
 1168|  9.30k|                        start += next;
 1169|  9.30k|                        if (start >= it) {
  ------------------
  |  Branch (1169:29): [True: 2.64k, False: 6.66k]
  ------------------
 1170|  2.64k|                           break;
 1171|  2.64k|                        }
 1172|       |
 1173|  6.66k|                        if ((*start & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1173:29): [True: 31, False: 6.62k]
  ------------------
 1174|     31|                           ctx.error = error_code::syntax_error;
 1175|     31|                           return;
 1176|     31|                        }
 1177|  6.62k|                        ++start; // skip the escape
 1178|  6.62k|                        if (*start == 'u') {
  ------------------
  |  Branch (1178:29): [True: 5.84k, False: 780]
  ------------------
 1179|  5.84k|                           ++start;
 1180|  5.84k|                           p += next;
 1181|  5.84k|                           const auto mark = start;
 1182|  5.84k|                           const auto offset = handle_unicode_code_point(start, p, end);
 1183|  5.84k|                           if (offset == 0) [[unlikely]] {
  ------------------
  |  Branch (1183:32): [True: 24, False: 5.82k]
  ------------------
 1184|     24|                              ctx.error = error_code::unicode_escape_conversion_failure;
 1185|     24|                              return;
 1186|     24|                           }
 1187|  5.82k|                           n += offset;
 1188|       |                           // escape + u + unicode code points
 1189|  5.82k|                           n -= 2 + uint32_t(start - mark);
 1190|  5.82k|                        }
 1191|    780|                        else {
 1192|    780|                           p += next;
 1193|    780|                           *p = char_unescape_table[uint8_t(*start)];
 1194|    780|                           if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1194:32): [True: 8, False: 772]
  ------------------
 1195|      8|                              ctx.error = error_code::invalid_escape;
 1196|      8|                              return;
 1197|      8|                           }
 1198|    772|                           ++p;
 1199|    772|                           ++start;
 1200|    772|                           --n;
 1201|    772|                        }
 1202|  6.62k|                     }
 1203|       |
 1204|  1.11M|                     value.resize(n);
 1205|  1.11M|                     ++it;
 1206|  1.11M|                  }
 1207|  1.19k|                  else {
 1208|       |                     // For large inputs this case of running out of buffer is very rare
 1209|  1.19k|                     value.resize(n);
 1210|  1.19k|                     auto* p = value.data();
 1211|       |
 1212|  1.19k|                     it = start;
 1213|   191k|                     while (it < end) [[likely]] {
  ------------------
  |  Branch (1213:29): [True: 191k, False: 0]
  ------------------
 1214|   191k|                        if (*it == '"') {
  ------------------
  |  Branch (1214:29): [True: 1.04k, False: 190k]
  ------------------
 1215|  1.04k|                           value.resize(size_t(p - value.data()));
 1216|  1.04k|                           ++it;
 1217|  1.04k|                           return;
 1218|  1.04k|                        }
 1219|       |
 1220|   190k|                        if ((*it & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1220:29): [True: 33, False: 190k]
  ------------------
 1221|     33|                           ctx.error = error_code::syntax_error;
 1222|     33|                           return;
 1223|     33|                        }
 1224|       |
 1225|   190k|                        *p = *it;
 1226|       |
 1227|   190k|                        if (*it == '\\') {
  ------------------
  |  Branch (1227:29): [True: 2.85k, False: 187k]
  ------------------
 1228|  2.85k|                           ++it; // skip the escape
 1229|  2.85k|                           if (*it == 'u') {
  ------------------
  |  Branch (1229:32): [True: 1.35k, False: 1.49k]
  ------------------
 1230|  1.35k|                              ++it;
 1231|  1.35k|                              if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
  ------------------
  |  Branch (1231:35): [True: 104, False: 1.25k]
  ------------------
 1232|    104|                                 ctx.error = error_code::unicode_escape_conversion_failure;
 1233|    104|                                 return;
 1234|    104|                              }
 1235|  1.35k|                           }
 1236|  1.49k|                           else {
 1237|  1.49k|                              *p = char_unescape_table[uint8_t(*it)];
 1238|  1.49k|                              if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1238:35): [True: 12, False: 1.48k]
  ------------------
 1239|     12|                                 ctx.error = error_code::invalid_escape;
 1240|     12|                                 return;
 1241|     12|                              }
 1242|  1.48k|                              ++p;
 1243|  1.48k|                              ++it;
 1244|  1.48k|                           }
 1245|  2.85k|                        }
 1246|   187k|                        else {
 1247|   187k|                           ++it;
 1248|   187k|                           ++p;
 1249|   187k|                        }
 1250|   190k|                     }
 1251|       |
 1252|      0|                     ctx.error = error_code::unexpected_end;
 1253|      0|                  }
 1254|  1.11M|               }
 1255|  3.04k|               else {
 1256|       |                  // For short strings
 1257|       |
 1258|  3.04k|                  std::array<char, 8> buffer{};
 1259|       |
 1260|  3.04k|                  auto* p = buffer.data();
 1261|  3.04k|                  const auto* const utf8_start = it;
 1262|       |
 1263|  6.36k|                  while (it < end) [[likely]] {
  ------------------
  |  Branch (1263:26): [True: 5.81k, False: 552]
  ------------------
 1264|  5.81k|                     *p = *it;
 1265|  5.81k|                     if (*it == '"') {
  ------------------
  |  Branch (1265:26): [True: 2.39k, False: 3.41k]
  ------------------
 1266|  2.39k|                        if (validate_utf8_span<Opts>(ctx, utf8_start, it)) [[unlikely]] {
  ------------------
  |  Branch (1266:29): [True: 117, False: 2.28k]
  ------------------
 1267|    117|                           return;
 1268|    117|                        }
 1269|  2.28k|                        const size_t n = size_t(p - buffer.data());
 1270|  2.28k|#if __has_cpp_attribute(assume) >= 202207L
 1271|  2.28k|                        [[assume(n <= sizeof(buffer))]];
 1272|  2.28k|#endif
 1273|  2.28k|                        value.assign(buffer.data(), n);
 1274|  2.28k|                        ++it;
 1275|  2.28k|                        if constexpr (not Opts.null_terminated) {
 1276|  2.28k|                           if (it == end) {
  ------------------
  |  Branch (1276:32): [True: 157, False: 2.12k]
  ------------------
 1277|    157|                              ctx.error = error_code::end_reached;
 1278|    157|                              return;
 1279|    157|                           }
 1280|  2.28k|                        }
 1281|  2.12k|                        return;
 1282|  2.39k|                     }
 1283|  3.41k|                     else if (*it == '\\') {
  ------------------
  |  Branch (1283:31): [True: 155, False: 3.25k]
  ------------------
 1284|    155|                        ++it; // skip the escape
 1285|    155|                        if constexpr (not Opts.null_terminated) {
 1286|    155|                           if (it == end) [[unlikely]] {
  ------------------
  |  Branch (1286:32): [True: 2, False: 153]
  ------------------
 1287|      2|                              ctx.error = error_code::unexpected_end;
 1288|      2|                              return;
 1289|      2|                           }
 1290|    155|                        }
 1291|    155|                        if (*it == 'u') {
  ------------------
  |  Branch (1291:29): [True: 103, False: 52]
  ------------------
 1292|    103|                           ++it;
 1293|    103|                           if constexpr (not Opts.null_terminated) {
 1294|    103|                              if (it == end) [[unlikely]] {
  ------------------
  |  Branch (1294:35): [True: 1, False: 102]
  ------------------
 1295|      1|                                 ctx.error = error_code::unexpected_end;
 1296|      1|                                 return;
 1297|      1|                              }
 1298|    103|                           }
 1299|    103|                           if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
  ------------------
  |  Branch (1299:32): [True: 49, False: 54]
  ------------------
 1300|     49|                              ctx.error = error_code::unicode_escape_conversion_failure;
 1301|     49|                              return;
 1302|     49|                           }
 1303|    103|                        }
 1304|     52|                        else {
 1305|     52|                           *p = char_unescape_table[uint8_t(*it)];
 1306|     52|                           if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1306:32): [True: 12, False: 40]
  ------------------
 1307|     12|                              ctx.error = error_code::invalid_escape;
 1308|     12|                              return;
 1309|     12|                           }
 1310|     40|                           ++p;
 1311|     40|                           ++it;
 1312|     40|                        }
 1313|    155|                     }
 1314|  3.25k|                     else if ((*it & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1314:31): [True: 31, False: 3.22k]
  ------------------
 1315|     31|                        ctx.error = error_code::syntax_error;
 1316|     31|                        return;
 1317|     31|                     }
 1318|  3.22k|                     else {
 1319|  3.22k|                        ++it;
 1320|  3.22k|                        ++p;
 1321|  3.22k|                     }
 1322|  5.81k|                  }
 1323|       |
 1324|    552|                  ctx.error = error_code::unexpected_end;
 1325|    552|               }
 1326|       |            }
 1327|       |            else {
 1328|       |               // raw_string
 1329|       |               auto start = it;
 1330|       |               skip_string_view(ctx, it, end);
 1331|       |               if (bool(ctx.error)) [[unlikely]]
 1332|       |                  return;
 1333|       |
 1334|       |               if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]] {
 1335|       |                  return;
 1336|       |               }
 1337|       |
 1338|       |               value.assign(start, size_t(it - start));
 1339|       |               ++it;
 1340|       |            }
 1341|  1.11M|         }
 1342|  1.11M|      }
_ZN3glz14parse_ws_colonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextENS_7contextERPKcS4_EEbRT0_OT1_T2_:
  159|  1.11M|   {
  160|  1.11M|      if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (160:11): [True: 142, False: 1.11M]
  ------------------
  161|    142|         return true;
  162|    142|      }
  163|  1.11M|      if (match_invalid_end<':', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (163:11): [True: 1.55k, False: 1.11M]
  ------------------
  164|  1.55k|         return true;
  165|  1.55k|      }
  166|  1.11M|      if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (166:11): [True: 27, False: 1.11M]
  ------------------
  167|     27|         return true;
  168|     27|      }
  169|  1.11M|      return false;
  170|  1.11M|   }
_ZZN3glz4fromILj10ENS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES1_EEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNS9_ILm1EEEEERS5_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT1_OT2_OT3_T4_ENKUlOT_E_clIRNSt3__112basic_stringIcNSS_11char_traitsIcEENSS_9allocatorIcEEEEEEDaSP_:
 3394|  1.11M|                  auto reading = [&](auto&& key) {
 3395|       |                     if constexpr (Opts.partial_read) {
 3396|       |                        if (auto element = value.find(key); element != value.end()) {
 3397|       |                           ++read_count;
 3398|       |                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
 3399|       |                        }
 3400|       |                        else {
 3401|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 3402|       |                        }
 3403|       |                     }
 3404|  1.11M|                     else {
 3405|  1.11M|                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
 3406|  1.11M|                     }
 3407|  1.11M|                  };
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERNS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
   49|  2.81M|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  2.81M|         else {
   60|  2.81M|            using V = std::remove_cvref_t<T>;
   61|  2.81M|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  2.81M|                                             end);
   63|  2.81M|         }
   64|  2.81M|      }
_ZN3glz4fromILj10ENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERS4_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
  150|  2.81M|      {
  151|  2.81M|         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
  152|  2.81M|         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
  153|  2.81M|                                          std::forward<Ctx>(ctx), std::forward<It0>(it), end);
  154|  2.81M|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4065|  2.81M|      {
 4066|       |         if constexpr (tagging == variant_tagging_kind::adjacent) {
 4067|       |            read_adjacent<Options>(value, ctx, it, end);
 4068|       |         }
 4069|  2.81M|         else {
 4070|  2.81M|            read_deduced<Options>(value, ctx, it, end);
 4071|  2.81M|         }
 4072|  2.81M|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE12read_deducedITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4076|  2.81M|      {
 4077|  2.81M|         constexpr auto Opts = ws_handled_off<Options>();
 4078|  2.81M|         if constexpr (variant_is_auto_deducible<T>()) {
 4079|       |            if constexpr (not check_ws_handled(Options)) {
 4080|       |               if (skip_ws<Opts>(ctx, it, end)) {
 4081|       |                  return;
 4082|       |               }
 4083|       |            }
 4084|       |
 4085|  2.81M|            switch (*it) {
 4086|     89|            case '\0':
  ------------------
  |  Branch (4086:13): [True: 89, False: 2.81M]
  ------------------
 4087|     89|               ctx.error = error_code::unexpected_end;
 4088|     89|               return;
 4089|  22.4k|            case '{': {
  ------------------
  |  Branch (4089:13): [True: 22.4k, False: 2.79M]
  ------------------
 4090|       |               // This branch consumes the brace itself and hands the object to a reader with
 4091|       |               // `opening_handled`, which therefore does not count the level -- but does release it at
 4092|       |               // the closing brace. So the level is taken here, in both buffer modes, and paid back by
 4093|       |               // the reader below.
 4094|  22.4k|               if (enter_depth(ctx)) [[unlikely]] {
  ------------------
  |  Branch (4094:20): [True: 11, False: 22.3k]
  ------------------
 4095|     11|                  return;
 4096|     11|               }
 4097|       |
 4098|  22.3k|               ++it;
 4099|  22.3k|               if constexpr (not Opts.null_terminated) {
 4100|  22.3k|                  if (it == end) [[unlikely]] {
  ------------------
  |  Branch (4100:23): [True: 47, False: 22.3k]
  ------------------
 4101|     47|                     ctx.error = error_code::unexpected_end;
 4102|     47|                     return;
 4103|     47|                  }
 4104|  22.3k|               }
 4105|  22.3k|               using type_counts = variant_type_count<T>;
 4106|  22.3k|               constexpr auto n_object_candidates = variant_object_candidate_count_v<Opts, T>;
 4107|       |               if constexpr (n_object_candidates < 1) {
 4108|       |                  ctx.error = error_code::no_matching_variant_type;
 4109|       |                  return;
 4110|       |               }
 4111|  22.3k|               else if constexpr (n_object_candidates == 1 && tag_v<T>.empty()) {
 4112|  22.3k|                  constexpr auto first_idx = variant_first_object_candidate_v<Opts, T>;
 4113|  22.3k|                  using V = std::variant_alternative_t<first_idx, T>;
 4114|  22.3k|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4114:23): [True: 21.9k, False: 442]
  ------------------
 4115|  22.3k|                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
 4116|  22.3k|                  return;
 4117|       |               }
 4118|       |               else {
 4119|       |                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
 4120|       |                  static constexpr auto& deduction_bits = variant_deduction_bits<T>;
 4121|       |                  static constexpr size_t deduction_key_count = variant_deduction_key_count<T>;
 4122|       |                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
 4123|       |
 4124|       |                  // Track if we've encountered a tag and what value it had
 4125|       |                  std::optional<size_t> tag_specified_index{};
 4126|       |
 4127|       |                  if (skip_ws<Opts>(ctx, it, end)) {
 4128|       |                     return;
 4129|       |                  }
 4130|       |                  // Once the reader knows which alternative this object holds it may have to read
 4131|       |                  // it again from here. Anchor the position rather than keep the pointer: the scan
 4132|       |                  // below skips values, and a streaming skip refills, which moves the window out
 4133|       |                  // from under a raw pointer (see rewind_anchor).
 4134|       |                  auto start = make_rewind_anchor(ctx, it);
 4135|       |                  bool first_key = true;
 4136|       |                  // Parse bifurcation for tagged variants:
 4137|       |                  //
 4138|       |                  // Without this optimization, tagged variant parsing always uses two passes:
 4139|       |                  //   1. Scan all keys to find the tag (e.g. "type"), skipping values
 4140|       |                  //   2. Reset `it = start` and re-parse the entire object into the resolved type
 4141|       |                  //
 4142|       |                  // When the tag is the first key, the second pass redundantly re-reads every
 4143|       |                  // field that follows it. This lambda avoids that: if the tag was the first key,
 4144|       |                  // it advances past the trailing comma so the object parser picks up at the
 4145|       |                  // second field. If the tag was found later, it falls back to the full re-parse.
 4146|       |                  //
 4147|       |                  // One exception: if the tag name is also a field on the resolved struct
 4148|       |                  // (contains_tag), we must re-parse regardless so the value is stored in
 4149|       |                  // the struct field. This override is applied inside each std::visit lambda.
 4150|       |                  //
 4151|       |                  // Either way the rewind can fail under a streaming read: the window only holds so
 4152|       |                  // much, and an object wider than it has no start left to return to.
 4153|       |                  auto position_after_tag = [&] {
 4154|       |                     if (first_key) {
 4155|       |                        if (*it == ',') ++it; // skip comma; handles tag-only objects where *it == '}'
 4156|       |                        return true;
 4157|       |                     }
 4158|       |                     return start.rewind(ctx, it, end); // tag came later, re-parse from the beginning
 4159|       |                  };
 4160|       |                  // `first_key` also answers "were we reset to the object start", which is what
 4161|       |                  // position_after_tag does for every key but the first.
 4162|       |                  for (; *it != '}'; first_key = false) {
 4163|       |                     if (!first_key) {
 4164|       |                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
 4165|       |                           return;
 4166|       |                        }
 4167|       |                     }
 4168|       |
 4169|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4170|       |                        return;
 4171|       |                     }
 4172|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4173|       |                        return;
 4174|       |                     }
 4175|       |
 4176|       |                     auto* key_start = it;
 4177|       |                     skip_string_view(ctx, it, end);
 4178|       |                     if (bool(ctx.error)) [[unlikely]]
 4179|       |                        return;
 4180|       |                     if (validate_utf8_span<Opts>(ctx, key_start, it)) [[unlikely]]
 4181|       |                        return;
 4182|       |                     const sv key = {key_start, size_t(it - key_start)};
 4183|       |
 4184|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4185|       |                        return;
 4186|       |                     }
 4187|       |
 4188|       |                     if constexpr (deduction_key_count > 0) {
 4189|       |                        // We first check if a tag is defined and see if the key matches the tag
 4190|       |                        if constexpr (not tag_v<T>.empty()) {
 4191|       |                           if (key == tag_v<T>) {
 4192|       |                              if (parse_ws_colon<Opts>(ctx, it, end)) {
 4193|       |                                 return;
 4194|       |                              }
 4195|       |
 4196|       |                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
 4197|       |
 4198|       |                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
 4199|       |                              if constexpr (std::integral<id_type>) {
 4200|       |                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
 4201|       |                              }
 4202|       |                              else {
 4203|       |                                 // The id is turned into an index below and never leaves this
 4204|       |                                 // reader, so the view of the window it borrows cannot outlive it.
 4205|       |                                 parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4206|       |                              }
 4207|       |                              if (bool(ctx.error)) [[unlikely]]
 4208|       |                                 return;
 4209|       |                              if (skip_ws<Opts>(ctx, it, end)) {
 4210|       |                                 return;
 4211|       |                              }
 4212|       |                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
 4213|       |                                 ctx.error = error_code::syntax_error;
 4214|       |                                 return;
 4215|       |                              }
 4216|       |
 4217|       |                              size_t type_index;
 4218|       |                              if constexpr (std::integral<id_type>) {
 4219|       |                                 type_index = variant_id_to_index<T>::op(type_id);
 4220|       |                              }
 4221|       |                              else {
 4222|       |                                 type_index = variant_id_to_index<T>::op(
 4223|       |                                    type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4224|       |                              }
 4225|       |                              if (type_index < ids_v<T>.size()) [[likely]] {
 4226|       |                                 // Check if the deduced types include the tag-specified type
 4227|       |                                 // If not, the tag doesn't match the fields
 4228|       |                                 // We're already inside if constexpr (deduction_registry.size()), so we know deduction
 4229|       |                                 // is happening. At this point, possible_types has been narrowed by field deduction.
 4230|       |                                 // Check if the tag-specified type is still possible
 4231|       |                                 const bool type_is_possible = possible_types[type_index];
 4232|       |                                 if (!type_is_possible) {
 4233|       |                                    // Tag specifies a type that doesn't match the fields seen so far
 4234|       |                                    ctx.error = error_code::no_matching_variant_type;
 4235|       |                                    return;
 4236|       |                                 }
 4237|       |
 4238|       |                                 if (!position_after_tag()) return;
 4239|       |                                 tag_specified_index = type_index; // Store the tag-specified type
 4240|       |                                 if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4241|       |                                 std::visit(
 4242|       |                                    [&](auto&& v) {
 4243|       |                                       using V = std::decay_t<decltype(v)>;
 4244|       |                                       constexpr bool is_object =
 4245|       |                                          (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4246|       |                                       if constexpr (variant_unit_alternative<V>) {
 4247|       |                                          // A unit alternative carries no data; its object holds only the
 4248|       |                                          // discriminator. Consume that body through an empty reflected object so
 4249|       |                                          // unknown-key policy and terminator handling match every other alternative.
 4250|       |                                          detail::variant_unit_body unit_body{};
 4251|       |                                          from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4252|       |                                                                                             tag_literal>(unit_body,
 4253|       |                                                                                                          ctx, it, end);
 4254|       |                                       }
 4255|       |                                       else if constexpr (is_object) {
 4256|       |                                          if constexpr (contains_tag<V, tag_literal>()) {
 4257|       |                                             // tag is a struct field, must re-parse
 4258|       |                                             if (!start.rewind(ctx, it, end)) return;
 4259|       |                                          }
 4260|       |                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
 4261|       |                                                                                                           end);
 4262|       |                                       }
 4263|       |                                       else if constexpr (is_memory_object<V>) {
 4264|       |                                          if (!v) {
 4265|       |                                             if constexpr (is_specialization_v<V, std::optional>) {
 4266|       |                                                if constexpr (requires { v.emplace(); }) {
 4267|       |                                                   v.emplace();
 4268|       |                                                }
 4269|       |                                                else {
 4270|       |                                                   v = typename V::value_type{};
 4271|       |                                                }
 4272|       |                                             }
 4273|       |                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4274|       |                                                v = std::make_unique<typename V::element_type>();
 4275|       |                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4276|       |                                                v = std::make_shared<typename V::element_type>();
 4277|       |                                             else if constexpr (constructible<V>) {
 4278|       |                                                v = meta_construct_v<V>();
 4279|       |                                             }
 4280|       |                                             else if constexpr (std::is_pointer_v<V> &&
 4281|       |                                                                can_allocate_raw_pointer<Opts,
 4282|       |                                                                                         std::decay_t<decltype(ctx)>>) {
 4283|       |                                                if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4284|       |                                                   return;
 4285|       |                                                }
 4286|       |                                             }
 4287|       |                                             else {
 4288|       |                                                ctx.error = error_code::invalid_nullable_read;
 4289|       |                                                return;
 4290|       |                                                // Cannot read into unset nullable that is not std::optional,
 4291|       |                                                // std::unique_ptr, or std::shared_ptr
 4292|       |                                             }
 4293|       |                                          }
 4294|       |                                          if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4295|       |                                             // tag is a struct field, must re-parse
 4296|       |                                             if (!start.rewind(ctx, it, end)) return;
 4297|       |                                          }
 4298|       |                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4299|       |                                             *v, ctx, it, end);
 4300|       |                                       }
 4301|       |                                       else if constexpr (custom_read<V>) {
 4302|       |                                          // Custom handlers parse the remaining body themselves and do not
 4303|       |                                          // accept the tag template parameter; the tag was already consumed.
 4304|       |                                          // This only works when the tag was the first key. If it came later,
 4305|       |                                          // we were reset to the object start and the custom handler would
 4306|       |                                          // absorb the tag, so error rather than corrupt the value.
 4307|       |                                          if (!first_key) {
 4308|       |                                             ctx.error = error_code::feature_not_supported;
 4309|       |                                             ctx.custom_error_message =
 4310|       |                                                "the tag must be the first key for a custom variant alternative";
 4311|       |                                             return;
 4312|       |                                          }
 4313|       |                                          from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4314|       |                                       }
 4315|       |                                    },
 4316|       |                                    value);
 4317|       |
 4318|       |                                 return; // we've decoded our target type
 4319|       |                              }
 4320|       |                              else [[unlikely]] {
 4321|       |                                 // Check if we have a default type (ids array shorter than variant)
 4322|       |                                 constexpr auto ids_size = ids_v<T>.size();
 4323|       |                                 constexpr auto variant_size = std::variant_size_v<T>;
 4324|       |                                 if constexpr (ids_size < variant_size) {
 4325|       |                                    // Use the first unlabeled type as the default
 4326|       |                                    const auto default_type_index = ids_size;
 4327|       |
 4328|       |                                    if (!position_after_tag()) return;
 4329|       |                                    tag_specified_index = default_type_index; // Store the default type index
 4330|       |                                    if (value.index() != default_type_index)
 4331|       |                                       emplace_runtime_variant(value, default_type_index);
 4332|       |                                    std::visit(
 4333|       |                                       [&](auto&& v) {
 4334|       |                                          using V = std::decay_t<decltype(v)>;
 4335|       |                                          constexpr bool is_object =
 4336|       |                                             (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4337|       |                                          if constexpr (variant_unit_alternative<V>) {
 4338|       |                                             // A unit alternative carries no data; its object holds only the
 4339|       |                                             // discriminator. Consume that body through an empty reflected object so
 4340|       |                                             // unknown-key policy and terminator handling match every other
 4341|       |                                             // alternative.
 4342|       |                                             detail::variant_unit_body unit_body{};
 4343|       |                                             from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4344|       |                                                                                                tag_literal>(
 4345|       |                                                unit_body, ctx, it, end);
 4346|       |                                          }
 4347|       |                                          else if constexpr (is_object) {
 4348|       |                                             if constexpr (contains_tag<V, tag_literal>()) {
 4349|       |                                                // tag is a struct field, must re-parse
 4350|       |                                                if (!start.rewind(ctx, it, end)) return;
 4351|       |                                             }
 4352|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4353|       |                                          }
 4354|       |                                          else if constexpr (is_memory_object<V>) {
 4355|       |                                             if (!v) {
 4356|       |                                                if constexpr (is_specialization_v<V, std::optional>) {
 4357|       |                                                   if constexpr (requires { v.emplace(); }) {
 4358|       |                                                      v.emplace();
 4359|       |                                                   }
 4360|       |                                                   else {
 4361|       |                                                      v = typename V::value_type{};
 4362|       |                                                   }
 4363|       |                                                }
 4364|       |                                                else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4365|       |                                                   v = std::make_unique<typename V::element_type>();
 4366|       |                                                else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4367|       |                                                   v = std::make_shared<typename V::element_type>();
 4368|       |                                                else if constexpr (constructible<V>) {
 4369|       |                                                   v = meta_construct_v<V>();
 4370|       |                                                }
 4371|       |                                                else if constexpr (std::is_pointer_v<V> &&
 4372|       |                                                                   can_allocate_raw_pointer<
 4373|       |                                                                      Opts, std::decay_t<decltype(ctx)>>) {
 4374|       |                                                   if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4375|       |                                                      return;
 4376|       |                                                   }
 4377|       |                                                }
 4378|       |                                                else {
 4379|       |                                                   ctx.error = error_code::invalid_nullable_read;
 4380|       |                                                   return;
 4381|       |                                                }
 4382|       |                                             }
 4383|       |                                             if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4384|       |                                                // tag is a struct field, must re-parse
 4385|       |                                                if (!start.rewind(ctx, it, end)) return;
 4386|       |                                             }
 4387|       |                                             from<JSON, memory_type<V>>::template op<opening_handled<Opts>()>(*v, ctx,
 4388|       |                                                                                                              it, end);
 4389|       |                                          }
 4390|       |                                          else if constexpr (custom_read<V>) {
 4391|       |                                             // Custom handlers parse the remaining body themselves; this only
 4392|       |                                             // works when the tag was the first key (see above). If it came
 4393|       |                                             // later we were reset to the object start, so error rather than
 4394|       |                                             // let the custom handler absorb the tag.
 4395|       |                                             if (!first_key) {
 4396|       |                                                ctx.error = error_code::feature_not_supported;
 4397|       |                                                ctx.custom_error_message =
 4398|       |                                                   "the tag must be the first key for a custom variant alternative";
 4399|       |                                                return;
 4400|       |                                             }
 4401|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4402|       |                                          }
 4403|       |                                       },
 4404|       |                                       value);
 4405|       |
 4406|       |                                    return;
 4407|       |                                 }
 4408|       |                                 else {
 4409|       |                                    ctx.error = error_code::no_matching_variant_type;
 4410|       |                                    ctx.custom_error_message = variant_ids_string_v<T>;
 4411|       |                                    return;
 4412|       |                                 }
 4413|       |                              }
 4414|       |                           }
 4415|       |                        }
 4416|       |
 4417|       |                        // Inline decode_hash lookup for variant deduction
 4418|       |                        using deduction_keys_t = keys_wrapper<variant_deduction_keys<T>>;
 4419|       |                        constexpr auto& DeductionHashInfo = hash_info<deduction_keys_t>;
 4420|       |                        const auto deduction_index =
 4421|       |                           decode_hash_with_size<JSON, deduction_keys_t, DeductionHashInfo, DeductionHashInfo.type>::op(
 4422|       |                              key.data(), key.data() + key.size(), key.size());
 4423|       |                        if (deduction_index < deduction_key_count && variant_deduction_keys<T>[deduction_index] == key)
 4424|       |                           [[likely]] {
 4425|       |                           possible_types &= deduction_bits[deduction_index];
 4426|       |                        }
 4427|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4428|       |                           ctx.error = error_code::unknown_key;
 4429|       |                           return;
 4430|       |                        }
 4431|       |                     }
 4432|       |                     else if constexpr (not tag_v<T>.empty()) {
 4433|       |                        // empty object case for variant, if there are no normal elements
 4434|       |                        if (key == tag_v<T>) {
 4435|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4436|       |                              return;
 4437|       |                           }
 4438|       |
 4439|       |                           // The id is turned into an index below and never leaves this reader,
 4440|       |                           // so the view of the window it borrows cannot outlive that window.
 4441|       |                           std::string_view type_id{};
 4442|       |                           parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4443|       |                           if (bool(ctx.error)) [[unlikely]]
 4444|       |                              return;
 4445|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4446|       |                              return;
 4447|       |                           }
 4448|       |
 4449|       |                           const auto type_index = variant_id_to_index<T>::op(
 4450|       |                              type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4451|       |                           if (type_index < ids_v<T>.size()) [[likely]] {
 4452|       |                              if (!position_after_tag()) return;
 4453|       |                              tag_specified_index = type_index; // Store the tag-specified type
 4454|       |                              if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4455|       |                           }
 4456|       |                           else {
 4457|       |                              // Check if we have a default type (ids array shorter than variant)
 4458|       |                              constexpr auto ids_size = ids_v<T>.size();
 4459|       |                              constexpr auto variant_size = std::variant_size_v<T>;
 4460|       |                              if constexpr (ids_size < variant_size) {
 4461|       |                                 // Use the first unlabeled type as the default
 4462|       |                                 if (!position_after_tag()) return;
 4463|       |                                 const auto default_index = ids_size;
 4464|       |                                 tag_specified_index = default_index; // Store the default type index
 4465|       |                                 if (value.index() != default_index) emplace_runtime_variant(value, default_index);
 4466|       |                              }
 4467|       |                              else {
 4468|       |                                 ctx.error = error_code::no_matching_variant_type;
 4469|       |                                 ctx.custom_error_message = variant_ids_string_v<T>;
 4470|       |                                 return;
 4471|       |                              }
 4472|       |                           }
 4473|       |                           // Parse the type (handles tag skipping and unknown keys)
 4474|       |                           std::visit(
 4475|       |                              [&](auto&& v) {
 4476|       |                                 using V = std::decay_t<decltype(v)>;
 4477|       |                                 if constexpr (custom_read<V>) {
 4478|       |                                    // Custom handlers parse the remaining object body themselves and do not
 4479|       |                                    // accept the tag template parameter that reflected objects use to skip an
 4480|       |                                    // interior tag key. That only works when the tag is the first key (it was
 4481|       |                                    // just consumed). If the tag came after other keys, position_after_tag()
 4482|       |                                    // reset us to the object start and the custom handler would absorb the tag
 4483|       |                                    // into its value, so error here rather than corrupt the result.
 4484|       |                                    if (!first_key) {
 4485|       |                                       ctx.error = error_code::feature_not_supported;
 4486|       |                                       ctx.custom_error_message =
 4487|       |                                          "the tag must be the first key for a custom variant alternative";
 4488|       |                                       return;
 4489|       |                                    }
 4490|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4491|       |                                 }
 4492|       |                                 else {
 4493|       |                                    if constexpr (contains_tag<V, tag_literal>()) {
 4494|       |                                       // tag is a struct field, must re-parse
 4495|       |                                       if (!start.rewind(ctx, it, end)) return;
 4496|       |                                    }
 4497|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4498|       |                                 }
 4499|       |                              },
 4500|       |                              value);
 4501|       |                           return;
 4502|       |                        }
 4503|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4504|       |                           ctx.error = error_code::unknown_key;
 4505|       |                           return;
 4506|       |                        }
 4507|       |                        else {
 4508|       |                           // Skip unknown key's value (non-tag key in empty variant)
 4509|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4510|       |                              return;
 4511|       |                           }
 4512|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 4513|       |                           if (bool(ctx.error)) [[unlikely]]
 4514|       |                              return;
 4515|       |                           resync_window_end(ctx, end); // a streaming skip refills
 4516|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4517|       |                              return;
 4518|       |                           }
 4519|       |                           continue; // Continue loop to find the tag
 4520|       |                        }
 4521|       |                     }
 4522|       |                     else if constexpr (Opts.error_on_unknown_keys) {
 4523|       |                        ctx.error = error_code::unknown_key;
 4524|       |                        return;
 4525|       |                     }
 4526|       |
 4527|       |                     auto matching_types = possible_types.popcount();
 4528|       |                     if (matching_types == 0) {
 4529|       |                        ctx.error = error_code::no_matching_variant_type;
 4530|       |                        return;
 4531|       |                     }
 4532|       |                     // Only short-circuit for variants without tags
 4533|       |                     else if constexpr (tag_v<T>.empty()) {
 4534|       |                        if (matching_types == 1) {
 4535|       |                           if (!start.rewind(ctx, it, end)) return;
 4536|       |                           const auto type_index = possible_types.countr_zero();
 4537|       |
 4538|       |                           if (value.index() != static_cast<size_t>(type_index))
 4539|       |                              emplace_runtime_variant(value, type_index);
 4540|       |                           std::visit(
 4541|       |                              [&](auto&& v) {
 4542|       |                                 using V = std::decay_t<decltype(v)>;
 4543|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4544|       |                                 if constexpr (variant_unit_alternative<V>) {
 4545|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4546|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4547|       |                                    // terminator handling match every other alternative.
 4548|       |                                    detail::variant_unit_body unit_body{};
 4549|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4550|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4551|       |                                                                                                    end);
 4552|       |                                 }
 4553|       |                                 else if constexpr (is_object) {
 4554|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4555|       |                                 }
 4556|       |                                 else if constexpr (is_memory_object<V>) {
 4557|       |                                    if (!v) {
 4558|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4559|       |                                          if constexpr (requires { v.emplace(); }) {
 4560|       |                                             v.emplace();
 4561|       |                                          }
 4562|       |                                          else {
 4563|       |                                             v = typename V::value_type{};
 4564|       |                                          }
 4565|       |                                       }
 4566|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4567|       |                                          v = std::make_unique<typename V::element_type>();
 4568|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4569|       |                                          v = std::make_shared<typename V::element_type>();
 4570|       |                                       else if constexpr (constructible<V>) {
 4571|       |                                          v = meta_construct_v<V>();
 4572|       |                                       }
 4573|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4574|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4575|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4576|       |                                             return;
 4577|       |                                          }
 4578|       |                                       }
 4579|       |                                       else {
 4580|       |                                          ctx.error = error_code::invalid_nullable_read;
 4581|       |                                          return;
 4582|       |                                          // Cannot read into unset nullable that is not std::optional,
 4583|       |                                          // std::unique_ptr, or std::shared_ptr
 4584|       |                                       }
 4585|       |                                    }
 4586|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4587|       |                                       *v, ctx, it, end);
 4588|       |                                 }
 4589|       |                                 else if constexpr (custom_read<V>) {
 4590|       |                                    // Custom handlers parse the remaining body themselves.
 4591|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4592|       |                                 }
 4593|       |                              },
 4594|       |                              value);
 4595|       |
 4596|       |                           return; // we've decoded our target type
 4597|       |                        }
 4598|       |                     }
 4599|       |                     // For tagged variants, continue processing to validate tags
 4600|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 4601|       |                        return;
 4602|       |                     }
 4603|       |
 4604|       |                     skip_value<JSON>::op<Opts>(ctx, it, end);
 4605|       |                     if (bool(ctx.error)) [[unlikely]]
 4606|       |                        return;
 4607|       |                     resync_window_end(ctx, end); // a streaming skip refills
 4608|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4609|       |                        return;
 4610|       |                     }
 4611|       |                  }
 4612|       |                  // Only apply ambiguous variant resolution if we have multiple object types
 4613|       |                  if constexpr ((type_counts::n_object + type_counts::n_nullable_object) > 1) {
 4614|       |                     // After parsing all keys, check if we have multiple matching types
 4615|       |                     // If so, choose the one with the fewest fields
 4616|       |                     auto final_matching = possible_types.popcount();
 4617|       |                     if (final_matching == 0) {
 4618|       |                        ctx.error = error_code::no_matching_variant_type;
 4619|       |                     }
 4620|       |                     else if (final_matching == 1) {
 4621|       |                        // Single type remains after field deduction
 4622|       |                        const auto type_index = possible_types.countr_zero();
 4623|       |
 4624|       |                        // Validate against tag if one was specified
 4625|       |                        if (tag_specified_index.has_value() &&
 4626|       |                            tag_specified_index.value() != static_cast<size_t>(type_index)) {
 4627|       |                           ctx.error = error_code::no_matching_variant_type;
 4628|       |                           return;
 4629|       |                        }
 4630|       |
 4631|       |                        if (!start.rewind(ctx, it, end)) return;
 4632|       |                        if (value.index() != static_cast<size_t>(type_index))
 4633|       |                           emplace_runtime_variant(value, type_index);
 4634|       |                        std::visit(
 4635|       |                           [&](auto&& v) {
 4636|       |                              using V = std::decay_t<decltype(v)>;
 4637|       |                              constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4638|       |                              if constexpr (variant_unit_alternative<V>) {
 4639|       |                                 // A unit alternative carries no data; its object holds only the discriminator.
 4640|       |                                 // Consume that body through an empty reflected object so unknown-key policy and
 4641|       |                                 // terminator handling match every other alternative.
 4642|       |                                 detail::variant_unit_body unit_body{};
 4643|       |                                 from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4644|       |                                                                                    tag_literal>(unit_body, ctx, it,
 4645|       |                                                                                                 end);
 4646|       |                              }
 4647|       |                              else if constexpr (is_object) {
 4648|       |                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4649|       |                              }
 4650|       |                              else if constexpr (is_memory_object<V>) {
 4651|       |                                 if (!v) {
 4652|       |                                    if constexpr (is_specialization_v<V, std::optional>) {
 4653|       |                                       if constexpr (requires { v.emplace(); }) {
 4654|       |                                          v.emplace();
 4655|       |                                       }
 4656|       |                                       else {
 4657|       |                                          v = typename V::value_type{};
 4658|       |                                       }
 4659|       |                                    }
 4660|       |                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4661|       |                                       v = std::make_unique<typename V::element_type>();
 4662|       |                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4663|       |                                       v = std::make_shared<typename V::element_type>();
 4664|       |                                    else if constexpr (constructible<V>) {
 4665|       |                                       v = meta_construct_v<V>();
 4666|       |                                    }
 4667|       |                                    else if constexpr (std::is_pointer_v<V> &&
 4668|       |                                                       can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4669|       |                                       if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4670|       |                                          return;
 4671|       |                                       }
 4672|       |                                    }
 4673|       |                                    else {
 4674|       |                                       ctx.error = error_code::invalid_nullable_read;
 4675|       |                                       return;
 4676|       |                                    }
 4677|       |                                 }
 4678|       |                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
 4679|       |                                                                                                               it, end);
 4680|       |                              }
 4681|       |                              else if constexpr (custom_read<V>) {
 4682|       |                                 // Custom handlers parse the remaining body themselves.
 4683|       |                                 from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4684|       |                              }
 4685|       |                           },
 4686|       |                           value);
 4687|       |                     }
 4688|       |                     else if (final_matching > 1) {
 4689|       |                        constexpr auto N = std::variant_size_v<T>;
 4690|       |
 4691|       |                        // Compile-time array of field counts for each variant type
 4692|       |                        constexpr auto field_counts = []<size_t... I>(std::index_sequence<I...>) {
 4693|       |                           return std::array<size_t, N> {
 4694|       |                              ([]<size_t J = I>() -> size_t {
 4695|       |                                 using V = std::decay_t<std::variant_alternative_t<J, T>>;
 4696|       |                                 if constexpr (glaze_object_t<V> || reflectable<V>) {
 4697|       |                                    return reflect<V>::size;
 4698|       |                                 }
 4699|       |                                 else if constexpr (is_memory_object<V>) {
 4700|       |                                    using X = memory_type<V>;
 4701|       |                                    if constexpr (glaze_object_t<X> || reflectable<X>) {
 4702|       |                                       return reflect<X>::size;
 4703|       |                                    }
 4704|       |                                    else {
 4705|       |                                       return (std::numeric_limits<size_t>::max)();
 4706|       |                                    }
 4707|       |                                 }
 4708|       |                                 else {
 4709|       |                                    return (std::numeric_limits<size_t>::max)();
 4710|       |                                 }
 4711|       |                              }.template operator()<I>())...
 4712|       |                           };
 4713|       |                        }(std::make_index_sequence<N>{});
 4714|       |
 4715|       |                        // Find the type with minimum field count among the possible types
 4716|       |                        size_t min_fields = (std::numeric_limits<size_t>::max)();
 4717|       |                        size_t chosen_index = N; // Invalid index initially
 4718|       |
 4719|       |                        for (size_t i = 0; i < N; ++i) {
 4720|       |                           if (possible_types[i] && field_counts[i] < min_fields) {
 4721|       |                              min_fields = field_counts[i];
 4722|       |                              chosen_index = i;
 4723|       |                           }
 4724|       |                        }
 4725|       |
 4726|       |                        if (chosen_index < N) {
 4727|       |                           // Validate against tag if one was specified
 4728|       |                           if (tag_specified_index.has_value() && tag_specified_index.value() != chosen_index) {
 4729|       |                              ctx.error = error_code::no_matching_variant_type;
 4730|       |                              return;
 4731|       |                           }
 4732|       |
 4733|       |                           if (!start.rewind(ctx, it, end)) return;
 4734|       |                           if (value.index() != chosen_index) emplace_runtime_variant(value, chosen_index);
 4735|       |                           std::visit(
 4736|       |                              [&](auto&& v) {
 4737|       |                                 using V = std::decay_t<decltype(v)>;
 4738|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4739|       |                                 if constexpr (variant_unit_alternative<V>) {
 4740|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4741|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4742|       |                                    // terminator handling match every other alternative.
 4743|       |                                    detail::variant_unit_body unit_body{};
 4744|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4745|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4746|       |                                                                                                    end);
 4747|       |                                 }
 4748|       |                                 else if constexpr (is_object) {
 4749|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4750|       |                                 }
 4751|       |                                 else if constexpr (is_memory_object<V>) {
 4752|       |                                    if (!v) {
 4753|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4754|       |                                          if constexpr (requires { v.emplace(); }) {
 4755|       |                                             v.emplace();
 4756|       |                                          }
 4757|       |                                          else {
 4758|       |                                             v = typename V::value_type{};
 4759|       |                                          }
 4760|       |                                       }
 4761|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4762|       |                                          v = std::make_unique<typename V::element_type>();
 4763|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4764|       |                                          v = std::make_shared<typename V::element_type>();
 4765|       |                                       else if constexpr (constructible<V>) {
 4766|       |                                          v = meta_construct_v<V>();
 4767|       |                                       }
 4768|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4769|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4770|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4771|       |                                             return;
 4772|       |                                          }
 4773|       |                                       }
 4774|       |                                       else {
 4775|       |                                          ctx.error = error_code::invalid_nullable_read;
 4776|       |                                          return;
 4777|       |                                       }
 4778|       |                                    }
 4779|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4780|       |                                       *v, ctx, it, end);
 4781|       |                                 }
 4782|       |                                 else if constexpr (custom_read<V>) {
 4783|       |                                    // Custom handlers parse the remaining body themselves.
 4784|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4785|       |                                 }
 4786|       |                              },
 4787|       |                              value);
 4788|       |                        }
 4789|       |                        else {
 4790|       |                           ctx.error = error_code::no_matching_variant_type;
 4791|       |                        }
 4792|       |                     }
 4793|       |                  }
 4794|       |                  else {
 4795|       |                     // For variants with 0 or 1 object types, use the original error handling
 4796|       |                     ctx.error = error_code::no_matching_variant_type;
 4797|       |                  }
 4798|       |               }
 4799|      0|               break;
 4800|  22.4k|            }
 4801|   596k|            case '[':
  ------------------
  |  Branch (4801:13): [True: 596k, False: 2.21M]
  ------------------
 4802|       |               // As with '{' above: the array reader each alternative goes through counts the level.
 4803|   596k|               process_variant_alternatives<T, is_variant_array>::template op<Opts>(value, ctx, it, end);
 4804|   596k|               break;
 4805|  5.11k|            case '"': {
  ------------------
  |  Branch (4805:13): [True: 5.11k, False: 2.80M]
  ------------------
 4806|  5.11k|               process_variant_alternatives<T, is_variant_str>::template op<Opts>(value, ctx, it, end);
 4807|  5.11k|               break;
 4808|  22.4k|            }
 4809|    902|            case 't':
  ------------------
  |  Branch (4809:13): [True: 902, False: 2.81M]
  ------------------
 4810|  1.19k|            case 'f': {
  ------------------
  |  Branch (4810:13): [True: 297, False: 2.81M]
  ------------------
 4811|  1.19k|               process_variant_alternatives<T, is_variant_bool>::template op<Opts>(value, ctx, it, end);
 4812|  1.19k|               break;
 4813|    902|            }
 4814|    584|            case 'n':
  ------------------
  |  Branch (4814:13): [True: 584, False: 2.81M]
  ------------------
 4815|       |               if constexpr (variant_count_v<T, is_variant_null> == 0) {
 4816|       |                  ctx.error = error_code::no_matching_variant_type;
 4817|       |               }
 4818|    584|               else {
 4819|    584|                  constexpr auto first_idx = variant_first_index_v<T, is_variant_null>;
 4820|    584|                  using V = std::variant_alternative_t<first_idx, T>;
 4821|    584|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4821:23): [True: 199, False: 385]
  ------------------
 4822|    584|                  match<"null", Opts>(ctx, it, end);
 4823|    584|               }
 4824|    584|               break;
 4825|  2.18M|            default: {
  ------------------
  |  Branch (4825:13): [True: 2.18M, False: 625k]
  ------------------
 4826|       |               // Not bool, string, object, or array so must be number or null
 4827|  2.18M|               process_variant_alternatives<T, is_variant_num>::template op<Opts>(value, ctx, it, end);
 4828|  2.18M|            }
 4829|  2.81M|            }
 4830|       |         }
 4831|       |         else {
 4832|       |            // For non-auto-deducible variants, try each type until one succeeds
 4833|       |            constexpr auto N = std::variant_size_v<T>;
 4834|       |            bool parsed = false;
 4835|       |            bool exhausted = false; // speculation budget spent; see charge_speculation
 4836|       |
 4837|       |            for_each<N>([&]<size_t I>() {
 4838|       |               if (parsed || exhausted || variant_alternative_exhausted(ctx)) return;
 4839|       |
 4840|       |               auto copy_it = it;
 4841|       |               // A rejected alternative may have bailed out inside a container, which leaves its
 4842|       |               // nesting level counted (see enter_depth), so the depth rewinds with the iterator.
 4843|       |               const auto copy_depth = ctx.depth;
 4844|       |
 4845|       |               // Try parsing as this type
 4846|       |               if (value.index() != I) {
 4847|       |                  emplace_runtime_variant(value, I);
 4848|       |               }
 4849|       |
 4850|       |               std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
 4851|       |               if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 4852|       |                  exhausted = true; // only rejected attempts are charged; see charge_speculation
 4853|       |               }
 4854|       |
 4855|       |               if (!bool(ctx.error)) {
 4856|       |                  parsed = true;
 4857|       |               }
 4858|       |               else if constexpr (not Options.null_terminated) {
 4859|       |                  // In non-null-terminated mode, if we hit end_reached after advancing the iterator,
 4860|       |                  // it means we successfully parsed the value but couldn't skip trailing whitespace
 4861|       |                  if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 4862|       |                     // We advanced the iterator, so we did parse something -- unless what advanced it
 4863|       |                     // was an abandoned attempt, which is what a spent speculation budget means.
 4864|       |                     parsed = true;
 4865|       |                     ctx.error = error_code::none;
 4866|       |                  }
 4867|       |                  else {
 4868|       |                     // Reset for next attempt (unless this is the last type)
 4869|       |                     it = copy_it;
 4870|       |                     rewind_depth<Options>(ctx, copy_depth);
 4871|       |                     if constexpr (I + 1 < N) {
 4872|       |                        if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4873|       |                           ctx.error = error_code::none; // Clear error for next attempt
 4874|       |                        }
 4875|       |                     }
 4876|       |                  }
 4877|       |               }
 4878|       |               else {
 4879|       |                  // Reset for next attempt (unless this is the last type)
 4880|       |                  it = copy_it;
 4881|       |                  rewind_depth<Options>(ctx, copy_depth);
 4882|       |                  if constexpr (I + 1 < N) {
 4883|       |                     if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4884|       |                        ctx.error = error_code::none; // Clear error for next attempt
 4885|       |                     }
 4886|       |                  }
 4887|       |               }
 4888|       |            });
 4889|       |         }
 4890|  2.81M|      }
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|   598k|      {
 3726|   598k|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|   598k|         else {
 3732|   598k|            constexpr auto N = std::variant_size_v<Variant>;
 3733|   598k|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|   598k|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|   598k|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|   598k|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|   598k|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|   598k|               size_t non_const_idx = 0;
 3793|       |
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|   598k|                     return;
 3797|   598k|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|   598k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|   598k|                     auto copy_it{it};
 3801|   598k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|   598k|                     if (!std::holds_alternative<V>(value)) {
 3803|   598k|                        value = V{};
 3804|   598k|                     }
 3805|   598k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|   598k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|   598k|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|   598k|                     }
 3809|   598k|                     if (!bool(ctx.error)) {
 3810|   598k|                        found_match = true;
 3811|   598k|                     }
 3812|   598k|                     else if constexpr (not Options.null_terminated) {
 3813|   598k|                        constexpr bool is_complete_type =
 3814|   598k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|   598k|                        if constexpr (is_complete_type) {
 3817|   598k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|   598k|                              found_match = true;
 3819|   598k|                              ctx.error = error_code::none;
 3820|   598k|                           }
 3821|   598k|                           else {
 3822|   598k|                              it = copy_it;
 3823|   598k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|   598k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|   598k|                                  not variant_alternative_exhausted(ctx)) {
 3826|   598k|                                 ctx.error = error_code::none;
 3827|   598k|                              }
 3828|   598k|                           }
 3829|   598k|                        }
 3830|   598k|                        else {
 3831|   598k|                           it = copy_it;
 3832|   598k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|   598k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|   598k|                               not variant_alternative_exhausted(ctx)) {
 3835|   598k|                              ctx.error = error_code::none;
 3836|   598k|                           }
 3837|   598k|                        }
 3838|   598k|                     }
 3839|   598k|                     else {
 3840|   598k|                        it = copy_it;
 3841|   598k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|   598k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|   598k|                            not variant_alternative_exhausted(ctx)) {
 3844|   598k|                           ctx.error = error_code::none;
 3845|   598k|                        }
 3846|   598k|                     }
 3847|   598k|                     ++non_const_idx;
 3848|   598k|                  }
 3849|   598k|               });
 3850|   598k|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 13.1k, False: 585k]
  ------------------
 3851|  13.1k|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|  13.1k|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|   598k|         }
 3864|   598k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZN3glz29variant_alternative_exhaustedITkNS_10is_contextENS_7contextEEEbRT_:
 3714|  22.2M|   {
 3715|  22.2M|      return ctx.error == error_code::exceeded_max_recursive_depth;
 3716|  22.2M|   }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|   598k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|   598k|                     auto copy_it{it};
 3801|   598k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|   598k|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 471k, False: 126k]
  ------------------
 3803|   471k|                        value = V{};
 3804|   471k|                     }
 3805|   598k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|   598k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 13.1k, False: 585k]
  |  Branch (3806:45): [True: 0, False: 13.1k]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|   598k|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 585k, False: 13.1k]
  ------------------
 3810|   585k|                        found_match = true;
 3811|   585k|                     }
 3812|  13.1k|                     else if constexpr (not Options.null_terminated) {
 3813|  13.1k|                        constexpr bool is_complete_type =
 3814|  13.1k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
  ------------------
  |  Branch (3814:28): [Folded, False: 0]
  |  Branch (3814:40): [Folded, False: 0]
  |  Branch (3814:53): [Folded, False: 0]
  |  Branch (3814:68): [Folded, False: 0]
  |  Branch (3814:89): [Folded, False: 0]
  |  Branch (3814:103): [Folded, False: 0]
  ------------------
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|  13.1k|                        else {
 3831|  13.1k|                           it = copy_it;
 3832|  13.1k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  13.1k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3833:32): [True: 0, False: 13.1k]
  |  Branch (3833:71): [True: 0, False: 0]
  ------------------
 3834|      0|                               not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3834:32): [True: 0, False: 0]
  ------------------
 3835|      0|                              ctx.error = error_code::none;
 3836|      0|                           }
 3837|  13.1k|                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|   598k|                     ++non_const_idx;
 3848|   598k|                  }
 3849|   598k|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERNSt3__16vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS4_9allocatorIS9_EEEETkNS_10is_contextERNS_7contextERPKcSH_EEvOT0_OT1_OT2_T3_:
   49|   598k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|   598k|         else {
   60|   598k|            using V = std::remove_cvref_t<T>;
   61|   598k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|   598k|                                             end);
   63|   598k|         }
   64|   598k|      }
_ZN3glz4fromILj10ENSt3__16vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS1_9allocatorIS6_EEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERS9_TkNS_10is_contextERNS_7contextERPKcSH_EEvOT0_OT1_OT2_T3_:
 2308|   598k|      {
 2309|   598k|         constexpr auto Opts = ws_handled_off<Options>();
 2310|       |         if constexpr (!check_ws_handled(Options)) {
 2311|       |            if (skip_ws<Opts>(ctx, it, end)) {
 2312|       |               return;
 2313|       |            }
 2314|       |         }
 2315|       |
 2316|   598k|         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2316:14): [True: 114, False: 598k]
  ------------------
 2317|    114|            return;
 2318|    114|         }
 2319|       |         // one nesting level (see enter_depth): counted in both modes so the limit binds,
 2320|       |         // released at each syntactic close below
 2321|   598k|         if (enter_depth(ctx)) [[unlikely]] {
  ------------------
  |  Branch (2321:14): [True: 4, False: 598k]
  ------------------
 2322|      4|            return;
 2323|      4|         }
 2324|       |
 2325|   598k|         const auto ws_start = it;
 2326|   598k|         if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2326:14): [True: 57, False: 598k]
  ------------------
 2327|     57|            return;
 2328|     57|         }
 2329|       |
 2330|   598k|         if (*it == ']') {
  ------------------
  |  Branch (2330:14): [True: 7.36k, False: 590k]
  ------------------
 2331|  7.36k|            --ctx.depth;
 2332|  7.36k|            ++it;
 2333|  7.36k|            if constexpr ((resizable<T> || is_inplace_vector<T>) && not check_append_arrays(Opts)) {
 2334|  7.36k|               value.clear();
 2335|       |
 2336|       |               if constexpr (check_shrink_to_fit(Opts) && has_shrink_to_fit<T>) {
 2337|       |                  value.shrink_to_fit();
 2338|       |               }
 2339|  7.36k|            }
 2340|  7.36k|            return;
 2341|  7.36k|         }
 2342|       |
 2343|   590k|         const size_t ws_size = size_t(it - ws_start);
 2344|       |
 2345|   590k|         static constexpr bool should_append = (resizable<T> || is_inplace_vector<T>) && check_append_arrays(Opts);
  ------------------
  |  Branch (2345:49): [True: 590k, Folded]
  |  Branch (2345:65): [Folded, False: 0]
  |  Branch (2345:90): [Folded, False: 0]
  ------------------
 2346|   590k|         if constexpr (not should_append) {
 2347|   590k|            const auto n = value.size();
 2348|       |
 2349|   590k|            auto value_it = value.begin();
 2350|       |
 2351|   597k|            for (size_t i = 0; i < n; ++i) {
  ------------------
  |  Branch (2351:32): [True: 130k, False: 466k]
  ------------------
 2352|   130k|               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
 2353|   130k|               if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (2353:20): [True: 739, False: 129k]
  ------------------
 2354|    739|                  return;
 2355|   129k|               if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2355:20): [True: 45, False: 129k]
  ------------------
 2356|     45|                  return;
 2357|     45|               }
 2358|   129k|               if (*it == ',') {
  ------------------
  |  Branch (2358:20): [True: 6.36k, False: 123k]
  ------------------
 2359|  6.36k|                  ++it;
 2360|       |
 2361|  6.36k|                  if constexpr (!Opts.minified && !Opts.comments) {
 2362|  6.36k|                     if (ws_size && ws_size < size_t(end - it)) {
  ------------------
  |  Branch (2362:26): [True: 3.46k, False: 2.90k]
  |  Branch (2362:37): [True: 2.83k, False: 625]
  ------------------
 2363|  2.83k|                        skip_matching_ws(ws_start, it, ws_size);
 2364|  2.83k|                     }
 2365|  6.36k|                  }
 2366|       |
 2367|  6.36k|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2367:23): [True: 104, False: 6.25k]
  ------------------
 2368|    104|                     return;
 2369|    104|                  }
 2370|  6.36k|               }
 2371|   123k|               else if (*it == ']') {
  ------------------
  |  Branch (2371:25): [True: 123k, False: 31]
  ------------------
 2372|   123k|                  --ctx.depth;
 2373|   123k|                  ++it;
 2374|   123k|                  if constexpr (erasable<T>) {
 2375|   123k|                     value.erase(value_it,
 2376|   123k|                                 value.end()); // use erase rather than resize for non-default constructible elements
 2377|       |
 2378|       |                     if constexpr (check_shrink_to_fit(Opts) && has_shrink_to_fit<T>) {
 2379|       |                        value.shrink_to_fit();
 2380|       |                     }
 2381|   123k|                  }
 2382|   123k|                  return;
 2383|   123k|               }
 2384|     31|               else [[unlikely]] {
 2385|     31|                  ctx.error = error_code::expected_bracket;
 2386|     31|                  return;
 2387|     31|               }
 2388|   129k|            }
 2389|   590k|         }
 2390|       |
 2391|       |         if constexpr (Opts.partial_read) {
 2392|       |            // partial_read stops early on a success path, so give the level back like the
 2393|       |            // syntactic-close paths do; otherwise it accumulates across reads sharing a context.
 2394|       |            --ctx.depth;
 2395|       |            return;
 2396|       |         }
 2397|   590k|         else {
 2398|       |            // growing
 2399|   590k|            if constexpr (emplace_backable<T> || has_try_emplace_back<T>) {
 2400|  1.69M|               while (it < end) {
  ------------------
  |  Branch (2400:23): [True: 1.57M, False: 124k]
  ------------------
 2401|       |                  // Streaming refill point: at start of each iteration, ensure buffer has data
 2402|       |                  if constexpr (has_streaming_state<decltype(ctx)>) {
 2403|       |                     if (ctx.stream.enabled()) {
 2404|       |                        const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 2405|       |                        const size_t remaining = ctx.stream.size() - consumed;
 2406|       |                        // Refill when less than half of buffer remains to ensure space for next element
 2407|       |                        if (remaining <= ctx.stream.size() / 2 || it >= end) {
 2408|       |                           const char* new_it;
 2409|       |                           const char* new_end;
 2410|       |                           ctx.stream.consume_and_refill(consumed, new_it, new_end);
 2411|       |                           it = new_it;
 2412|       |                           end = new_end;
 2413|       |                           if (it >= end && ctx.stream.at_eof()) {
 2414|       |                              break; // No more data, exit loop normally
 2415|       |                           }
 2416|       |                        }
 2417|       |                     }
 2418|       |                  }
 2419|       |
 2420|       |                  if constexpr (has_try_emplace_back<T>) {
 2421|       |                     if (value.try_emplace_back())
 2422|       |                        parse<JSON>::op<ws_handled<Opts>()>(value.back(), ctx, it, end);
 2423|       |                     else
 2424|       |                        ctx.error = error_code::exceeded_static_array_size;
 2425|       |                  }
 2426|  1.57M|                  else {
 2427|  1.57M|                     parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
 2428|  1.57M|                  }
 2429|       |
 2430|  1.57M|                  if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (2430:23): [True: 10.8k, False: 1.56M]
  ------------------
 2431|  10.8k|                     return;
 2432|       |
 2433|       |                  // Streaming refill point: after parsing each element, refill if buffer is low
 2434|       |                  if constexpr (has_streaming_state<decltype(ctx)>) {
 2435|       |                     if (ctx.stream.enabled()) {
 2436|       |                        const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 2437|       |                        // Refill when less than 25% of buffer remains to ensure enough space for next element
 2438|       |                        if (ctx.stream.size() - consumed <= ctx.stream.size() / 4 || it >= end) {
 2439|       |                           const char* new_it;
 2440|       |                           const char* new_end;
 2441|       |                           ctx.stream.consume_and_refill(consumed, new_it, new_end);
 2442|       |                           it = new_it;
 2443|       |                           end = new_end;
 2444|       |                           if (it >= end && ctx.stream.at_eof()) {
 2445|       |                              ctx.error = error_code::unexpected_end;
 2446|       |                              return;
 2447|       |                           }
 2448|       |                        }
 2449|       |                     }
 2450|       |                  }
 2451|       |
 2452|  1.56M|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2452:23): [True: 646, False: 1.56M]
  ------------------
 2453|    646|                     return;
 2454|    646|                  }
 2455|  1.56M|                  if (*it == ',') [[likely]] {
  ------------------
  |  Branch (2455:23): [True: 1.10M, False: 454k]
  ------------------
 2456|  1.10M|                     ++it;
 2457|       |
 2458|  1.10M|                     if constexpr (!Opts.minified && !Opts.comments) {
 2459|  1.10M|                        if (ws_size && ws_size < size_t(end - it)) {
  ------------------
  |  Branch (2459:29): [True: 15.0k, False: 1.09M]
  |  Branch (2459:40): [True: 14.1k, False: 889]
  ------------------
 2460|  14.1k|                           skip_matching_ws(ws_start, it, ws_size);
 2461|  14.1k|                        }
 2462|  1.10M|                     }
 2463|       |
 2464|  1.10M|                     if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2464:26): [True: 234, False: 1.10M]
  ------------------
 2465|    234|                        return;
 2466|    234|                     }
 2467|  1.10M|                  }
 2468|   454k|                  else if (*it == ']') {
  ------------------
  |  Branch (2468:28): [True: 454k, False: 367]
  ------------------
 2469|   454k|                     --ctx.depth;
 2470|   454k|                     ++it;
 2471|       |                     if constexpr (check_shrink_to_fit(Opts) && has_shrink_to_fit<T>) {
 2472|       |                        value.shrink_to_fit();
 2473|       |                     }
 2474|   454k|                     return;
 2475|   454k|                  }
 2476|    367|                  else [[unlikely]] {
 2477|    367|                     ctx.error = error_code::expected_bracket;
 2478|    367|                     return;
 2479|    367|                  }
 2480|  1.56M|               }
 2481|       |
 2482|       |               // A valid array always returns from inside the loop upon reaching ']'.
 2483|       |               // For a null-terminated buffer the loop can only exit here by falling
 2484|       |               // through when `it` reaches the terminator without a closing bracket,
 2485|       |               // which means the input was truncated (e.g. "[", "[1," or "[1,2,").
 2486|       |               // Non-null-terminated buffers surface this through skip_ws/depth
 2487|       |               // tracking (or the streaming refill break), so this guard is limited
 2488|       |               // to the null-terminated case.
 2489|       |               if constexpr (Opts.null_terminated) {
 2490|       |                  ctx.error = error_code::unexpected_end;
 2491|       |               }
 2492|       |            }
 2493|       |            else {
 2494|       |               ctx.error = error_code::exceeded_static_array_size;
 2495|       |            }
 2496|   590k|         }
 2497|   590k|      }
_ZN3glz12rewind_depthITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextENS_7contextEEEvRT0_j:
 3697|  16.0k|   {
 3698|  16.0k|      if (ctx.error == error_code::exceeded_max_recursive_depth) [[unlikely]] {
  ------------------
  |  Branch (3698:11): [True: 991, False: 15.0k]
  ------------------
 3699|    991|         return;
 3700|    991|      }
 3701|       |      if constexpr (Opts.null_terminated) {
 3702|       |         ctx.depth = depth;
 3703|       |      }
 3704|  15.0k|      else {
 3705|  15.0k|         if (ctx.error != error_code::end_reached && ctx.error != error_code::unexpected_end) {
  ------------------
  |  Branch (3705:14): [True: 12.8k, False: 2.24k]
  |  Branch (3705:54): [True: 7.20k, False: 5.59k]
  ------------------
 3706|  7.20k|            ctx.depth = depth;
 3707|  7.20k|         }
 3708|  15.0k|      }
 3709|  15.0k|   }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 585k, False: 13.1k]
  |  Branch (3795:38): [True: 0, False: 13.1k]
  |  Branch (3795:51): [True: 991, False: 12.2k]
  ------------------
 3796|   586k|                     return;
 3797|   586k|                  }
 3798|  12.2k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  12.2k|               });
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|  6.27k|      {
 3726|  6.27k|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|  6.27k|         else {
 3732|  6.27k|            constexpr auto N = std::variant_size_v<Variant>;
 3733|  6.27k|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|  6.27k|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|  6.27k|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|  6.27k|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|  6.27k|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|  6.27k|               size_t non_const_idx = 0;
 3793|       |
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|  6.27k|                     return;
 3797|  6.27k|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  6.27k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  6.27k|                     auto copy_it{it};
 3801|  6.27k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  6.27k|                     if (!std::holds_alternative<V>(value)) {
 3803|  6.27k|                        value = V{};
 3804|  6.27k|                     }
 3805|  6.27k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  6.27k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|  6.27k|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|  6.27k|                     }
 3809|  6.27k|                     if (!bool(ctx.error)) {
 3810|  6.27k|                        found_match = true;
 3811|  6.27k|                     }
 3812|  6.27k|                     else if constexpr (not Options.null_terminated) {
 3813|  6.27k|                        constexpr bool is_complete_type =
 3814|  6.27k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|  6.27k|                        if constexpr (is_complete_type) {
 3817|  6.27k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|  6.27k|                              found_match = true;
 3819|  6.27k|                              ctx.error = error_code::none;
 3820|  6.27k|                           }
 3821|  6.27k|                           else {
 3822|  6.27k|                              it = copy_it;
 3823|  6.27k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  6.27k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|  6.27k|                                  not variant_alternative_exhausted(ctx)) {
 3826|  6.27k|                                 ctx.error = error_code::none;
 3827|  6.27k|                              }
 3828|  6.27k|                           }
 3829|  6.27k|                        }
 3830|  6.27k|                        else {
 3831|  6.27k|                           it = copy_it;
 3832|  6.27k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  6.27k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|  6.27k|                               not variant_alternative_exhausted(ctx)) {
 3835|  6.27k|                              ctx.error = error_code::none;
 3836|  6.27k|                           }
 3837|  6.27k|                        }
 3838|  6.27k|                     }
 3839|  6.27k|                     else {
 3840|  6.27k|                        it = copy_it;
 3841|  6.27k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  6.27k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|  6.27k|                            not variant_alternative_exhausted(ctx)) {
 3844|  6.27k|                           ctx.error = error_code::none;
 3845|  6.27k|                        }
 3846|  6.27k|                     }
 3847|  6.27k|                     ++non_const_idx;
 3848|  6.27k|                  }
 3849|  6.27k|               });
 3850|  6.27k|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 884, False: 5.38k]
  ------------------
 3851|    884|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|    884|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|  6.27k|         }
 3864|  6.27k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 6.27k]
  |  Branch (3795:38): [True: 0, False: 6.27k]
  |  Branch (3795:51): [True: 0, False: 6.27k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  6.27k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 6.27k]
  |  Branch (3795:38): [True: 0, False: 6.27k]
  |  Branch (3795:51): [True: 0, False: 6.27k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  6.27k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 6.27k]
  |  Branch (3795:38): [True: 0, False: 6.27k]
  |  Branch (3795:51): [True: 0, False: 6.27k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  6.27k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  6.27k|                     auto copy_it{it};
 3801|  6.27k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  6.27k|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 4.75k, False: 1.51k]
  ------------------
 3803|  4.75k|                        value = V{};
 3804|  4.75k|                     }
 3805|  6.27k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  6.27k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 1.03k, False: 5.23k]
  |  Branch (3806:45): [True: 0, False: 1.03k]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|  6.27k|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 5.23k, False: 1.03k]
  ------------------
 3810|  5.23k|                        found_match = true;
 3811|  5.23k|                     }
 3812|  1.03k|                     else if constexpr (not Options.null_terminated) {
 3813|  1.03k|                        constexpr bool is_complete_type =
 3814|  1.03k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
  ------------------
  |  Branch (3814:28): [Folded, False: 0]
  |  Branch (3814:40): [Folded, False: 0]
  |  Branch (3814:53): [True: 0, Folded]
  |  Branch (3814:68): [Folded, False: 0]
  |  Branch (3814:89): [Folded, False: 0]
  |  Branch (3814:103): [Folded, False: 0]
  ------------------
 3815|       |
 3816|  1.03k|                        if constexpr (is_complete_type) {
 3817|  1.03k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
  ------------------
  |  Branch (3817:32): [True: 155, False: 884]
  |  Branch (3817:72): [True: 155, False: 0]
  |  Branch (3817:88): [True: 155, False: 0]
  ------------------
 3818|    155|                              found_match = true;
 3819|    155|                              ctx.error = error_code::none;
 3820|    155|                           }
 3821|    884|                           else {
 3822|    884|                              it = copy_it;
 3823|    884|                              rewind_depth<Options>(ctx, copy_depth);
 3824|    884|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3824:35): [True: 0, False: 884]
  |  Branch (3824:74): [True: 0, False: 0]
  ------------------
 3825|      0|                                  not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3825:35): [True: 0, False: 0]
  ------------------
 3826|      0|                                 ctx.error = error_code::none;
 3827|      0|                              }
 3828|    884|                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|  6.27k|                     ++non_const_idx;
 3848|  6.27k|                  }
 3849|  6.27k|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_T3_:
   49|  6.27k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  6.27k|         else {
   60|  6.27k|            using V = std::remove_cvref_t<T>;
   61|  6.27k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  6.27k|                                             end);
   63|  6.27k|         }
   64|  6.27k|      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERPKcSC_S7_TkNS_10is_contextERNS_7contextEQntcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_T1_:
 1043|  6.27k|      {
 1044|       |         if constexpr (check_string_as_number(Opts)) {
 1045|       |            auto start = it;
 1046|       |            skip_number<Opts>(ctx, it, end);
 1047|       |            if (bool(ctx.error)) [[unlikely]] {
 1048|       |               return;
 1049|       |            }
 1050|       |            if (start == it) [[unlikely]] {
 1051|       |               ctx.error = error_code::parse_number_failure;
 1052|       |               return;
 1053|       |            }
 1054|       |            value.append(start, size_t(it - start));
 1055|       |         }
 1056|  6.27k|         else {
 1057|  6.27k|            if constexpr (!check_opening_handled(Opts)) {
 1058|       |               if constexpr (!check_ws_handled(Opts)) {
 1059|       |                  if (skip_ws<Opts>(ctx, it, end)) {
 1060|       |                     return;
 1061|       |                  }
 1062|       |               }
 1063|       |
 1064|  6.27k|               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (1064:20): [True: 77, False: 6.19k]
  ------------------
 1065|     77|                  return;
 1066|     77|               }
 1067|  6.27k|            }
 1068|       |
 1069|  6.27k|            if constexpr (not check_raw_string(Opts)) {
 1070|  6.27k|               static constexpr auto string_padding_bytes = 8;
 1071|       |
 1072|  6.27k|               if (size_t(end - it) >= 8) {
  ------------------
  |  Branch (1072:20): [True: 5.56k, False: 709]
  ------------------
 1073|  5.56k|                  auto start = it;
 1074|  5.56k|                  uint64_t ascii_acc{};
 1075|  5.56k|                  const auto end8 = end - 8;
 1076|  1.27M|                  while (true) {
  ------------------
  |  Branch (1076:26): [True: 1.27M, Folded]
  ------------------
 1077|  1.27M|                     if (it >= end8) [[unlikely]] {
  ------------------
  |  Branch (1077:26): [True: 603, False: 1.27M]
  ------------------
 1078|    603|                        break;
 1079|    603|                     }
 1080|       |
 1081|  1.27M|                     uint64_t chunk;
 1082|  1.27M|                     std::memcpy(&chunk, it, 8);
 1083|       |                     if constexpr (std::endian::native == std::endian::big) {
 1084|       |                        chunk = std::byteswap(chunk);
 1085|       |                     }
 1086|  1.27M|                     ascii_acc |= chunk;
 1087|  1.27M|                     const uint64_t test_chars = has_quote(chunk);
 1088|  1.27M|                     if (test_chars) {
  ------------------
  |  Branch (1088:26): [True: 6.66k, False: 1.26M]
  ------------------
 1089|  6.66k|                        it += (countr_zero(test_chars) >> 3);
 1090|       |
 1091|  6.66k|                        auto* prev = it - 1;
 1092|  8.69k|                        while (*prev == '\\') {
  ------------------
  |  Branch (1092:32): [True: 2.03k, False: 6.66k]
  ------------------
 1093|  2.03k|                           --prev;
 1094|  2.03k|                        }
 1095|  6.66k|                        if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (1095:29): [True: 4.95k, False: 1.70k]
  ------------------
 1096|  4.95k|                           goto continue_decode;
 1097|  4.95k|                        }
 1098|  1.70k|                        ++it; // skip the escaped quote
 1099|  1.70k|                     }
 1100|  1.26M|                     else {
 1101|  1.26M|                        it += 8;
 1102|  1.26M|                     }
 1103|  1.27M|                  }
 1104|       |
 1105|  2.06k|                  while (it[-1] == '\\') [[unlikely]] {
  ------------------
  |  Branch (1105:26): [True: 1.46k, False: 603]
  ------------------
 1106|       |                     // if we ended on an escape character then we need to rewind
 1107|       |                     // because we lost our context
 1108|  1.46k|                     --it;
 1109|  1.46k|                  }
 1110|       |
 1111|       |                  // The byte-wise tail keeps feeding the accumulator: it has to cover every byte of
 1112|       |                  // the string, or a non-ASCII byte reached here would be waved through unvalidated.
 1113|  4.16k|                  for (; it < end; ++it) {
  ------------------
  |  Branch (1113:26): [True: 4.05k, False: 115]
  ------------------
 1114|  4.05k|                     ascii_acc |= uint8_t(*it);
 1115|  4.05k|                     if (*it == '"') {
  ------------------
  |  Branch (1115:26): [True: 587, False: 3.46k]
  ------------------
 1116|    587|                        auto* prev = it - 1;
 1117|  1.44k|                        while (*prev == '\\') {
  ------------------
  |  Branch (1117:32): [True: 853, False: 587]
  ------------------
 1118|    853|                           --prev;
 1119|    853|                        }
 1120|    587|                        if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (1120:29): [True: 488, False: 99]
  ------------------
 1121|    488|                           goto continue_decode;
 1122|    488|                        }
 1123|    587|                     }
 1124|  4.05k|                  }
 1125|       |
 1126|    115|                  ctx.error = error_code::unexpected_end;
 1127|    115|                  return;
 1128|       |
 1129|  5.44k|               continue_decode:
 1130|       |
 1131|  5.44k|                  if (validate_utf8_span<Opts>(ctx, start, it, ascii_acc)) [[unlikely]] {
  ------------------
  |  Branch (1131:23): [True: 128, False: 5.31k]
  ------------------
 1132|    128|                     return;
 1133|    128|                  }
 1134|       |
 1135|  5.31k|                  const auto available_padding = size_t(end - it);
 1136|  5.31k|                  auto n = size_t(it - start);
 1137|  5.31k|                  if (available_padding >= 8) [[likely]] {
  ------------------
  |  Branch (1137:23): [True: 4.90k, False: 416]
  ------------------
 1138|  4.90k|                     value.resize(n + string_padding_bytes);
 1139|       |
 1140|  4.90k|                     auto* p = value.data();
 1141|       |
 1142|  26.5k|                     while (true) {
  ------------------
  |  Branch (1142:29): [True: 26.5k, Folded]
  ------------------
 1143|  26.5k|                        if (start >= it) {
  ------------------
  |  Branch (1143:29): [True: 4.51k, False: 21.9k]
  ------------------
 1144|  4.51k|                           break;
 1145|  4.51k|                        }
 1146|       |
 1147|  21.9k|                        std::memcpy(p, start, 8);
 1148|  21.9k|                        uint64_t swar;
 1149|  21.9k|                        std::memcpy(&swar, p, 8);
 1150|       |                        if constexpr (std::endian::native == std::endian::big) {
 1151|       |                           swar = std::byteswap(swar);
 1152|       |                        }
 1153|       |
 1154|  21.9k|                        constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
 1155|  21.9k|                        const uint64_t lo7 = swar & lo7_mask;
 1156|  21.9k|                        const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
 1157|  21.9k|                        const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
 1158|  21.9k|                        uint64_t next = ~((backslash & less_32) | swar);
 1159|       |
 1160|  21.9k|                        next &= repeat_byte8(0b10000000);
 1161|  21.9k|                        if (next == 0) {
  ------------------
  |  Branch (1161:29): [True: 20.0k, False: 1.92k]
  ------------------
 1162|  20.0k|                           start += 8;
 1163|  20.0k|                           p += 8;
 1164|  20.0k|                           continue;
 1165|  20.0k|                        }
 1166|       |
 1167|  1.92k|                        next = countr_zero(next) >> 3;
 1168|  1.92k|                        start += next;
 1169|  1.92k|                        if (start >= it) {
  ------------------
  |  Branch (1169:29): [True: 295, False: 1.63k]
  ------------------
 1170|    295|                           break;
 1171|    295|                        }
 1172|       |
 1173|  1.63k|                        if ((*start & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1173:29): [True: 27, False: 1.60k]
  ------------------
 1174|     27|                           ctx.error = error_code::syntax_error;
 1175|     27|                           return;
 1176|     27|                        }
 1177|  1.60k|                        ++start; // skip the escape
 1178|  1.60k|                        if (*start == 'u') {
  ------------------
  |  Branch (1178:29): [True: 1.19k, False: 412]
  ------------------
 1179|  1.19k|                           ++start;
 1180|  1.19k|                           p += next;
 1181|  1.19k|                           const auto mark = start;
 1182|  1.19k|                           const auto offset = handle_unicode_code_point(start, p, end);
 1183|  1.19k|                           if (offset == 0) [[unlikely]] {
  ------------------
  |  Branch (1183:32): [True: 57, False: 1.13k]
  ------------------
 1184|     57|                              ctx.error = error_code::unicode_escape_conversion_failure;
 1185|     57|                              return;
 1186|     57|                           }
 1187|  1.13k|                           n += offset;
 1188|       |                           // escape + u + unicode code points
 1189|  1.13k|                           n -= 2 + uint32_t(start - mark);
 1190|  1.13k|                        }
 1191|    412|                        else {
 1192|    412|                           p += next;
 1193|    412|                           *p = char_unescape_table[uint8_t(*start)];
 1194|    412|                           if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1194:32): [True: 11, False: 401]
  ------------------
 1195|     11|                              ctx.error = error_code::invalid_escape;
 1196|     11|                              return;
 1197|     11|                           }
 1198|    401|                           ++p;
 1199|    401|                           ++start;
 1200|    401|                           --n;
 1201|    401|                        }
 1202|  1.60k|                     }
 1203|       |
 1204|  4.80k|                     value.resize(n);
 1205|  4.80k|                     ++it;
 1206|  4.80k|                  }
 1207|    416|                  else {
 1208|       |                     // For large inputs this case of running out of buffer is very rare
 1209|    416|                     value.resize(n);
 1210|    416|                     auto* p = value.data();
 1211|       |
 1212|    416|                     it = start;
 1213|   602k|                     while (it < end) [[likely]] {
  ------------------
  |  Branch (1213:29): [True: 602k, False: 0]
  ------------------
 1214|   602k|                        if (*it == '"') {
  ------------------
  |  Branch (1214:29): [True: 261, False: 601k]
  ------------------
 1215|    261|                           value.resize(size_t(p - value.data()));
 1216|    261|                           ++it;
 1217|    261|                           return;
 1218|    261|                        }
 1219|       |
 1220|   601k|                        if ((*it & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1220:29): [True: 43, False: 601k]
  ------------------
 1221|     43|                           ctx.error = error_code::syntax_error;
 1222|     43|                           return;
 1223|     43|                        }
 1224|       |
 1225|   601k|                        *p = *it;
 1226|       |
 1227|   601k|                        if (*it == '\\') {
  ------------------
  |  Branch (1227:29): [True: 2.16k, False: 599k]
  ------------------
 1228|  2.16k|                           ++it; // skip the escape
 1229|  2.16k|                           if (*it == 'u') {
  ------------------
  |  Branch (1229:32): [True: 1.21k, False: 958]
  ------------------
 1230|  1.21k|                              ++it;
 1231|  1.21k|                              if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
  ------------------
  |  Branch (1231:35): [True: 96, False: 1.11k]
  ------------------
 1232|     96|                                 ctx.error = error_code::unicode_escape_conversion_failure;
 1233|     96|                                 return;
 1234|     96|                              }
 1235|  1.21k|                           }
 1236|    958|                           else {
 1237|    958|                              *p = char_unescape_table[uint8_t(*it)];
 1238|    958|                              if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1238:35): [True: 16, False: 942]
  ------------------
 1239|     16|                                 ctx.error = error_code::invalid_escape;
 1240|     16|                                 return;
 1241|     16|                              }
 1242|    942|                              ++p;
 1243|    942|                              ++it;
 1244|    942|                           }
 1245|  2.16k|                        }
 1246|   599k|                        else {
 1247|   599k|                           ++it;
 1248|   599k|                           ++p;
 1249|   599k|                        }
 1250|   601k|                     }
 1251|       |
 1252|      0|                     ctx.error = error_code::unexpected_end;
 1253|      0|                  }
 1254|  5.31k|               }
 1255|    709|               else {
 1256|       |                  // For short strings
 1257|       |
 1258|    709|                  std::array<char, 8> buffer{};
 1259|       |
 1260|    709|                  auto* p = buffer.data();
 1261|    709|                  const auto* const utf8_start = it;
 1262|       |
 1263|  1.71k|                  while (it < end) [[likely]] {
  ------------------
  |  Branch (1263:26): [True: 1.53k, False: 174]
  ------------------
 1264|  1.53k|                     *p = *it;
 1265|  1.53k|                     if (*it == '"') {
  ------------------
  |  Branch (1265:26): [True: 410, False: 1.12k]
  ------------------
 1266|    410|                        if (validate_utf8_span<Opts>(ctx, utf8_start, it)) [[unlikely]] {
  ------------------
  |  Branch (1266:29): [True: 92, False: 318]
  ------------------
 1267|     92|                           return;
 1268|     92|                        }
 1269|    318|                        const size_t n = size_t(p - buffer.data());
 1270|    318|#if __has_cpp_attribute(assume) >= 202207L
 1271|    318|                        [[assume(n <= sizeof(buffer))]];
 1272|    318|#endif
 1273|    318|                        value.assign(buffer.data(), n);
 1274|    318|                        ++it;
 1275|    318|                        if constexpr (not Opts.null_terminated) {
 1276|    318|                           if (it == end) {
  ------------------
  |  Branch (1276:32): [True: 155, False: 163]
  ------------------
 1277|    155|                              ctx.error = error_code::end_reached;
 1278|    155|                              return;
 1279|    155|                           }
 1280|    318|                        }
 1281|    163|                        return;
 1282|    410|                     }
 1283|  1.12k|                     else if (*it == '\\') {
  ------------------
  |  Branch (1283:31): [True: 172, False: 956]
  ------------------
 1284|    172|                        ++it; // skip the escape
 1285|    172|                        if constexpr (not Opts.null_terminated) {
 1286|    172|                           if (it == end) [[unlikely]] {
  ------------------
  |  Branch (1286:32): [True: 3, False: 169]
  ------------------
 1287|      3|                              ctx.error = error_code::unexpected_end;
 1288|      3|                              return;
 1289|      3|                           }
 1290|    172|                        }
 1291|    172|                        if (*it == 'u') {
  ------------------
  |  Branch (1291:29): [True: 109, False: 63]
  ------------------
 1292|    109|                           ++it;
 1293|    109|                           if constexpr (not Opts.null_terminated) {
 1294|    109|                              if (it == end) [[unlikely]] {
  ------------------
  |  Branch (1294:35): [True: 2, False: 107]
  ------------------
 1295|      2|                                 ctx.error = error_code::unexpected_end;
 1296|      2|                                 return;
 1297|      2|                              }
 1298|    109|                           }
 1299|    109|                           if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
  ------------------
  |  Branch (1299:32): [True: 62, False: 47]
  ------------------
 1300|     62|                              ctx.error = error_code::unicode_escape_conversion_failure;
 1301|     62|                              return;
 1302|     62|                           }
 1303|    109|                        }
 1304|     63|                        else {
 1305|     63|                           *p = char_unescape_table[uint8_t(*it)];
 1306|     63|                           if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1306:32): [True: 13, False: 50]
  ------------------
 1307|     13|                              ctx.error = error_code::invalid_escape;
 1308|     13|                              return;
 1309|     13|                           }
 1310|     50|                           ++p;
 1311|     50|                           ++it;
 1312|     50|                        }
 1313|    172|                     }
 1314|    956|                     else if ((*it & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1314:31): [True: 50, False: 906]
  ------------------
 1315|     50|                        ctx.error = error_code::syntax_error;
 1316|     50|                        return;
 1317|     50|                     }
 1318|    906|                     else {
 1319|    906|                        ++it;
 1320|    906|                        ++p;
 1321|    906|                     }
 1322|  1.53k|                  }
 1323|       |
 1324|    174|                  ctx.error = error_code::unexpected_end;
 1325|    174|               }
 1326|       |            }
 1327|       |            else {
 1328|       |               // raw_string
 1329|       |               auto start = it;
 1330|       |               skip_string_view(ctx, it, end);
 1331|       |               if (bool(ctx.error)) [[unlikely]]
 1332|       |                  return;
 1333|       |
 1334|       |               if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]] {
 1335|       |                  return;
 1336|       |               }
 1337|       |
 1338|       |               value.assign(start, size_t(it - start));
 1339|       |               ++it;
 1340|       |            }
 1341|  6.27k|         }
 1342|  6.27k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 5.38k, False: 884]
  |  Branch (3795:38): [True: 0, False: 884]
  |  Branch (3795:51): [True: 0, False: 884]
  ------------------
 3796|  5.38k|                     return;
 3797|  5.38k|                  }
 3798|    884|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    884|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 5.38k, False: 884]
  |  Branch (3795:38): [True: 0, False: 884]
  |  Branch (3795:51): [True: 0, False: 884]
  ------------------
 3796|  5.38k|                     return;
 3797|  5.38k|                  }
 3798|    884|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    884|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 5.38k, False: 884]
  |  Branch (3795:38): [True: 0, False: 884]
  |  Branch (3795:51): [True: 0, False: 884]
  ------------------
 3796|  5.38k|                     return;
 3797|  5.38k|                  }
 3798|    884|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    884|               });
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|  1.38k|      {
 3726|  1.38k|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|  1.38k|         else {
 3732|  1.38k|            constexpr auto N = std::variant_size_v<Variant>;
 3733|  1.38k|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|  1.38k|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|  1.38k|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|  1.38k|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|  1.38k|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|  1.38k|               size_t non_const_idx = 0;
 3793|       |
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|  1.38k|                     return;
 3797|  1.38k|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  1.38k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  1.38k|                     auto copy_it{it};
 3801|  1.38k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  1.38k|                     if (!std::holds_alternative<V>(value)) {
 3803|  1.38k|                        value = V{};
 3804|  1.38k|                     }
 3805|  1.38k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  1.38k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|  1.38k|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|  1.38k|                     }
 3809|  1.38k|                     if (!bool(ctx.error)) {
 3810|  1.38k|                        found_match = true;
 3811|  1.38k|                     }
 3812|  1.38k|                     else if constexpr (not Options.null_terminated) {
 3813|  1.38k|                        constexpr bool is_complete_type =
 3814|  1.38k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|  1.38k|                        if constexpr (is_complete_type) {
 3817|  1.38k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|  1.38k|                              found_match = true;
 3819|  1.38k|                              ctx.error = error_code::none;
 3820|  1.38k|                           }
 3821|  1.38k|                           else {
 3822|  1.38k|                              it = copy_it;
 3823|  1.38k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  1.38k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|  1.38k|                                  not variant_alternative_exhausted(ctx)) {
 3826|  1.38k|                                 ctx.error = error_code::none;
 3827|  1.38k|                              }
 3828|  1.38k|                           }
 3829|  1.38k|                        }
 3830|  1.38k|                        else {
 3831|  1.38k|                           it = copy_it;
 3832|  1.38k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  1.38k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|  1.38k|                               not variant_alternative_exhausted(ctx)) {
 3835|  1.38k|                              ctx.error = error_code::none;
 3836|  1.38k|                           }
 3837|  1.38k|                        }
 3838|  1.38k|                     }
 3839|  1.38k|                     else {
 3840|  1.38k|                        it = copy_it;
 3841|  1.38k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  1.38k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|  1.38k|                            not variant_alternative_exhausted(ctx)) {
 3844|  1.38k|                           ctx.error = error_code::none;
 3845|  1.38k|                        }
 3846|  1.38k|                     }
 3847|  1.38k|                     ++non_const_idx;
 3848|  1.38k|                  }
 3849|  1.38k|               });
 3850|  1.38k|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 250, False: 1.13k]
  ------------------
 3851|    250|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|    250|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|  1.38k|         }
 3864|  1.38k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.38k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.38k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.38k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  1.38k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  1.38k|                     auto copy_it{it};
 3801|  1.38k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  1.38k|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 1.18k, False: 194]
  ------------------
 3803|  1.18k|                        value = V{};
 3804|  1.18k|                     }
 3805|  1.38k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  1.38k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 267, False: 1.11k]
  |  Branch (3806:45): [True: 0, False: 267]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|  1.38k|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 1.11k, False: 267]
  ------------------
 3810|  1.11k|                        found_match = true;
 3811|  1.11k|                     }
 3812|    267|                     else if constexpr (not Options.null_terminated) {
 3813|    267|                        constexpr bool is_complete_type =
 3814|    267|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
  ------------------
  |  Branch (3814:28): [Folded, False: 0]
  |  Branch (3814:40): [True: 0, Folded]
  |  Branch (3814:53): [Folded, False: 0]
  |  Branch (3814:68): [Folded, False: 0]
  |  Branch (3814:89): [Folded, False: 0]
  |  Branch (3814:103): [Folded, False: 0]
  ------------------
 3815|       |
 3816|    267|                        if constexpr (is_complete_type) {
 3817|    267|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
  ------------------
  |  Branch (3817:32): [True: 17, False: 250]
  |  Branch (3817:72): [True: 17, False: 0]
  |  Branch (3817:88): [True: 17, False: 0]
  ------------------
 3818|     17|                              found_match = true;
 3819|     17|                              ctx.error = error_code::none;
 3820|     17|                           }
 3821|    250|                           else {
 3822|    250|                              it = copy_it;
 3823|    250|                              rewind_depth<Options>(ctx, copy_depth);
 3824|    250|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3824:35): [True: 0, False: 250]
  |  Branch (3824:74): [True: 0, False: 0]
  ------------------
 3825|      0|                                  not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3825:35): [True: 0, False: 0]
  ------------------
 3826|      0|                                 ctx.error = error_code::none;
 3827|      0|                              }
 3828|    250|                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|  1.38k|                     ++non_const_idx;
 3848|  1.38k|                  }
 3849|  1.38k|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERbTkNS_10is_contextERNS_7contextERPKcS8_EEvOT0_OT1_OT2_T3_:
   49|  1.38k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  1.38k|         else {
   60|  1.38k|            using V = std::remove_cvref_t<T>;
   61|  1.38k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  1.38k|                                             end);
   63|  1.38k|         }
   64|  1.38k|      }
_ZN3glz4fromILj10EbE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEETkNS_6bool_tERbTkNS_10is_contextERNS_7contextERPKcS8_EEvOT0_OT1_OT2_T3_:
  669|  1.38k|      {
  670|       |         if constexpr (check_quoted_num(Opts)) {
  671|       |            if (skip_ws<Opts>(ctx, it, end)) {
  672|       |               return;
  673|       |            }
  674|       |            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  675|       |               return;
  676|       |            }
  677|       |         }
  678|       |
  679|       |         if constexpr (!check_ws_handled(Opts)) {
  680|       |            if (skip_ws<Opts>(ctx, it, end)) {
  681|       |               return;
  682|       |            }
  683|       |         }
  684|       |
  685|       |         if constexpr (check_bools_as_numbers(Opts)) {
  686|       |            if (*it == '1') {
  687|       |               value = true;
  688|       |               ++it;
  689|       |            }
  690|       |            else if (*it == '0') {
  691|       |               value = false;
  692|       |               ++it;
  693|       |            }
  694|       |            else {
  695|       |               ctx.error = error_code::syntax_error;
  696|       |               return;
  697|       |            }
  698|       |         }
  699|  1.38k|         else {
  700|  1.38k|            if constexpr (not check_is_padded(Opts)) {
  701|  1.38k|               if (size_t(end - it) < 4) [[unlikely]] {
  ------------------
  |  Branch (701:20): [True: 69, False: 1.31k]
  ------------------
  702|     69|                  ctx.error = error_code::expected_true_or_false;
  703|     69|                  return;
  704|     69|               }
  705|  1.38k|            }
  706|       |
  707|  1.31k|            uint32_t c;
  708|  1.38k|            static constexpr uint32_t u_true = 0b01100101'01110101'01110010'01110100;
  709|  1.38k|            static constexpr uint32_t u_fals = 0b01110011'01101100'01100001'01100110;
  710|  1.38k|            std::memcpy(&c, it, 4);
  711|       |            if constexpr (std::endian::native == std::endian::big) {
  712|       |               c = std::byteswap(c);
  713|       |            }
  714|  1.38k|            it += 4;
  715|  1.38k|            if (c == u_true) {
  ------------------
  |  Branch (715:17): [True: 862, False: 521]
  ------------------
  716|    862|               value = true;
  717|    862|            }
  718|    521|            else if (it == end) [[unlikely]] {
  ------------------
  |  Branch (718:22): [True: 63, False: 458]
  ------------------
  719|     63|               ctx.error = error_code::unexpected_end;
  720|     63|               return;
  721|     63|            }
  722|    458|            else {
  723|    458|               if (c == u_fals && (*it == 'e')) [[likely]] {
  ------------------
  |  Branch (723:20): [True: 285, False: 173]
  |  Branch (723:35): [True: 271, False: 14]
  ------------------
  724|    271|                  value = false;
  725|    271|                  ++it;
  726|    271|               }
  727|    187|               else [[unlikely]] {
  728|    187|                  ctx.error = error_code::expected_true_or_false;
  729|    187|                  return;
  730|    187|               }
  731|    458|            }
  732|  1.38k|         }
  733|       |
  734|       |         if constexpr (check_quoted_num(Opts)) {
  735|       |            if constexpr (not Opts.null_terminated) {
  736|       |               if (it == end) [[unlikely]] {
  737|       |                  ctx.error = error_code::unexpected_end;
  738|       |                  return;
  739|       |               }
  740|       |            }
  741|       |            if (match<'"'>(ctx, it)) {
  742|       |               return;
  743|       |            }
  744|       |            if constexpr (not Opts.null_terminated) {
  745|       |               if (it == end) {
  746|       |                  ctx.error = error_code::end_reached;
  747|       |                  return;
  748|       |               }
  749|       |            }
  750|       |         }
  751|  1.38k|         else {
  752|  1.38k|            if constexpr (not Opts.null_terminated) {
  753|  1.38k|               if (it == end) {
  ------------------
  |  Branch (753:20): [True: 17, False: 1.36k]
  ------------------
  754|     17|                  ctx.error = error_code::end_reached;
  755|     17|                  return;
  756|     17|               }
  757|  1.38k|            }
  758|  1.38k|         }
  759|  1.38k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 1.13k, False: 250]
  |  Branch (3795:38): [True: 0, False: 250]
  |  Branch (3795:51): [True: 0, False: 250]
  ------------------
 3796|  1.13k|                     return;
 3797|  1.13k|                  }
 3798|    250|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    250|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 1.13k, False: 250]
  |  Branch (3795:38): [True: 0, False: 250]
  |  Branch (3795:51): [True: 0, False: 250]
  ------------------
 3796|  1.13k|                     return;
 3797|  1.13k|                  }
 3798|    250|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    250|               });
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|  2.19M|      {
 3726|  2.19M|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|  2.19M|         else {
 3732|  2.19M|            constexpr auto N = std::variant_size_v<Variant>;
 3733|  2.19M|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|  2.19M|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|  2.19M|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|  2.19M|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|  2.19M|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|  2.19M|               size_t non_const_idx = 0;
 3793|       |
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|  2.19M|                     return;
 3797|  2.19M|                  }
 3798|  2.19M|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  2.19M|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  2.19M|                     auto copy_it{it};
 3801|  2.19M|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  2.19M|                     if (!std::holds_alternative<V>(value)) {
 3803|  2.19M|                        value = V{};
 3804|  2.19M|                     }
 3805|  2.19M|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  2.19M|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|  2.19M|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|  2.19M|                     }
 3809|  2.19M|                     if (!bool(ctx.error)) {
 3810|  2.19M|                        found_match = true;
 3811|  2.19M|                     }
 3812|  2.19M|                     else if constexpr (not Options.null_terminated) {
 3813|  2.19M|                        constexpr bool is_complete_type =
 3814|  2.19M|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|  2.19M|                        if constexpr (is_complete_type) {
 3817|  2.19M|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|  2.19M|                              found_match = true;
 3819|  2.19M|                              ctx.error = error_code::none;
 3820|  2.19M|                           }
 3821|  2.19M|                           else {
 3822|  2.19M|                              it = copy_it;
 3823|  2.19M|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  2.19M|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|  2.19M|                                  not variant_alternative_exhausted(ctx)) {
 3826|  2.19M|                                 ctx.error = error_code::none;
 3827|  2.19M|                              }
 3828|  2.19M|                           }
 3829|  2.19M|                        }
 3830|  2.19M|                        else {
 3831|  2.19M|                           it = copy_it;
 3832|  2.19M|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  2.19M|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|  2.19M|                               not variant_alternative_exhausted(ctx)) {
 3835|  2.19M|                              ctx.error = error_code::none;
 3836|  2.19M|                           }
 3837|  2.19M|                        }
 3838|  2.19M|                     }
 3839|  2.19M|                     else {
 3840|  2.19M|                        it = copy_it;
 3841|  2.19M|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  2.19M|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|  2.19M|                            not variant_alternative_exhausted(ctx)) {
 3844|  2.19M|                           ctx.error = error_code::none;
 3845|  2.19M|                        }
 3846|  2.19M|                     }
 3847|  2.19M|                     ++non_const_idx;
 3848|  2.19M|                  }
 3849|  2.19M|               });
 3850|  2.19M|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 1.70k, False: 2.18M]
  ------------------
 3851|  1.70k|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|  1.70k|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|  2.19M|         }
 3864|  2.19M|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 2.19M]
  |  Branch (3795:38): [True: 0, False: 2.19M]
  |  Branch (3795:51): [True: 0, False: 2.19M]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  2.19M|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  2.19M|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 2.19M]
  |  Branch (3795:38): [True: 0, False: 2.19M]
  |  Branch (3795:51): [True: 0, False: 2.19M]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  2.19M|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  2.19M|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  2.19M|                     auto copy_it{it};
 3801|  2.19M|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  2.19M|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 1.92M, False: 270k]
  ------------------
 3803|  1.92M|                        value = V{};
 3804|  1.92M|                     }
 3805|  2.19M|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  2.19M|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 4.55k, False: 2.18M]
  |  Branch (3806:45): [True: 0, False: 4.55k]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|  2.19M|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 2.18M, False: 4.55k]
  ------------------
 3810|  2.18M|                        found_match = true;
 3811|  2.18M|                     }
 3812|  4.55k|                     else if constexpr (not Options.null_terminated) {
 3813|  4.55k|                        constexpr bool is_complete_type =
 3814|  4.55k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
  ------------------
  |  Branch (3814:28): [True: 4.55k, Folded]
  |  Branch (3814:40): [Folded, False: 0]
  |  Branch (3814:53): [Folded, False: 0]
  |  Branch (3814:68): [Folded, False: 0]
  |  Branch (3814:89): [Folded, False: 0]
  |  Branch (3814:103): [Folded, False: 0]
  ------------------
 3815|       |
 3816|  4.55k|                        if constexpr (is_complete_type) {
 3817|  4.55k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
  ------------------
  |  Branch (3817:32): [True: 2.84k, False: 1.70k]
  |  Branch (3817:72): [True: 2.84k, False: 0]
  |  Branch (3817:88): [True: 2.84k, False: 0]
  ------------------
 3818|  2.84k|                              found_match = true;
 3819|  2.84k|                              ctx.error = error_code::none;
 3820|  2.84k|                           }
 3821|  1.70k|                           else {
 3822|  1.70k|                              it = copy_it;
 3823|  1.70k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  1.70k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3824:35): [True: 0, False: 1.70k]
  |  Branch (3824:74): [True: 0, False: 0]
  ------------------
 3825|      0|                                  not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3825:35): [True: 0, False: 0]
  ------------------
 3826|      0|                                 ctx.error = error_code::none;
 3827|      0|                              }
 3828|  1.70k|                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|  2.19M|                     ++non_const_idx;
 3848|  2.19M|                  }
 3849|  2.19M|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERdTkNS_10is_contextERNS_7contextERPKcS8_EEvOT0_OT1_OT2_T3_:
   49|  2.19M|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  2.19M|         else {
   60|  2.19M|            using V = std::remove_cvref_t<T>;
   61|  2.19M|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  2.19M|                                             end);
   63|  2.19M|         }
   64|  2.19M|      }
_ZN3glz4fromILj10EdE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERPKcRdTkNS_10is_contextERNS_7contextES5_EEvOT1_OT2_OT0_T3_:
  767|  2.19M|      {
  768|       |         if constexpr (check_quoted_num(Opts)) {
  769|       |            if (skip_ws<Opts>(ctx, it, end)) {
  770|       |               return;
  771|       |            }
  772|       |            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  773|       |               return;
  774|       |            }
  775|       |         }
  776|       |
  777|       |         if constexpr (!check_ws_handled(Opts)) {
  778|       |            if (skip_ws<Opts>(ctx, it, end)) {
  779|       |               return;
  780|       |            }
  781|       |         }
  782|       |
  783|  2.19M|         using V = std::decay_t<decltype(value)>;
  784|       |         if constexpr (int_t<V>) {
  785|       |            static_assert(sizeof(*it) == sizeof(char));
  786|       |
  787|       |            if constexpr (Opts.null_terminated) {
  788|       |               if (not glz::atoi(value, it)) [[unlikely]] {
  789|       |                  ctx.error = error_code::parse_number_failure;
  790|       |                  return;
  791|       |               }
  792|       |            }
  793|       |            else {
  794|       |               if (not glz::atoi(value, it, end)) [[unlikely]] {
  795|       |                  ctx.error = error_code::parse_number_failure;
  796|       |                  return;
  797|       |               }
  798|       |            }
  799|       |         }
  800|  2.19M|         else {
  801|       |// float128_t requires std::from_chars for floating-point, unavailable on older Apple platforms (iOS < 16.3)
  802|  2.19M|#if !defined(_LIBCPP_VERSION) || defined(_LIBCPP_AVAILABILITY_HAS_TO_CHARS_FLOATING_POINT)
  803|       |            if constexpr (is_float128<V>) {
  804|       |               auto [ptr, ec] = std::from_chars(it, end, value);
  805|       |               if (ec != std::errc()) {
  806|       |                  ctx.error = error_code::parse_number_failure;
  807|       |                  return;
  808|       |               }
  809|       |               it = ptr;
  810|       |            }
  811|       |            else
  812|       |#endif
  813|  2.19M|            {
  814|       |               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
  815|       |                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
  816|       |                  // place
  817|       |                  V temp;
  818|       |                  if constexpr (is_size_optimized(Opts)) {
  819|       |                     auto [ptr, ec] = simple_float::from_chars<Opts.null_terminated>(it, end, temp);
  820|       |                     if (ec != std::errc{}) [[unlikely]] {
  821|       |                        ctx.error = error_code::parse_number_failure;
  822|       |                        return;
  823|       |                     }
  824|       |                     it = ptr;
  825|       |                  }
  826|       |                  else {
  827|       |                     auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
  828|       |                     if (ec != std::errc()) [[unlikely]] {
  829|       |                        ctx.error = error_code::parse_number_failure;
  830|       |                        return;
  831|       |                     }
  832|       |                     it = ptr;
  833|       |                  }
  834|       |                  value = temp;
  835|       |               }
  836|  2.19M|               else {
  837|       |                  if constexpr (is_size_optimized(Opts)) {
  838|       |                     auto [ptr, ec] = simple_float::from_chars<Opts.null_terminated>(it, end, value);
  839|       |                     if (ec != std::errc{}) [[unlikely]] {
  840|       |                        ctx.error = error_code::parse_number_failure;
  841|       |                        return;
  842|       |                     }
  843|       |                     it = ptr;
  844|       |                  }
  845|  2.19M|                  else {
  846|  2.19M|                     auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
  847|  2.19M|                     if (ec != std::errc()) [[unlikely]] {
  ------------------
  |  Branch (847:26): [True: 1.70k, False: 2.18M]
  ------------------
  848|  1.70k|                        ctx.error = error_code::parse_number_failure;
  849|  1.70k|                        return;
  850|  1.70k|                     }
  851|  2.18M|                     it = ptr;
  852|  2.18M|                  }
  853|  2.19M|               }
  854|  2.19M|            }
  855|  2.19M|         }
  856|       |
  857|       |         if constexpr (check_quoted_num(Opts)) {
  858|       |            if constexpr (not Opts.null_terminated) {
  859|       |               if (it == end) [[unlikely]] {
  860|       |                  ctx.error = error_code::unexpected_end;
  861|       |                  return;
  862|       |               }
  863|       |            }
  864|       |            if (match<'"'>(ctx, it)) {
  865|       |               return;
  866|       |            }
  867|       |            if constexpr (not Opts.null_terminated) {
  868|       |               if (it == end) {
  869|       |                  ctx.error = error_code::end_reached;
  870|       |                  return;
  871|       |               }
  872|       |            }
  873|       |         }
  874|  2.19M|         else {
  875|  2.19M|            if constexpr (not Opts.null_terminated) {
  876|  2.19M|               if (it == end) {
  ------------------
  |  Branch (876:20): [True: 2.84k, False: 2.18M]
  ------------------
  877|  2.84k|                  ctx.error = error_code::end_reached;
  878|  2.84k|                  return;
  879|  2.84k|               }
  880|  2.19M|            }
  881|  2.19M|         }
  882|  2.19M|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_9is_bufferERKNSt3__16vectorIcNS6_9allocatorIcEEEEQnt18is_input_streamingIu20__remove_reference_tIT0_EEEENS_9error_ctxERT_OSD_:
 5266|  11.3k|   {
 5267|  11.3k|      context ctx{};
 5268|  11.3k|      return read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
 5269|  11.3k|   }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERNS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
   49|  11.3k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  11.3k|         else {
   60|  11.3k|            using V = std::remove_cvref_t<T>;
   61|  11.3k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  11.3k|                                             end);
   63|  11.3k|         }
   64|  11.3k|      }
_ZN3glz4fromILj10ENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERS4_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
  150|  11.3k|      {
  151|  11.3k|         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
  152|  11.3k|         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
  153|  11.3k|                                          std::forward<Ctx>(ctx), std::forward<It0>(it), end);
  154|  11.3k|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4065|  11.3k|      {
 4066|       |         if constexpr (tagging == variant_tagging_kind::adjacent) {
 4067|       |            read_adjacent<Options>(value, ctx, it, end);
 4068|       |         }
 4069|  11.3k|         else {
 4070|  11.3k|            read_deduced<Options>(value, ctx, it, end);
 4071|  11.3k|         }
 4072|  11.3k|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE12read_deducedITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4076|  11.3k|      {
 4077|  11.3k|         constexpr auto Opts = ws_handled_off<Options>();
 4078|  11.3k|         if constexpr (variant_is_auto_deducible<T>()) {
 4079|  11.3k|            if constexpr (not check_ws_handled(Options)) {
 4080|  11.3k|               if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (4080:20): [True: 0, False: 11.3k]
  ------------------
 4081|      0|                  return;
 4082|      0|               }
 4083|  11.3k|            }
 4084|       |
 4085|  11.3k|            switch (*it) {
 4086|     15|            case '\0':
  ------------------
  |  Branch (4086:13): [True: 15, False: 11.3k]
  ------------------
 4087|     15|               ctx.error = error_code::unexpected_end;
 4088|     15|               return;
 4089|  5.14k|            case '{': {
  ------------------
  |  Branch (4089:13): [True: 5.14k, False: 6.17k]
  ------------------
 4090|       |               // This branch consumes the brace itself and hands the object to a reader with
 4091|       |               // `opening_handled`, which therefore does not count the level -- but does release it at
 4092|       |               // the closing brace. So the level is taken here, in both buffer modes, and paid back by
 4093|       |               // the reader below.
 4094|  5.14k|               if (enter_depth(ctx)) [[unlikely]] {
  ------------------
  |  Branch (4094:20): [True: 0, False: 5.14k]
  ------------------
 4095|      0|                  return;
 4096|      0|               }
 4097|       |
 4098|  5.14k|               ++it;
 4099|       |               if constexpr (not Opts.null_terminated) {
 4100|       |                  if (it == end) [[unlikely]] {
 4101|       |                     ctx.error = error_code::unexpected_end;
 4102|       |                     return;
 4103|       |                  }
 4104|       |               }
 4105|  5.14k|               using type_counts = variant_type_count<T>;
 4106|  5.14k|               constexpr auto n_object_candidates = variant_object_candidate_count_v<Opts, T>;
 4107|       |               if constexpr (n_object_candidates < 1) {
 4108|       |                  ctx.error = error_code::no_matching_variant_type;
 4109|       |                  return;
 4110|       |               }
 4111|  5.14k|               else if constexpr (n_object_candidates == 1 && tag_v<T>.empty()) {
 4112|  5.14k|                  constexpr auto first_idx = variant_first_object_candidate_v<Opts, T>;
 4113|  5.14k|                  using V = std::variant_alternative_t<first_idx, T>;
 4114|  5.14k|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4114:23): [True: 5.14k, False: 0]
  ------------------
 4115|  5.14k|                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
 4116|  5.14k|                  return;
 4117|       |               }
 4118|       |               else {
 4119|       |                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
 4120|       |                  static constexpr auto& deduction_bits = variant_deduction_bits<T>;
 4121|       |                  static constexpr size_t deduction_key_count = variant_deduction_key_count<T>;
 4122|       |                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
 4123|       |
 4124|       |                  // Track if we've encountered a tag and what value it had
 4125|       |                  std::optional<size_t> tag_specified_index{};
 4126|       |
 4127|       |                  if (skip_ws<Opts>(ctx, it, end)) {
 4128|       |                     return;
 4129|       |                  }
 4130|       |                  // Once the reader knows which alternative this object holds it may have to read
 4131|       |                  // it again from here. Anchor the position rather than keep the pointer: the scan
 4132|       |                  // below skips values, and a streaming skip refills, which moves the window out
 4133|       |                  // from under a raw pointer (see rewind_anchor).
 4134|       |                  auto start = make_rewind_anchor(ctx, it);
 4135|       |                  bool first_key = true;
 4136|       |                  // Parse bifurcation for tagged variants:
 4137|       |                  //
 4138|       |                  // Without this optimization, tagged variant parsing always uses two passes:
 4139|       |                  //   1. Scan all keys to find the tag (e.g. "type"), skipping values
 4140|       |                  //   2. Reset `it = start` and re-parse the entire object into the resolved type
 4141|       |                  //
 4142|       |                  // When the tag is the first key, the second pass redundantly re-reads every
 4143|       |                  // field that follows it. This lambda avoids that: if the tag was the first key,
 4144|       |                  // it advances past the trailing comma so the object parser picks up at the
 4145|       |                  // second field. If the tag was found later, it falls back to the full re-parse.
 4146|       |                  //
 4147|       |                  // One exception: if the tag name is also a field on the resolved struct
 4148|       |                  // (contains_tag), we must re-parse regardless so the value is stored in
 4149|       |                  // the struct field. This override is applied inside each std::visit lambda.
 4150|       |                  //
 4151|       |                  // Either way the rewind can fail under a streaming read: the window only holds so
 4152|       |                  // much, and an object wider than it has no start left to return to.
 4153|       |                  auto position_after_tag = [&] {
 4154|       |                     if (first_key) {
 4155|       |                        if (*it == ',') ++it; // skip comma; handles tag-only objects where *it == '}'
 4156|       |                        return true;
 4157|       |                     }
 4158|       |                     return start.rewind(ctx, it, end); // tag came later, re-parse from the beginning
 4159|       |                  };
 4160|       |                  // `first_key` also answers "were we reset to the object start", which is what
 4161|       |                  // position_after_tag does for every key but the first.
 4162|       |                  for (; *it != '}'; first_key = false) {
 4163|       |                     if (!first_key) {
 4164|       |                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
 4165|       |                           return;
 4166|       |                        }
 4167|       |                     }
 4168|       |
 4169|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4170|       |                        return;
 4171|       |                     }
 4172|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4173|       |                        return;
 4174|       |                     }
 4175|       |
 4176|       |                     auto* key_start = it;
 4177|       |                     skip_string_view(ctx, it, end);
 4178|       |                     if (bool(ctx.error)) [[unlikely]]
 4179|       |                        return;
 4180|       |                     if (validate_utf8_span<Opts>(ctx, key_start, it)) [[unlikely]]
 4181|       |                        return;
 4182|       |                     const sv key = {key_start, size_t(it - key_start)};
 4183|       |
 4184|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4185|       |                        return;
 4186|       |                     }
 4187|       |
 4188|       |                     if constexpr (deduction_key_count > 0) {
 4189|       |                        // We first check if a tag is defined and see if the key matches the tag
 4190|       |                        if constexpr (not tag_v<T>.empty()) {
 4191|       |                           if (key == tag_v<T>) {
 4192|       |                              if (parse_ws_colon<Opts>(ctx, it, end)) {
 4193|       |                                 return;
 4194|       |                              }
 4195|       |
 4196|       |                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
 4197|       |
 4198|       |                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
 4199|       |                              if constexpr (std::integral<id_type>) {
 4200|       |                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
 4201|       |                              }
 4202|       |                              else {
 4203|       |                                 // The id is turned into an index below and never leaves this
 4204|       |                                 // reader, so the view of the window it borrows cannot outlive it.
 4205|       |                                 parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4206|       |                              }
 4207|       |                              if (bool(ctx.error)) [[unlikely]]
 4208|       |                                 return;
 4209|       |                              if (skip_ws<Opts>(ctx, it, end)) {
 4210|       |                                 return;
 4211|       |                              }
 4212|       |                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
 4213|       |                                 ctx.error = error_code::syntax_error;
 4214|       |                                 return;
 4215|       |                              }
 4216|       |
 4217|       |                              size_t type_index;
 4218|       |                              if constexpr (std::integral<id_type>) {
 4219|       |                                 type_index = variant_id_to_index<T>::op(type_id);
 4220|       |                              }
 4221|       |                              else {
 4222|       |                                 type_index = variant_id_to_index<T>::op(
 4223|       |                                    type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4224|       |                              }
 4225|       |                              if (type_index < ids_v<T>.size()) [[likely]] {
 4226|       |                                 // Check if the deduced types include the tag-specified type
 4227|       |                                 // If not, the tag doesn't match the fields
 4228|       |                                 // We're already inside if constexpr (deduction_registry.size()), so we know deduction
 4229|       |                                 // is happening. At this point, possible_types has been narrowed by field deduction.
 4230|       |                                 // Check if the tag-specified type is still possible
 4231|       |                                 const bool type_is_possible = possible_types[type_index];
 4232|       |                                 if (!type_is_possible) {
 4233|       |                                    // Tag specifies a type that doesn't match the fields seen so far
 4234|       |                                    ctx.error = error_code::no_matching_variant_type;
 4235|       |                                    return;
 4236|       |                                 }
 4237|       |
 4238|       |                                 if (!position_after_tag()) return;
 4239|       |                                 tag_specified_index = type_index; // Store the tag-specified type
 4240|       |                                 if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4241|       |                                 std::visit(
 4242|       |                                    [&](auto&& v) {
 4243|       |                                       using V = std::decay_t<decltype(v)>;
 4244|       |                                       constexpr bool is_object =
 4245|       |                                          (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4246|       |                                       if constexpr (variant_unit_alternative<V>) {
 4247|       |                                          // A unit alternative carries no data; its object holds only the
 4248|       |                                          // discriminator. Consume that body through an empty reflected object so
 4249|       |                                          // unknown-key policy and terminator handling match every other alternative.
 4250|       |                                          detail::variant_unit_body unit_body{};
 4251|       |                                          from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4252|       |                                                                                             tag_literal>(unit_body,
 4253|       |                                                                                                          ctx, it, end);
 4254|       |                                       }
 4255|       |                                       else if constexpr (is_object) {
 4256|       |                                          if constexpr (contains_tag<V, tag_literal>()) {
 4257|       |                                             // tag is a struct field, must re-parse
 4258|       |                                             if (!start.rewind(ctx, it, end)) return;
 4259|       |                                          }
 4260|       |                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
 4261|       |                                                                                                           end);
 4262|       |                                       }
 4263|       |                                       else if constexpr (is_memory_object<V>) {
 4264|       |                                          if (!v) {
 4265|       |                                             if constexpr (is_specialization_v<V, std::optional>) {
 4266|       |                                                if constexpr (requires { v.emplace(); }) {
 4267|       |                                                   v.emplace();
 4268|       |                                                }
 4269|       |                                                else {
 4270|       |                                                   v = typename V::value_type{};
 4271|       |                                                }
 4272|       |                                             }
 4273|       |                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4274|       |                                                v = std::make_unique<typename V::element_type>();
 4275|       |                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4276|       |                                                v = std::make_shared<typename V::element_type>();
 4277|       |                                             else if constexpr (constructible<V>) {
 4278|       |                                                v = meta_construct_v<V>();
 4279|       |                                             }
 4280|       |                                             else if constexpr (std::is_pointer_v<V> &&
 4281|       |                                                                can_allocate_raw_pointer<Opts,
 4282|       |                                                                                         std::decay_t<decltype(ctx)>>) {
 4283|       |                                                if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4284|       |                                                   return;
 4285|       |                                                }
 4286|       |                                             }
 4287|       |                                             else {
 4288|       |                                                ctx.error = error_code::invalid_nullable_read;
 4289|       |                                                return;
 4290|       |                                                // Cannot read into unset nullable that is not std::optional,
 4291|       |                                                // std::unique_ptr, or std::shared_ptr
 4292|       |                                             }
 4293|       |                                          }
 4294|       |                                          if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4295|       |                                             // tag is a struct field, must re-parse
 4296|       |                                             if (!start.rewind(ctx, it, end)) return;
 4297|       |                                          }
 4298|       |                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4299|       |                                             *v, ctx, it, end);
 4300|       |                                       }
 4301|       |                                       else if constexpr (custom_read<V>) {
 4302|       |                                          // Custom handlers parse the remaining body themselves and do not
 4303|       |                                          // accept the tag template parameter; the tag was already consumed.
 4304|       |                                          // This only works when the tag was the first key. If it came later,
 4305|       |                                          // we were reset to the object start and the custom handler would
 4306|       |                                          // absorb the tag, so error rather than corrupt the value.
 4307|       |                                          if (!first_key) {
 4308|       |                                             ctx.error = error_code::feature_not_supported;
 4309|       |                                             ctx.custom_error_message =
 4310|       |                                                "the tag must be the first key for a custom variant alternative";
 4311|       |                                             return;
 4312|       |                                          }
 4313|       |                                          from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4314|       |                                       }
 4315|       |                                    },
 4316|       |                                    value);
 4317|       |
 4318|       |                                 return; // we've decoded our target type
 4319|       |                              }
 4320|       |                              else [[unlikely]] {
 4321|       |                                 // Check if we have a default type (ids array shorter than variant)
 4322|       |                                 constexpr auto ids_size = ids_v<T>.size();
 4323|       |                                 constexpr auto variant_size = std::variant_size_v<T>;
 4324|       |                                 if constexpr (ids_size < variant_size) {
 4325|       |                                    // Use the first unlabeled type as the default
 4326|       |                                    const auto default_type_index = ids_size;
 4327|       |
 4328|       |                                    if (!position_after_tag()) return;
 4329|       |                                    tag_specified_index = default_type_index; // Store the default type index
 4330|       |                                    if (value.index() != default_type_index)
 4331|       |                                       emplace_runtime_variant(value, default_type_index);
 4332|       |                                    std::visit(
 4333|       |                                       [&](auto&& v) {
 4334|       |                                          using V = std::decay_t<decltype(v)>;
 4335|       |                                          constexpr bool is_object =
 4336|       |                                             (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4337|       |                                          if constexpr (variant_unit_alternative<V>) {
 4338|       |                                             // A unit alternative carries no data; its object holds only the
 4339|       |                                             // discriminator. Consume that body through an empty reflected object so
 4340|       |                                             // unknown-key policy and terminator handling match every other
 4341|       |                                             // alternative.
 4342|       |                                             detail::variant_unit_body unit_body{};
 4343|       |                                             from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4344|       |                                                                                                tag_literal>(
 4345|       |                                                unit_body, ctx, it, end);
 4346|       |                                          }
 4347|       |                                          else if constexpr (is_object) {
 4348|       |                                             if constexpr (contains_tag<V, tag_literal>()) {
 4349|       |                                                // tag is a struct field, must re-parse
 4350|       |                                                if (!start.rewind(ctx, it, end)) return;
 4351|       |                                             }
 4352|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4353|       |                                          }
 4354|       |                                          else if constexpr (is_memory_object<V>) {
 4355|       |                                             if (!v) {
 4356|       |                                                if constexpr (is_specialization_v<V, std::optional>) {
 4357|       |                                                   if constexpr (requires { v.emplace(); }) {
 4358|       |                                                      v.emplace();
 4359|       |                                                   }
 4360|       |                                                   else {
 4361|       |                                                      v = typename V::value_type{};
 4362|       |                                                   }
 4363|       |                                                }
 4364|       |                                                else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4365|       |                                                   v = std::make_unique<typename V::element_type>();
 4366|       |                                                else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4367|       |                                                   v = std::make_shared<typename V::element_type>();
 4368|       |                                                else if constexpr (constructible<V>) {
 4369|       |                                                   v = meta_construct_v<V>();
 4370|       |                                                }
 4371|       |                                                else if constexpr (std::is_pointer_v<V> &&
 4372|       |                                                                   can_allocate_raw_pointer<
 4373|       |                                                                      Opts, std::decay_t<decltype(ctx)>>) {
 4374|       |                                                   if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4375|       |                                                      return;
 4376|       |                                                   }
 4377|       |                                                }
 4378|       |                                                else {
 4379|       |                                                   ctx.error = error_code::invalid_nullable_read;
 4380|       |                                                   return;
 4381|       |                                                }
 4382|       |                                             }
 4383|       |                                             if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4384|       |                                                // tag is a struct field, must re-parse
 4385|       |                                                if (!start.rewind(ctx, it, end)) return;
 4386|       |                                             }
 4387|       |                                             from<JSON, memory_type<V>>::template op<opening_handled<Opts>()>(*v, ctx,
 4388|       |                                                                                                              it, end);
 4389|       |                                          }
 4390|       |                                          else if constexpr (custom_read<V>) {
 4391|       |                                             // Custom handlers parse the remaining body themselves; this only
 4392|       |                                             // works when the tag was the first key (see above). If it came
 4393|       |                                             // later we were reset to the object start, so error rather than
 4394|       |                                             // let the custom handler absorb the tag.
 4395|       |                                             if (!first_key) {
 4396|       |                                                ctx.error = error_code::feature_not_supported;
 4397|       |                                                ctx.custom_error_message =
 4398|       |                                                   "the tag must be the first key for a custom variant alternative";
 4399|       |                                                return;
 4400|       |                                             }
 4401|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4402|       |                                          }
 4403|       |                                       },
 4404|       |                                       value);
 4405|       |
 4406|       |                                    return;
 4407|       |                                 }
 4408|       |                                 else {
 4409|       |                                    ctx.error = error_code::no_matching_variant_type;
 4410|       |                                    ctx.custom_error_message = variant_ids_string_v<T>;
 4411|       |                                    return;
 4412|       |                                 }
 4413|       |                              }
 4414|       |                           }
 4415|       |                        }
 4416|       |
 4417|       |                        // Inline decode_hash lookup for variant deduction
 4418|       |                        using deduction_keys_t = keys_wrapper<variant_deduction_keys<T>>;
 4419|       |                        constexpr auto& DeductionHashInfo = hash_info<deduction_keys_t>;
 4420|       |                        const auto deduction_index =
 4421|       |                           decode_hash_with_size<JSON, deduction_keys_t, DeductionHashInfo, DeductionHashInfo.type>::op(
 4422|       |                              key.data(), key.data() + key.size(), key.size());
 4423|       |                        if (deduction_index < deduction_key_count && variant_deduction_keys<T>[deduction_index] == key)
 4424|       |                           [[likely]] {
 4425|       |                           possible_types &= deduction_bits[deduction_index];
 4426|       |                        }
 4427|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4428|       |                           ctx.error = error_code::unknown_key;
 4429|       |                           return;
 4430|       |                        }
 4431|       |                     }
 4432|       |                     else if constexpr (not tag_v<T>.empty()) {
 4433|       |                        // empty object case for variant, if there are no normal elements
 4434|       |                        if (key == tag_v<T>) {
 4435|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4436|       |                              return;
 4437|       |                           }
 4438|       |
 4439|       |                           // The id is turned into an index below and never leaves this reader,
 4440|       |                           // so the view of the window it borrows cannot outlive that window.
 4441|       |                           std::string_view type_id{};
 4442|       |                           parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4443|       |                           if (bool(ctx.error)) [[unlikely]]
 4444|       |                              return;
 4445|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4446|       |                              return;
 4447|       |                           }
 4448|       |
 4449|       |                           const auto type_index = variant_id_to_index<T>::op(
 4450|       |                              type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4451|       |                           if (type_index < ids_v<T>.size()) [[likely]] {
 4452|       |                              if (!position_after_tag()) return;
 4453|       |                              tag_specified_index = type_index; // Store the tag-specified type
 4454|       |                              if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4455|       |                           }
 4456|       |                           else {
 4457|       |                              // Check if we have a default type (ids array shorter than variant)
 4458|       |                              constexpr auto ids_size = ids_v<T>.size();
 4459|       |                              constexpr auto variant_size = std::variant_size_v<T>;
 4460|       |                              if constexpr (ids_size < variant_size) {
 4461|       |                                 // Use the first unlabeled type as the default
 4462|       |                                 if (!position_after_tag()) return;
 4463|       |                                 const auto default_index = ids_size;
 4464|       |                                 tag_specified_index = default_index; // Store the default type index
 4465|       |                                 if (value.index() != default_index) emplace_runtime_variant(value, default_index);
 4466|       |                              }
 4467|       |                              else {
 4468|       |                                 ctx.error = error_code::no_matching_variant_type;
 4469|       |                                 ctx.custom_error_message = variant_ids_string_v<T>;
 4470|       |                                 return;
 4471|       |                              }
 4472|       |                           }
 4473|       |                           // Parse the type (handles tag skipping and unknown keys)
 4474|       |                           std::visit(
 4475|       |                              [&](auto&& v) {
 4476|       |                                 using V = std::decay_t<decltype(v)>;
 4477|       |                                 if constexpr (custom_read<V>) {
 4478|       |                                    // Custom handlers parse the remaining object body themselves and do not
 4479|       |                                    // accept the tag template parameter that reflected objects use to skip an
 4480|       |                                    // interior tag key. That only works when the tag is the first key (it was
 4481|       |                                    // just consumed). If the tag came after other keys, position_after_tag()
 4482|       |                                    // reset us to the object start and the custom handler would absorb the tag
 4483|       |                                    // into its value, so error here rather than corrupt the result.
 4484|       |                                    if (!first_key) {
 4485|       |                                       ctx.error = error_code::feature_not_supported;
 4486|       |                                       ctx.custom_error_message =
 4487|       |                                          "the tag must be the first key for a custom variant alternative";
 4488|       |                                       return;
 4489|       |                                    }
 4490|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4491|       |                                 }
 4492|       |                                 else {
 4493|       |                                    if constexpr (contains_tag<V, tag_literal>()) {
 4494|       |                                       // tag is a struct field, must re-parse
 4495|       |                                       if (!start.rewind(ctx, it, end)) return;
 4496|       |                                    }
 4497|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4498|       |                                 }
 4499|       |                              },
 4500|       |                              value);
 4501|       |                           return;
 4502|       |                        }
 4503|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4504|       |                           ctx.error = error_code::unknown_key;
 4505|       |                           return;
 4506|       |                        }
 4507|       |                        else {
 4508|       |                           // Skip unknown key's value (non-tag key in empty variant)
 4509|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4510|       |                              return;
 4511|       |                           }
 4512|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 4513|       |                           if (bool(ctx.error)) [[unlikely]]
 4514|       |                              return;
 4515|       |                           resync_window_end(ctx, end); // a streaming skip refills
 4516|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4517|       |                              return;
 4518|       |                           }
 4519|       |                           continue; // Continue loop to find the tag
 4520|       |                        }
 4521|       |                     }
 4522|       |                     else if constexpr (Opts.error_on_unknown_keys) {
 4523|       |                        ctx.error = error_code::unknown_key;
 4524|       |                        return;
 4525|       |                     }
 4526|       |
 4527|       |                     auto matching_types = possible_types.popcount();
 4528|       |                     if (matching_types == 0) {
 4529|       |                        ctx.error = error_code::no_matching_variant_type;
 4530|       |                        return;
 4531|       |                     }
 4532|       |                     // Only short-circuit for variants without tags
 4533|       |                     else if constexpr (tag_v<T>.empty()) {
 4534|       |                        if (matching_types == 1) {
 4535|       |                           if (!start.rewind(ctx, it, end)) return;
 4536|       |                           const auto type_index = possible_types.countr_zero();
 4537|       |
 4538|       |                           if (value.index() != static_cast<size_t>(type_index))
 4539|       |                              emplace_runtime_variant(value, type_index);
 4540|       |                           std::visit(
 4541|       |                              [&](auto&& v) {
 4542|       |                                 using V = std::decay_t<decltype(v)>;
 4543|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4544|       |                                 if constexpr (variant_unit_alternative<V>) {
 4545|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4546|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4547|       |                                    // terminator handling match every other alternative.
 4548|       |                                    detail::variant_unit_body unit_body{};
 4549|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4550|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4551|       |                                                                                                    end);
 4552|       |                                 }
 4553|       |                                 else if constexpr (is_object) {
 4554|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4555|       |                                 }
 4556|       |                                 else if constexpr (is_memory_object<V>) {
 4557|       |                                    if (!v) {
 4558|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4559|       |                                          if constexpr (requires { v.emplace(); }) {
 4560|       |                                             v.emplace();
 4561|       |                                          }
 4562|       |                                          else {
 4563|       |                                             v = typename V::value_type{};
 4564|       |                                          }
 4565|       |                                       }
 4566|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4567|       |                                          v = std::make_unique<typename V::element_type>();
 4568|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4569|       |                                          v = std::make_shared<typename V::element_type>();
 4570|       |                                       else if constexpr (constructible<V>) {
 4571|       |                                          v = meta_construct_v<V>();
 4572|       |                                       }
 4573|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4574|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4575|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4576|       |                                             return;
 4577|       |                                          }
 4578|       |                                       }
 4579|       |                                       else {
 4580|       |                                          ctx.error = error_code::invalid_nullable_read;
 4581|       |                                          return;
 4582|       |                                          // Cannot read into unset nullable that is not std::optional,
 4583|       |                                          // std::unique_ptr, or std::shared_ptr
 4584|       |                                       }
 4585|       |                                    }
 4586|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4587|       |                                       *v, ctx, it, end);
 4588|       |                                 }
 4589|       |                                 else if constexpr (custom_read<V>) {
 4590|       |                                    // Custom handlers parse the remaining body themselves.
 4591|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4592|       |                                 }
 4593|       |                              },
 4594|       |                              value);
 4595|       |
 4596|       |                           return; // we've decoded our target type
 4597|       |                        }
 4598|       |                     }
 4599|       |                     // For tagged variants, continue processing to validate tags
 4600|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 4601|       |                        return;
 4602|       |                     }
 4603|       |
 4604|       |                     skip_value<JSON>::op<Opts>(ctx, it, end);
 4605|       |                     if (bool(ctx.error)) [[unlikely]]
 4606|       |                        return;
 4607|       |                     resync_window_end(ctx, end); // a streaming skip refills
 4608|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4609|       |                        return;
 4610|       |                     }
 4611|       |                  }
 4612|       |                  // Only apply ambiguous variant resolution if we have multiple object types
 4613|       |                  if constexpr ((type_counts::n_object + type_counts::n_nullable_object) > 1) {
 4614|       |                     // After parsing all keys, check if we have multiple matching types
 4615|       |                     // If so, choose the one with the fewest fields
 4616|       |                     auto final_matching = possible_types.popcount();
 4617|       |                     if (final_matching == 0) {
 4618|       |                        ctx.error = error_code::no_matching_variant_type;
 4619|       |                     }
 4620|       |                     else if (final_matching == 1) {
 4621|       |                        // Single type remains after field deduction
 4622|       |                        const auto type_index = possible_types.countr_zero();
 4623|       |
 4624|       |                        // Validate against tag if one was specified
 4625|       |                        if (tag_specified_index.has_value() &&
 4626|       |                            tag_specified_index.value() != static_cast<size_t>(type_index)) {
 4627|       |                           ctx.error = error_code::no_matching_variant_type;
 4628|       |                           return;
 4629|       |                        }
 4630|       |
 4631|       |                        if (!start.rewind(ctx, it, end)) return;
 4632|       |                        if (value.index() != static_cast<size_t>(type_index))
 4633|       |                           emplace_runtime_variant(value, type_index);
 4634|       |                        std::visit(
 4635|       |                           [&](auto&& v) {
 4636|       |                              using V = std::decay_t<decltype(v)>;
 4637|       |                              constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4638|       |                              if constexpr (variant_unit_alternative<V>) {
 4639|       |                                 // A unit alternative carries no data; its object holds only the discriminator.
 4640|       |                                 // Consume that body through an empty reflected object so unknown-key policy and
 4641|       |                                 // terminator handling match every other alternative.
 4642|       |                                 detail::variant_unit_body unit_body{};
 4643|       |                                 from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4644|       |                                                                                    tag_literal>(unit_body, ctx, it,
 4645|       |                                                                                                 end);
 4646|       |                              }
 4647|       |                              else if constexpr (is_object) {
 4648|       |                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4649|       |                              }
 4650|       |                              else if constexpr (is_memory_object<V>) {
 4651|       |                                 if (!v) {
 4652|       |                                    if constexpr (is_specialization_v<V, std::optional>) {
 4653|       |                                       if constexpr (requires { v.emplace(); }) {
 4654|       |                                          v.emplace();
 4655|       |                                       }
 4656|       |                                       else {
 4657|       |                                          v = typename V::value_type{};
 4658|       |                                       }
 4659|       |                                    }
 4660|       |                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4661|       |                                       v = std::make_unique<typename V::element_type>();
 4662|       |                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4663|       |                                       v = std::make_shared<typename V::element_type>();
 4664|       |                                    else if constexpr (constructible<V>) {
 4665|       |                                       v = meta_construct_v<V>();
 4666|       |                                    }
 4667|       |                                    else if constexpr (std::is_pointer_v<V> &&
 4668|       |                                                       can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4669|       |                                       if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4670|       |                                          return;
 4671|       |                                       }
 4672|       |                                    }
 4673|       |                                    else {
 4674|       |                                       ctx.error = error_code::invalid_nullable_read;
 4675|       |                                       return;
 4676|       |                                    }
 4677|       |                                 }
 4678|       |                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
 4679|       |                                                                                                               it, end);
 4680|       |                              }
 4681|       |                              else if constexpr (custom_read<V>) {
 4682|       |                                 // Custom handlers parse the remaining body themselves.
 4683|       |                                 from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4684|       |                              }
 4685|       |                           },
 4686|       |                           value);
 4687|       |                     }
 4688|       |                     else if (final_matching > 1) {
 4689|       |                        constexpr auto N = std::variant_size_v<T>;
 4690|       |
 4691|       |                        // Compile-time array of field counts for each variant type
 4692|       |                        constexpr auto field_counts = []<size_t... I>(std::index_sequence<I...>) {
 4693|       |                           return std::array<size_t, N> {
 4694|       |                              ([]<size_t J = I>() -> size_t {
 4695|       |                                 using V = std::decay_t<std::variant_alternative_t<J, T>>;
 4696|       |                                 if constexpr (glaze_object_t<V> || reflectable<V>) {
 4697|       |                                    return reflect<V>::size;
 4698|       |                                 }
 4699|       |                                 else if constexpr (is_memory_object<V>) {
 4700|       |                                    using X = memory_type<V>;
 4701|       |                                    if constexpr (glaze_object_t<X> || reflectable<X>) {
 4702|       |                                       return reflect<X>::size;
 4703|       |                                    }
 4704|       |                                    else {
 4705|       |                                       return (std::numeric_limits<size_t>::max)();
 4706|       |                                    }
 4707|       |                                 }
 4708|       |                                 else {
 4709|       |                                    return (std::numeric_limits<size_t>::max)();
 4710|       |                                 }
 4711|       |                              }.template operator()<I>())...
 4712|       |                           };
 4713|       |                        }(std::make_index_sequence<N>{});
 4714|       |
 4715|       |                        // Find the type with minimum field count among the possible types
 4716|       |                        size_t min_fields = (std::numeric_limits<size_t>::max)();
 4717|       |                        size_t chosen_index = N; // Invalid index initially
 4718|       |
 4719|       |                        for (size_t i = 0; i < N; ++i) {
 4720|       |                           if (possible_types[i] && field_counts[i] < min_fields) {
 4721|       |                              min_fields = field_counts[i];
 4722|       |                              chosen_index = i;
 4723|       |                           }
 4724|       |                        }
 4725|       |
 4726|       |                        if (chosen_index < N) {
 4727|       |                           // Validate against tag if one was specified
 4728|       |                           if (tag_specified_index.has_value() && tag_specified_index.value() != chosen_index) {
 4729|       |                              ctx.error = error_code::no_matching_variant_type;
 4730|       |                              return;
 4731|       |                           }
 4732|       |
 4733|       |                           if (!start.rewind(ctx, it, end)) return;
 4734|       |                           if (value.index() != chosen_index) emplace_runtime_variant(value, chosen_index);
 4735|       |                           std::visit(
 4736|       |                              [&](auto&& v) {
 4737|       |                                 using V = std::decay_t<decltype(v)>;
 4738|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4739|       |                                 if constexpr (variant_unit_alternative<V>) {
 4740|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4741|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4742|       |                                    // terminator handling match every other alternative.
 4743|       |                                    detail::variant_unit_body unit_body{};
 4744|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4745|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4746|       |                                                                                                    end);
 4747|       |                                 }
 4748|       |                                 else if constexpr (is_object) {
 4749|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4750|       |                                 }
 4751|       |                                 else if constexpr (is_memory_object<V>) {
 4752|       |                                    if (!v) {
 4753|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4754|       |                                          if constexpr (requires { v.emplace(); }) {
 4755|       |                                             v.emplace();
 4756|       |                                          }
 4757|       |                                          else {
 4758|       |                                             v = typename V::value_type{};
 4759|       |                                          }
 4760|       |                                       }
 4761|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4762|       |                                          v = std::make_unique<typename V::element_type>();
 4763|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4764|       |                                          v = std::make_shared<typename V::element_type>();
 4765|       |                                       else if constexpr (constructible<V>) {
 4766|       |                                          v = meta_construct_v<V>();
 4767|       |                                       }
 4768|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4769|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4770|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4771|       |                                             return;
 4772|       |                                          }
 4773|       |                                       }
 4774|       |                                       else {
 4775|       |                                          ctx.error = error_code::invalid_nullable_read;
 4776|       |                                          return;
 4777|       |                                       }
 4778|       |                                    }
 4779|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4780|       |                                       *v, ctx, it, end);
 4781|       |                                 }
 4782|       |                                 else if constexpr (custom_read<V>) {
 4783|       |                                    // Custom handlers parse the remaining body themselves.
 4784|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4785|       |                                 }
 4786|       |                              },
 4787|       |                              value);
 4788|       |                        }
 4789|       |                        else {
 4790|       |                           ctx.error = error_code::no_matching_variant_type;
 4791|       |                        }
 4792|       |                     }
 4793|       |                  }
 4794|       |                  else {
 4795|       |                     // For variants with 0 or 1 object types, use the original error handling
 4796|       |                     ctx.error = error_code::no_matching_variant_type;
 4797|       |                  }
 4798|       |               }
 4799|      0|               break;
 4800|  5.14k|            }
 4801|  2.19k|            case '[':
  ------------------
  |  Branch (4801:13): [True: 2.19k, False: 9.12k]
  ------------------
 4802|       |               // As with '{' above: the array reader each alternative goes through counts the level.
 4803|  2.19k|               process_variant_alternatives<T, is_variant_array>::template op<Opts>(value, ctx, it, end);
 4804|  2.19k|               break;
 4805|  1.15k|            case '"': {
  ------------------
  |  Branch (4805:13): [True: 1.15k, False: 10.1k]
  ------------------
 4806|  1.15k|               process_variant_alternatives<T, is_variant_str>::template op<Opts>(value, ctx, it, end);
 4807|  1.15k|               break;
 4808|  5.14k|            }
 4809|     78|            case 't':
  ------------------
  |  Branch (4809:13): [True: 78, False: 11.2k]
  ------------------
 4810|    184|            case 'f': {
  ------------------
  |  Branch (4810:13): [True: 106, False: 11.2k]
  ------------------
 4811|    184|               process_variant_alternatives<T, is_variant_bool>::template op<Opts>(value, ctx, it, end);
 4812|    184|               break;
 4813|     78|            }
 4814|     74|            case 'n':
  ------------------
  |  Branch (4814:13): [True: 74, False: 11.2k]
  ------------------
 4815|       |               if constexpr (variant_count_v<T, is_variant_null> == 0) {
 4816|       |                  ctx.error = error_code::no_matching_variant_type;
 4817|       |               }
 4818|     74|               else {
 4819|     74|                  constexpr auto first_idx = variant_first_index_v<T, is_variant_null>;
 4820|     74|                  using V = std::variant_alternative_t<first_idx, T>;
 4821|     74|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4821:23): [True: 0, False: 74]
  ------------------
 4822|     74|                  match<"null", Opts>(ctx, it, end);
 4823|     74|               }
 4824|     74|               break;
 4825|  2.55k|            default: {
  ------------------
  |  Branch (4825:13): [True: 2.55k, False: 8.76k]
  ------------------
 4826|       |               // Not bool, string, object, or array so must be number or null
 4827|  2.55k|               process_variant_alternatives<T, is_variant_num>::template op<Opts>(value, ctx, it, end);
 4828|  2.55k|            }
 4829|  11.3k|            }
 4830|       |         }
 4831|       |         else {
 4832|       |            // For non-auto-deducible variants, try each type until one succeeds
 4833|       |            constexpr auto N = std::variant_size_v<T>;
 4834|       |            bool parsed = false;
 4835|       |            bool exhausted = false; // speculation budget spent; see charge_speculation
 4836|       |
 4837|       |            for_each<N>([&]<size_t I>() {
 4838|       |               if (parsed || exhausted || variant_alternative_exhausted(ctx)) return;
 4839|       |
 4840|       |               auto copy_it = it;
 4841|       |               // A rejected alternative may have bailed out inside a container, which leaves its
 4842|       |               // nesting level counted (see enter_depth), so the depth rewinds with the iterator.
 4843|       |               const auto copy_depth = ctx.depth;
 4844|       |
 4845|       |               // Try parsing as this type
 4846|       |               if (value.index() != I) {
 4847|       |                  emplace_runtime_variant(value, I);
 4848|       |               }
 4849|       |
 4850|       |               std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
 4851|       |               if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 4852|       |                  exhausted = true; // only rejected attempts are charged; see charge_speculation
 4853|       |               }
 4854|       |
 4855|       |               if (!bool(ctx.error)) {
 4856|       |                  parsed = true;
 4857|       |               }
 4858|       |               else if constexpr (not Options.null_terminated) {
 4859|       |                  // In non-null-terminated mode, if we hit end_reached after advancing the iterator,
 4860|       |                  // it means we successfully parsed the value but couldn't skip trailing whitespace
 4861|       |                  if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 4862|       |                     // We advanced the iterator, so we did parse something -- unless what advanced it
 4863|       |                     // was an abandoned attempt, which is what a spent speculation budget means.
 4864|       |                     parsed = true;
 4865|       |                     ctx.error = error_code::none;
 4866|       |                  }
 4867|       |                  else {
 4868|       |                     // Reset for next attempt (unless this is the last type)
 4869|       |                     it = copy_it;
 4870|       |                     rewind_depth<Options>(ctx, copy_depth);
 4871|       |                     if constexpr (I + 1 < N) {
 4872|       |                        if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4873|       |                           ctx.error = error_code::none; // Clear error for next attempt
 4874|       |                        }
 4875|       |                     }
 4876|       |                  }
 4877|       |               }
 4878|       |               else {
 4879|       |                  // Reset for next attempt (unless this is the last type)
 4880|       |                  it = copy_it;
 4881|       |                  rewind_depth<Options>(ctx, copy_depth);
 4882|       |                  if constexpr (I + 1 < N) {
 4883|       |                     if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4884|       |                        ctx.error = error_code::none; // Clear error for next attempt
 4885|       |                     }
 4886|       |                  }
 4887|       |               }
 4888|       |            });
 4889|       |         }
 4890|  11.3k|      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj1EEERNS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES4_EEEETkNS_10is_contextERNS_7contextERPKcSD_EEvOT0_OT1_OT2_T3_:
   49|  27.5k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  27.5k|         else {
   60|  27.5k|            using V = std::remove_cvref_t<T>;
   61|  27.5k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  27.5k|                                             end);
   63|  27.5k|         }
   64|  27.5k|      }
_ZN3glz4fromILj10ENS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES1_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNS9_ILm1EEEEERS5_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT1_OT2_OT3_T4_:
 3044|  27.5k|      {
 3045|  27.5k|         static constexpr auto num_members = reflect<T>::size;
 3046|       |
 3047|  27.5k|         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
 3048|       |         if constexpr (!check_opening_handled(Options)) {
 3049|       |            if constexpr (!check_ws_handled(Options)) {
 3050|       |               if (skip_ws<Opts>(ctx, it, end)) {
 3051|       |                  return;
 3052|       |               }
 3053|       |            }
 3054|       |            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
 3055|       |               return;
 3056|       |            }
 3057|       |            if constexpr (not Opts.null_terminated) {
 3058|       |               if (it == end) [[unlikely]] {
 3059|       |                  ctx.error = error_code::unexpected_end;
 3060|       |                  return;
 3061|       |               }
 3062|       |            }
 3063|       |            // one nesting level (see enter_depth): counted in both modes so the limit binds,
 3064|       |            // released at each syntactic close below
 3065|       |            if (enter_depth(ctx)) [[unlikely]] {
 3066|       |               return;
 3067|       |            }
 3068|       |         }
 3069|  27.5k|         const auto ws_start = it;
 3070|  27.5k|         if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3070:14): [True: 0, False: 27.5k]
  ------------------
 3071|      0|            return;
 3072|      0|         }
 3073|  27.5k|         const size_t ws_size = size_t(it - ws_start);
 3074|       |
 3075|       |         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
 3076|       |            if constexpr (not tag.sv().empty()) {
 3077|       |               if (*it == '"') {
 3078|       |                  ++it;
 3079|       |                  if constexpr (not Opts.null_terminated) {
 3080|       |                     if (it == end) [[unlikely]] {
 3081|       |                        ctx.error = error_code::unexpected_end;
 3082|       |                        return;
 3083|       |                     }
 3084|       |                  }
 3085|       |
 3086|       |                  const auto start = it;
 3087|       |                  skip_string_view(ctx, it, end);
 3088|       |                  if (bool(ctx.error)) [[unlikely]]
 3089|       |                     return;
 3090|       |                  if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]]
 3091|       |                     return;
 3092|       |                  const sv key{start, size_t(it - start)};
 3093|       |                  ++it;
 3094|       |                  if constexpr (not Opts.null_terminated) {
 3095|       |                     if (it == end) [[unlikely]] {
 3096|       |                        ctx.error = error_code::unexpected_end;
 3097|       |                        return;
 3098|       |                     }
 3099|       |                  }
 3100|       |
 3101|       |                  if (key == tag.sv()) {
 3102|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3103|       |                        return;
 3104|       |                     }
 3105|       |
 3106|       |                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
 3107|       |                     if (bool(ctx.error)) [[unlikely]]
 3108|       |                        return;
 3109|       |
 3110|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 3111|       |                        return;
 3112|       |                     }
 3113|       |                  }
 3114|       |                  else {
 3115|       |                     ctx.error = error_code::unknown_key;
 3116|       |                     return;
 3117|       |                  }
 3118|       |               }
 3119|       |            }
 3120|       |
 3121|       |            if (*it == '}') [[likely]] {
 3122|       |               --ctx.depth;
 3123|       |               if constexpr (glaze_object_t<T> || reflectable<T>) {
 3124|       |                  if constexpr (has_self_constraint_v<T> && !check_skip_self_constraint(Opts)) {
 3125|       |                     auto wrapper = self_constraint_v<T>(value);
 3126|       |                     from<JSON, decltype(wrapper)>::template op<ws_handled<Opts>()>(wrapper, ctx, it, end);
 3127|       |                     if (bool(ctx.error)) {
 3128|       |                        return;
 3129|       |                     }
 3130|       |                  }
 3131|       |               }
 3132|       |               ++it;
 3133|       |               if constexpr (not Opts.null_terminated) {
 3134|       |                  if (it == end) {
 3135|       |                     ctx.error = error_code::end_reached;
 3136|       |                     return;
 3137|       |                  }
 3138|       |               }
 3139|       |               if constexpr (Opts.partial_read) {
 3140|       |                  ctx.error = error_code::partial_read_complete;
 3141|       |               }
 3142|       |               return;
 3143|       |            }
 3144|       |            ctx.error = error_code::unknown_key;
 3145|       |            return;
 3146|       |         }
 3147|  27.5k|         else {
 3148|  27.5k|            decltype(auto) fields = [&]() -> decltype(auto) {
 3149|  27.5k|               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
 3150|  27.5k|                             (Opts.error_on_missing_keys || Opts.partial_read)) {
 3151|  27.5k|                  return bit_array<num_members>{};
 3152|  27.5k|               }
 3153|  27.5k|               else {
 3154|  27.5k|                  return nullptr;
 3155|  27.5k|               }
 3156|  27.5k|            }();
 3157|       |
 3158|  27.5k|            size_t read_count{}; // for partial_read
 3159|       |
 3160|  27.5k|            bool first = true;
 3161|  1.14M|            while (true) {
  ------------------
  |  Branch (3161:20): [True: 1.11M, Folded]
  ------------------
 3162|       |               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
 3163|       |                  static constexpr bit_array<num_members> all_fields = [] {
 3164|       |                     bit_array<num_members> arr{};
 3165|       |                     for (size_t i = 0; i < num_members; ++i) {
 3166|       |                        arr[i] = true;
 3167|       |                     }
 3168|       |                     return arr;
 3169|       |                  }();
 3170|       |
 3171|       |                  if ((all_fields & fields) == all_fields) {
 3172|       |                     ctx.error = error_code::partial_read_complete;
 3173|       |                     --ctx.depth; // as above: an early success still closes this level
 3174|       |                     return;
 3175|       |                  }
 3176|       |               }
 3177|       |
 3178|       |               // Streaming refill point: at start of each iteration, ensure buffer has data
 3179|       |               if constexpr (has_streaming_state<decltype(ctx)>) {
 3180|       |                  if (ctx.stream.enabled()) {
 3181|       |                     const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 3182|       |                     const size_t remaining = ctx.stream.size() - consumed;
 3183|       |                     // Refill when less than half of buffer remains to ensure space for next key-value pair
 3184|       |                     if (remaining <= ctx.stream.size() / 2 || it >= end) {
 3185|       |                        const char* new_it;
 3186|       |                        const char* new_end;
 3187|       |                        ctx.stream.consume_and_refill(consumed, new_it, new_end);
 3188|       |                        it = new_it;
 3189|       |                        end = new_end;
 3190|       |                        if (it >= end && ctx.stream.at_eof()) {
 3191|       |                           ctx.error = error_code::unexpected_end;
 3192|       |                           return;
 3193|       |                        }
 3194|       |                     }
 3195|       |                  }
 3196|       |               }
 3197|       |
 3198|  1.11M|               if (*it == '}') {
  ------------------
  |  Branch (3198:20): [True: 2.05k, False: 1.11M]
  ------------------
 3199|  2.05k|                  --ctx.depth;
 3200|       |                  if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
 3201|       |                     constexpr auto req_fields = required_fields<T, Opts>();
 3202|       |                     if ((req_fields & fields) != req_fields) {
 3203|       |                        for (size_t i = 0; i < num_members; ++i) {
 3204|       |                           if (not fields[i] && req_fields[i]) {
 3205|       |                              ctx.custom_error_message = reflect<T>::keys[i];
 3206|       |                              // We just return the first missing key in order to avoid heap allocations
 3207|       |                              break;
 3208|       |                           }
 3209|       |                        }
 3210|       |
 3211|       |                        ctx.error = error_code::missing_key;
 3212|       |                        return;
 3213|       |                     }
 3214|       |                  }
 3215|       |                  if constexpr (glaze_object_t<T> || reflectable<T>) {
 3216|       |                     if constexpr (has_self_constraint_v<T> && !check_skip_self_constraint(Opts)) {
 3217|       |                        auto wrapper = self_constraint_v<T>(value);
 3218|       |                        from<JSON, decltype(wrapper)>::template op<ws_handled<Opts>()>(wrapper, ctx, it, end);
 3219|       |                        if (bool(ctx.error)) {
 3220|       |                           return;
 3221|       |                        }
 3222|       |                     }
 3223|       |                  }
 3224|  2.05k|                  ++it; // Increment after checking for missing keys so errors are within buffer bounds
 3225|       |                  if constexpr (not Opts.null_terminated) {
 3226|       |                     if (it == end) {
 3227|       |                        ctx.error = error_code::end_reached;
 3228|       |                        return;
 3229|       |                     }
 3230|       |                  }
 3231|  2.05k|                  return;
 3232|  2.05k|               }
 3233|  1.11M|               else if (first) {
  ------------------
  |  Branch (3233:25): [True: 25.8k, False: 1.08M]
  ------------------
 3234|  25.8k|                  first = false;
 3235|  25.8k|               }
 3236|  1.08M|               else {
 3237|  1.08M|                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3237:23): [True: 514, False: 1.08M]
  ------------------
 3238|    514|                     return;
 3239|    514|                  }
 3240|       |                  if constexpr (not Opts.null_terminated) {
 3241|       |                     if (it == end) [[unlikely]] {
 3242|       |                        ctx.error = error_code::unexpected_end;
 3243|       |                        return;
 3244|       |                     }
 3245|       |                  }
 3246|       |
 3247|       |                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys) &&
 3248|       |                                (!Opts.comments)) {
 3249|       |                     if (ws_size && ws_size < size_t(end - it)) {
 3250|       |                        skip_matching_ws(ws_start, it, ws_size);
 3251|       |                     }
 3252|       |                  }
 3253|       |
 3254|  1.08M|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3254:23): [True: 0, False: 1.08M]
  ------------------
 3255|      0|                     return;
 3256|      0|                  }
 3257|  1.08M|               }
 3258|       |
 3259|  1.11M|               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
  ------------------
  |  Branch (3259:49): [Folded, False: 0]
  |  Branch (3259:70): [Folded, False: 0]
  ------------------
 3260|       |
 3261|       |               if constexpr (reflection_type && (num_members == 0)) {
 3262|       |                  if constexpr (Opts.error_on_unknown_keys) {
 3263|       |                     static_assert(false_v<T>, "This should be unreachable");
 3264|       |                  }
 3265|       |                  else {
 3266|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 3267|       |                        return;
 3268|       |                     }
 3269|       |
 3270|       |                     // parsing to an empty object, but at this point the JSON presents keys
 3271|       |
 3272|       |                     // Unknown key handler does not unescape keys. Unknown escaped keys are
 3273|       |                     // handled by the user.
 3274|       |
 3275|       |                     const auto start = it;
 3276|       |                     skip_string_view(ctx, it, end);
 3277|       |                     if (bool(ctx.error)) [[unlikely]]
 3278|       |                        return;
 3279|       |                     if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]]
 3280|       |                        return;
 3281|       |                     const sv key{start, size_t(it - start)};
 3282|       |                     ++it;
 3283|       |                     if constexpr (not Opts.null_terminated) {
 3284|       |                        if (it == end) [[unlikely]] {
 3285|       |                           ctx.error = error_code::unexpected_end;
 3286|       |                           return;
 3287|       |                        }
 3288|       |                     }
 3289|       |
 3290|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3291|       |                        return;
 3292|       |                     }
 3293|       |
 3294|       |                     // Check if this key is the variant tag that should be skipped
 3295|       |                     if constexpr (not tag.sv().empty()) {
 3296|       |                        if (key == tag.sv()) {
 3297|       |                           // Skip the tag value
 3298|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 3299|       |                           if (bool(ctx.error)) [[unlikely]]
 3300|       |                              return;
 3301|       |                           resync_window_end(ctx, end); // a streaming skip refills
 3302|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 3303|       |                              return;
 3304|       |                           }
 3305|       |                           continue;
 3306|       |                        }
 3307|       |                     }
 3308|       |
 3309|       |                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
 3310|       |                     if (bool(ctx.error)) [[unlikely]]
 3311|       |                        return;
 3312|       |                     if constexpr (not Opts.null_terminated) {
 3313|       |                        if (it == end) [[unlikely]] {
 3314|       |                           ctx.error = error_code::unexpected_end;
 3315|       |                           return;
 3316|       |                        }
 3317|       |                     }
 3318|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 3319|       |                        return;
 3320|       |                     }
 3321|       |                  }
 3322|       |               }
 3323|       |               else if constexpr (reflection_type) {
 3324|       |                  static_assert(bool(hash_info<T>.type));
 3325|       |
 3326|       |                  if (*it != '"') [[unlikely]] {
 3327|       |                     ctx.error = error_code::expected_quote;
 3328|       |                     return;
 3329|       |                  }
 3330|       |                  ++it;
 3331|       |                  if constexpr (not Opts.null_terminated) {
 3332|       |                     if (it == end) [[unlikely]] {
 3333|       |                        ctx.error = error_code::unexpected_end;
 3334|       |                        return;
 3335|       |                     }
 3336|       |                  }
 3337|       |
 3338|       |                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
 3339|       |                     // For tagged variants we first check to see if the key matches the tag
 3340|       |                     // We only need to do this if the tag is not part of the keys
 3341|       |
 3342|       |                     const auto start = it;
 3343|       |                     skip_string_view(ctx, it, end);
 3344|       |                     if (bool(ctx.error)) [[unlikely]]
 3345|       |                        return;
 3346|       |                     if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]]
 3347|       |                        return;
 3348|       |                     const sv key{start, size_t(it - start)};
 3349|       |                     ++it;
 3350|       |                     if constexpr (not Opts.null_terminated) {
 3351|       |                        if (it == end) [[unlikely]] {
 3352|       |                           ctx.error = error_code::unexpected_end;
 3353|       |                           return;
 3354|       |                        }
 3355|       |                     }
 3356|       |
 3357|       |                     if (key == tag.sv()) {
 3358|       |                        if (parse_ws_colon<Opts>(ctx, it, end)) {
 3359|       |                           return;
 3360|       |                        }
 3361|       |
 3362|       |                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
 3363|       |                        if (bool(ctx.error)) [[unlikely]]
 3364|       |                           return;
 3365|       |
 3366|       |                        if (skip_ws<Opts>(ctx, it, end)) {
 3367|       |                           return;
 3368|       |                        }
 3369|       |                        continue;
 3370|       |                     }
 3371|       |                     else {
 3372|       |                        it = start; // reset the iterator
 3373|       |                     }
 3374|       |                  }
 3375|       |
 3376|       |                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
 3377|       |                     size_t index = num_members;
 3378|       |                     parse_and_invoke<Opts, T>(value, ctx, it, end, index);
 3379|       |                     if (bool(ctx.error)) [[unlikely]]
 3380|       |                        return;
 3381|       |                     if (index < num_members) {
 3382|       |                        fields[index] = true;
 3383|       |                     }
 3384|       |                  }
 3385|       |                  else {
 3386|       |                     parse_and_invoke<Opts, T>(value, ctx, it, end);
 3387|       |                     if (bool(ctx.error)) [[unlikely]]
 3388|       |                        return;
 3389|       |                  }
 3390|       |               }
 3391|  1.11M|               else {
 3392|       |                  // For types like std::map, std::unordered_map
 3393|       |
 3394|  1.11M|                  auto reading = [&](auto&& key) {
 3395|  1.11M|                     if constexpr (Opts.partial_read) {
 3396|  1.11M|                        if (auto element = value.find(key); element != value.end()) {
 3397|  1.11M|                           ++read_count;
 3398|  1.11M|                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
 3399|  1.11M|                        }
 3400|  1.11M|                        else {
 3401|  1.11M|                           skip_value<JSON>::op<Opts>(ctx, it, end);
 3402|  1.11M|                        }
 3403|  1.11M|                     }
 3404|  1.11M|                     else {
 3405|  1.11M|                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
 3406|  1.11M|                     }
 3407|  1.11M|                  };
 3408|       |
 3409|       |                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
 3410|  1.11M|                  using Key = typename T::key_type;
 3411|  1.11M|                  if constexpr (std::is_same_v<Key, std::string>) {
 3412|  1.11M|                     ctx.scratch.clear();
 3413|  1.11M|                     parse<JSON>::op<Opts>(ctx.scratch, ctx, it, end);
 3414|  1.11M|                     if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (3414:26): [True: 1.38k, False: 1.11M]
  ------------------
 3415|  1.38k|                        return;
 3416|       |
 3417|  1.11M|                     if (parse_ws_colon<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3417:26): [True: 739, False: 1.11M]
  ------------------
 3418|    739|                        return;
 3419|    739|                     }
 3420|       |
 3421|  1.11M|                     reading(ctx.scratch);
 3422|       |                     if constexpr (Opts.partial_read) {
 3423|       |                        if (read_count == value.size()) {
 3424|       |                           return;
 3425|       |                        }
 3426|       |                     }
 3427|  1.11M|                     if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (3427:26): [True: 22.8k, False: 1.09M]
  ------------------
 3428|  22.8k|                        return;
 3429|       |                  }
 3430|       |                  else if constexpr (str_t<Key>) {
 3431|       |                     Key key;
 3432|       |                     parse<JSON>::op<Opts>(key, ctx, it, end);
 3433|       |                     if (bool(ctx.error)) [[unlikely]]
 3434|       |                        return;
 3435|       |
 3436|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3437|       |                        return;
 3438|       |                     }
 3439|       |
 3440|       |                     reading(key);
 3441|       |                     if constexpr (Opts.partial_read) {
 3442|       |                        if (read_count == value.size()) {
 3443|       |                           return;
 3444|       |                        }
 3445|       |                     }
 3446|       |                     if (bool(ctx.error)) [[unlikely]]
 3447|       |                        return;
 3448|       |                  }
 3449|       |                  else {
 3450|       |                     Key key_value{};
 3451|       |                     if constexpr (is_named_enum<Key> || mimics_str_t<Key>) {
 3452|       |                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
 3453|       |                     }
 3454|       |                     else if constexpr (std::is_arithmetic_v<Key>) {
 3455|       |                        // prefer over quoted_t below to avoid double parsing of quoted_t
 3456|       |                        parse<JSON>::op<opt_true<Opts, quoted_num_opt_tag{}>>(key_value, ctx, it, end);
 3457|       |                     }
 3458|       |                     else {
 3459|       |                        parse<JSON>::op<opt_false<Opts, raw_string_opt_tag{}>>(quoted_t<Key>{key_value}, ctx, it, end);
 3460|       |                     }
 3461|       |                     if (bool(ctx.error)) [[unlikely]]
 3462|       |                        return;
 3463|       |
 3464|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3465|       |                        return;
 3466|       |                     }
 3467|       |
 3468|       |                     reading(key_value);
 3469|       |                     if constexpr (Opts.partial_read) {
 3470|       |                        if (read_count == value.size()) {
 3471|       |                           return;
 3472|       |                        }
 3473|       |                     }
 3474|       |                     if (bool(ctx.error)) [[unlikely]]
 3475|       |                        return;
 3476|       |                  }
 3477|  1.11M|               }
 3478|       |
 3479|       |               // Streaming refill point: after parsing each key-value pair, refill if buffer is low
 3480|       |               if constexpr (has_streaming_state<decltype(ctx)>) {
 3481|       |                  if (ctx.stream.enabled()) {
 3482|       |                     const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 3483|       |                     // Refill when less than 25% of buffer remains to ensure enough space for next element
 3484|       |                     if (ctx.stream.size() - consumed <= ctx.stream.size() / 4 || it >= end) {
 3485|       |                        const char* new_it;
 3486|       |                        const char* new_end;
 3487|       |                        ctx.stream.consume_and_refill(consumed, new_it, new_end);
 3488|       |                        it = new_it;
 3489|       |                        end = new_end;
 3490|       |                        if (it >= end && ctx.stream.at_eof()) {
 3491|       |                           ctx.error = error_code::unexpected_end;
 3492|       |                           return;
 3493|       |                        }
 3494|       |                     }
 3495|       |                  }
 3496|       |               }
 3497|       |
 3498|  1.11M|               if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3498:20): [True: 0, False: 1.11M]
  ------------------
 3499|      0|                  return;
 3500|      0|               }
 3501|  1.11M|            }
 3502|  27.5k|         }
 3503|  27.5k|      }
_ZZN3glz4fromILj10ENS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES1_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNS9_ILm1EEEEERS5_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT1_OT2_OT3_T4_ENKUlvE_clEv:
 3148|  27.5k|            decltype(auto) fields = [&]() -> decltype(auto) {
 3149|       |               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
 3150|       |                             (Opts.error_on_missing_keys || Opts.partial_read)) {
 3151|       |                  return bit_array<num_members>{};
 3152|       |               }
 3153|  27.5k|               else {
 3154|  27.5k|                  return nullptr;
 3155|  27.5k|               }
 3156|  27.5k|            }();
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_T3_:
   49|  1.11M|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  1.11M|         else {
   60|  1.11M|            using V = std::remove_cvref_t<T>;
   61|  1.11M|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  1.11M|                                             end);
   63|  1.11M|         }
   64|  1.11M|      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERPKcSC_S7_TkNS_10is_contextERNS_7contextEQntcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_T1_:
 1043|  1.11M|      {
 1044|       |         if constexpr (check_string_as_number(Opts)) {
 1045|       |            auto start = it;
 1046|       |            skip_number<Opts>(ctx, it, end);
 1047|       |            if (bool(ctx.error)) [[unlikely]] {
 1048|       |               return;
 1049|       |            }
 1050|       |            if (start == it) [[unlikely]] {
 1051|       |               ctx.error = error_code::parse_number_failure;
 1052|       |               return;
 1053|       |            }
 1054|       |            value.append(start, size_t(it - start));
 1055|       |         }
 1056|  1.11M|         else {
 1057|  1.11M|            if constexpr (!check_opening_handled(Opts)) {
 1058|  1.11M|               if constexpr (!check_ws_handled(Opts)) {
 1059|  1.11M|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (1059:23): [True: 0, False: 1.11M]
  ------------------
 1060|      0|                     return;
 1061|      0|                  }
 1062|  1.11M|               }
 1063|       |
 1064|  1.11M|               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (1064:20): [True: 363, False: 1.11M]
  ------------------
 1065|    363|                  return;
 1066|    363|               }
 1067|  1.11M|            }
 1068|       |
 1069|  1.11M|            if constexpr (not check_raw_string(Opts)) {
 1070|  1.11M|               static constexpr auto string_padding_bytes = 8;
 1071|       |
 1072|  1.11M|               if (size_t(end - it) >= 8) {
  ------------------
  |  Branch (1072:20): [True: 1.11M, False: 2.81k]
  ------------------
 1073|  1.11M|                  auto start = it;
 1074|  1.11M|                  uint64_t ascii_acc{};
 1075|  1.11M|                  const auto end8 = end - 8;
 1076|  4.12M|                  while (true) {
  ------------------
  |  Branch (1076:26): [True: 4.12M, Folded]
  ------------------
 1077|  4.12M|                     if (it >= end8) [[unlikely]] {
  ------------------
  |  Branch (1077:26): [True: 889, False: 4.12M]
  ------------------
 1078|    889|                        break;
 1079|    889|                     }
 1080|       |
 1081|  4.12M|                     uint64_t chunk;
 1082|  4.12M|                     std::memcpy(&chunk, it, 8);
 1083|       |                     if constexpr (std::endian::native == std::endian::big) {
 1084|       |                        chunk = std::byteswap(chunk);
 1085|       |                     }
 1086|  4.12M|                     ascii_acc |= chunk;
 1087|  4.12M|                     const uint64_t test_chars = has_quote(chunk);
 1088|  4.12M|                     if (test_chars) {
  ------------------
  |  Branch (1088:26): [True: 1.11M, False: 3.01M]
  ------------------
 1089|  1.11M|                        it += (countr_zero(test_chars) >> 3);
 1090|       |
 1091|  1.11M|                        auto* prev = it - 1;
 1092|  1.11M|                        while (*prev == '\\') {
  ------------------
  |  Branch (1092:32): [True: 2.01k, False: 1.11M]
  ------------------
 1093|  2.01k|                           --prev;
 1094|  2.01k|                        }
 1095|  1.11M|                        if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (1095:29): [True: 1.11M, False: 1.41k]
  ------------------
 1096|  1.11M|                           goto continue_decode;
 1097|  1.11M|                        }
 1098|  1.41k|                        ++it; // skip the escaped quote
 1099|  1.41k|                     }
 1100|  3.01M|                     else {
 1101|  3.01M|                        it += 8;
 1102|  3.01M|                     }
 1103|  4.12M|                  }
 1104|       |
 1105|  2.67k|                  while (it[-1] == '\\') [[unlikely]] {
  ------------------
  |  Branch (1105:26): [True: 1.78k, False: 889]
  ------------------
 1106|       |                     // if we ended on an escape character then we need to rewind
 1107|       |                     // because we lost our context
 1108|  1.78k|                     --it;
 1109|  1.78k|                  }
 1110|       |
 1111|       |                  // The byte-wise tail keeps feeding the accumulator: it has to cover every byte of
 1112|       |                  // the string, or a non-ASCII byte reached here would be waved through unvalidated.
 1113|  5.05k|                  for (; it < end; ++it) {
  ------------------
  |  Branch (1113:26): [True: 4.88k, False: 175]
  ------------------
 1114|  4.88k|                     ascii_acc |= uint8_t(*it);
 1115|  4.88k|                     if (*it == '"') {
  ------------------
  |  Branch (1115:26): [True: 765, False: 4.11k]
  ------------------
 1116|    765|                        auto* prev = it - 1;
 1117|  1.64k|                        while (*prev == '\\') {
  ------------------
  |  Branch (1117:32): [True: 881, False: 765]
  ------------------
 1118|    881|                           --prev;
 1119|    881|                        }
 1120|    765|                        if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (1120:29): [True: 714, False: 51]
  ------------------
 1121|    714|                           goto continue_decode;
 1122|    714|                        }
 1123|    765|                     }
 1124|  4.88k|                  }
 1125|       |
 1126|    175|                  ctx.error = error_code::unexpected_end;
 1127|    175|                  return;
 1128|       |
 1129|  1.11M|               continue_decode:
 1130|       |
 1131|  1.11M|                  if (validate_utf8_span<Opts>(ctx, start, it, ascii_acc)) [[unlikely]] {
  ------------------
  |  Branch (1131:23): [True: 172, False: 1.11M]
  ------------------
 1132|    172|                     return;
 1133|    172|                  }
 1134|       |
 1135|  1.11M|                  const auto available_padding = size_t(end - it);
 1136|  1.11M|                  auto n = size_t(it - start);
 1137|  1.11M|                  if (available_padding >= 8) [[likely]] {
  ------------------
  |  Branch (1137:23): [True: 1.11M, False: 828]
  ------------------
 1138|  1.11M|                     value.resize(n + string_padding_bytes);
 1139|       |
 1140|  1.11M|                     auto* p = value.data();
 1141|       |
 1142|  4.73M|                     while (true) {
  ------------------
  |  Branch (1142:29): [True: 4.73M, Folded]
  ------------------
 1143|  4.73M|                        if (start >= it) {
  ------------------
  |  Branch (1143:29): [True: 1.10M, False: 3.63M]
  ------------------
 1144|  1.10M|                           break;
 1145|  1.10M|                        }
 1146|       |
 1147|  3.63M|                        std::memcpy(p, start, 8);
 1148|  3.63M|                        uint64_t swar;
 1149|  3.63M|                        std::memcpy(&swar, p, 8);
 1150|       |                        if constexpr (std::endian::native == std::endian::big) {
 1151|       |                           swar = std::byteswap(swar);
 1152|       |                        }
 1153|       |
 1154|  3.63M|                        constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
 1155|  3.63M|                        const uint64_t lo7 = swar & lo7_mask;
 1156|  3.63M|                        const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
 1157|  3.63M|                        const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
 1158|  3.63M|                        uint64_t next = ~((backslash & less_32) | swar);
 1159|       |
 1160|  3.63M|                        next &= repeat_byte8(0b10000000);
 1161|  3.63M|                        if (next == 0) {
  ------------------
  |  Branch (1161:29): [True: 3.62M, False: 9.91k]
  ------------------
 1162|  3.62M|                           start += 8;
 1163|  3.62M|                           p += 8;
 1164|  3.62M|                           continue;
 1165|  3.62M|                        }
 1166|       |
 1167|  9.91k|                        next = countr_zero(next) >> 3;
 1168|  9.91k|                        start += next;
 1169|  9.91k|                        if (start >= it) {
  ------------------
  |  Branch (1169:29): [True: 2.66k, False: 7.24k]
  ------------------
 1170|  2.66k|                           break;
 1171|  2.66k|                        }
 1172|       |
 1173|  7.24k|                        if ((*start & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1173:29): [True: 40, False: 7.20k]
  ------------------
 1174|     40|                           ctx.error = error_code::syntax_error;
 1175|     40|                           return;
 1176|     40|                        }
 1177|  7.20k|                        ++start; // skip the escape
 1178|  7.20k|                        if (*start == 'u') {
  ------------------
  |  Branch (1178:29): [True: 6.06k, False: 1.14k]
  ------------------
 1179|  6.06k|                           ++start;
 1180|  6.06k|                           p += next;
 1181|  6.06k|                           const auto mark = start;
 1182|  6.06k|                           const auto offset = handle_unicode_code_point(start, p, end);
 1183|  6.06k|                           if (offset == 0) [[unlikely]] {
  ------------------
  |  Branch (1183:32): [True: 56, False: 6.00k]
  ------------------
 1184|     56|                              ctx.error = error_code::unicode_escape_conversion_failure;
 1185|     56|                              return;
 1186|     56|                           }
 1187|  6.00k|                           n += offset;
 1188|       |                           // escape + u + unicode code points
 1189|  6.00k|                           n -= 2 + uint32_t(start - mark);
 1190|  6.00k|                        }
 1191|  1.14k|                        else {
 1192|  1.14k|                           p += next;
 1193|  1.14k|                           *p = char_unescape_table[uint8_t(*start)];
 1194|  1.14k|                           if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1194:32): [True: 12, False: 1.13k]
  ------------------
 1195|     12|                              ctx.error = error_code::invalid_escape;
 1196|     12|                              return;
 1197|     12|                           }
 1198|  1.13k|                           ++p;
 1199|  1.13k|                           ++start;
 1200|  1.13k|                           --n;
 1201|  1.13k|                        }
 1202|  7.20k|                     }
 1203|       |
 1204|  1.11M|                     value.resize(n);
 1205|  1.11M|                     ++it;
 1206|  1.11M|                  }
 1207|    828|                  else {
 1208|       |                     // For large inputs this case of running out of buffer is very rare
 1209|    828|                     value.resize(n);
 1210|    828|                     auto* p = value.data();
 1211|       |
 1212|    828|                     it = start;
 1213|   179k|                     while (it < end) [[likely]] {
  ------------------
  |  Branch (1213:29): [True: 179k, False: 0]
  ------------------
 1214|   179k|                        if (*it == '"') {
  ------------------
  |  Branch (1214:29): [True: 707, False: 178k]
  ------------------
 1215|    707|                           value.resize(size_t(p - value.data()));
 1216|    707|                           ++it;
 1217|    707|                           return;
 1218|    707|                        }
 1219|       |
 1220|   178k|                        if ((*it & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1220:29): [True: 32, False: 178k]
  ------------------
 1221|     32|                           ctx.error = error_code::syntax_error;
 1222|     32|                           return;
 1223|     32|                        }
 1224|       |
 1225|   178k|                        *p = *it;
 1226|       |
 1227|   178k|                        if (*it == '\\') {
  ------------------
  |  Branch (1227:29): [True: 2.33k, False: 176k]
  ------------------
 1228|  2.33k|                           ++it; // skip the escape
 1229|  2.33k|                           if (*it == 'u') {
  ------------------
  |  Branch (1229:32): [True: 1.19k, False: 1.14k]
  ------------------
 1230|  1.19k|                              ++it;
 1231|  1.19k|                              if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
  ------------------
  |  Branch (1231:35): [True: 80, False: 1.11k]
  ------------------
 1232|     80|                                 ctx.error = error_code::unicode_escape_conversion_failure;
 1233|     80|                                 return;
 1234|     80|                              }
 1235|  1.19k|                           }
 1236|  1.14k|                           else {
 1237|  1.14k|                              *p = char_unescape_table[uint8_t(*it)];
 1238|  1.14k|                              if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1238:35): [True: 9, False: 1.13k]
  ------------------
 1239|      9|                                 ctx.error = error_code::invalid_escape;
 1240|      9|                                 return;
 1241|      9|                              }
 1242|  1.13k|                              ++p;
 1243|  1.13k|                              ++it;
 1244|  1.13k|                           }
 1245|  2.33k|                        }
 1246|   176k|                        else {
 1247|   176k|                           ++it;
 1248|   176k|                           ++p;
 1249|   176k|                        }
 1250|   178k|                     }
 1251|       |
 1252|      0|                     ctx.error = error_code::unexpected_end;
 1253|      0|                  }
 1254|  1.11M|               }
 1255|  2.81k|               else {
 1256|       |                  // For short strings
 1257|       |
 1258|  2.81k|                  std::array<char, 8> buffer{};
 1259|       |
 1260|  2.81k|                  auto* p = buffer.data();
 1261|  2.81k|                  const auto* const utf8_start = it;
 1262|       |
 1263|  5.34k|                  while (it < end) [[likely]] {
  ------------------
  |  Branch (1263:26): [True: 4.98k, False: 363]
  ------------------
 1264|  4.98k|                     *p = *it;
 1265|  4.98k|                     if (*it == '"') {
  ------------------
  |  Branch (1265:26): [True: 2.08k, False: 2.90k]
  ------------------
 1266|  2.08k|                        if (validate_utf8_span<Opts>(ctx, utf8_start, it)) [[unlikely]] {
  ------------------
  |  Branch (1266:29): [True: 75, False: 2.00k]
  ------------------
 1267|     75|                           return;
 1268|     75|                        }
 1269|  2.00k|                        const size_t n = size_t(p - buffer.data());
 1270|  2.00k|#if __has_cpp_attribute(assume) >= 202207L
 1271|  2.00k|                        [[assume(n <= sizeof(buffer))]];
 1272|  2.00k|#endif
 1273|  2.00k|                        value.assign(buffer.data(), n);
 1274|  2.00k|                        ++it;
 1275|       |                        if constexpr (not Opts.null_terminated) {
 1276|       |                           if (it == end) {
 1277|       |                              ctx.error = error_code::end_reached;
 1278|       |                              return;
 1279|       |                           }
 1280|       |                        }
 1281|  2.00k|                        return;
 1282|  2.08k|                     }
 1283|  2.90k|                     else if (*it == '\\') {
  ------------------
  |  Branch (1283:31): [True: 81, False: 2.82k]
  ------------------
 1284|     81|                        ++it; // skip the escape
 1285|       |                        if constexpr (not Opts.null_terminated) {
 1286|       |                           if (it == end) [[unlikely]] {
 1287|       |                              ctx.error = error_code::unexpected_end;
 1288|       |                              return;
 1289|       |                           }
 1290|       |                        }
 1291|     81|                        if (*it == 'u') {
  ------------------
  |  Branch (1291:29): [True: 41, False: 40]
  ------------------
 1292|     41|                           ++it;
 1293|       |                           if constexpr (not Opts.null_terminated) {
 1294|       |                              if (it == end) [[unlikely]] {
 1295|       |                                 ctx.error = error_code::unexpected_end;
 1296|       |                                 return;
 1297|       |                              }
 1298|       |                           }
 1299|     41|                           if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
  ------------------
  |  Branch (1299:32): [True: 9, False: 32]
  ------------------
 1300|      9|                              ctx.error = error_code::unicode_escape_conversion_failure;
 1301|      9|                              return;
 1302|      9|                           }
 1303|     41|                        }
 1304|     40|                        else {
 1305|     40|                           *p = char_unescape_table[uint8_t(*it)];
 1306|     40|                           if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1306:32): [True: 12, False: 28]
  ------------------
 1307|     12|                              ctx.error = error_code::invalid_escape;
 1308|     12|                              return;
 1309|     12|                           }
 1310|     28|                           ++p;
 1311|     28|                           ++it;
 1312|     28|                        }
 1313|     81|                     }
 1314|  2.82k|                     else if ((*it & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1314:31): [True: 348, False: 2.47k]
  ------------------
 1315|    348|                        ctx.error = error_code::syntax_error;
 1316|    348|                        return;
 1317|    348|                     }
 1318|  2.47k|                     else {
 1319|  2.47k|                        ++it;
 1320|  2.47k|                        ++p;
 1321|  2.47k|                     }
 1322|  4.98k|                  }
 1323|       |
 1324|    363|                  ctx.error = error_code::unexpected_end;
 1325|    363|               }
 1326|       |            }
 1327|       |            else {
 1328|       |               // raw_string
 1329|       |               auto start = it;
 1330|       |               skip_string_view(ctx, it, end);
 1331|       |               if (bool(ctx.error)) [[unlikely]]
 1332|       |                  return;
 1333|       |
 1334|       |               if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]] {
 1335|       |                  return;
 1336|       |               }
 1337|       |
 1338|       |               value.assign(start, size_t(it - start));
 1339|       |               ++it;
 1340|       |            }
 1341|  1.11M|         }
 1342|  1.11M|      }
_ZN3glz14parse_ws_colonITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_10is_contextENS_7contextERPKcS4_EEbRT0_OT1_T2_:
  159|  1.11M|   {
  160|  1.11M|      if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (160:11): [True: 0, False: 1.11M]
  ------------------
  161|      0|         return true;
  162|      0|      }
  163|  1.11M|      if (match_invalid_end<':', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (163:11): [True: 739, False: 1.11M]
  ------------------
  164|    739|         return true;
  165|    739|      }
  166|  1.11M|      if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (166:11): [True: 0, False: 1.11M]
  ------------------
  167|      0|         return true;
  168|      0|      }
  169|  1.11M|      return false;
  170|  1.11M|   }
_ZZN3glz4fromILj10ENS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES1_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNS9_ILm1EEEEERS5_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT1_OT2_OT3_T4_ENKUlOT_E_clIRNSt3__112basic_stringIcNSS_11char_traitsIcEENSS_9allocatorIcEEEEEEDaSP_:
 3394|  1.11M|                  auto reading = [&](auto&& key) {
 3395|       |                     if constexpr (Opts.partial_read) {
 3396|       |                        if (auto element = value.find(key); element != value.end()) {
 3397|       |                           ++read_count;
 3398|       |                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
 3399|       |                        }
 3400|       |                        else {
 3401|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 3402|       |                        }
 3403|       |                     }
 3404|  1.11M|                     else {
 3405|  1.11M|                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
 3406|  1.11M|                     }
 3407|  1.11M|                  };
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERNS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
   49|  2.81M|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  2.81M|         else {
   60|  2.81M|            using V = std::remove_cvref_t<T>;
   61|  2.81M|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  2.81M|                                             end);
   63|  2.81M|         }
   64|  2.81M|      }
_ZN3glz4fromILj10ENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERS4_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
  150|  2.81M|      {
  151|  2.81M|         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
  152|  2.81M|         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
  153|  2.81M|                                          std::forward<Ctx>(ctx), std::forward<It0>(it), end);
  154|  2.81M|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4065|  2.81M|      {
 4066|       |         if constexpr (tagging == variant_tagging_kind::adjacent) {
 4067|       |            read_adjacent<Options>(value, ctx, it, end);
 4068|       |         }
 4069|  2.81M|         else {
 4070|  2.81M|            read_deduced<Options>(value, ctx, it, end);
 4071|  2.81M|         }
 4072|  2.81M|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE12read_deducedITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4076|  2.81M|      {
 4077|  2.81M|         constexpr auto Opts = ws_handled_off<Options>();
 4078|  2.81M|         if constexpr (variant_is_auto_deducible<T>()) {
 4079|       |            if constexpr (not check_ws_handled(Options)) {
 4080|       |               if (skip_ws<Opts>(ctx, it, end)) {
 4081|       |                  return;
 4082|       |               }
 4083|       |            }
 4084|       |
 4085|  2.81M|            switch (*it) {
 4086|  1.74k|            case '\0':
  ------------------
  |  Branch (4086:13): [True: 1.74k, False: 2.81M]
  ------------------
 4087|  1.74k|               ctx.error = error_code::unexpected_end;
 4088|  1.74k|               return;
 4089|  22.4k|            case '{': {
  ------------------
  |  Branch (4089:13): [True: 22.4k, False: 2.79M]
  ------------------
 4090|       |               // This branch consumes the brace itself and hands the object to a reader with
 4091|       |               // `opening_handled`, which therefore does not count the level -- but does release it at
 4092|       |               // the closing brace. So the level is taken here, in both buffer modes, and paid back by
 4093|       |               // the reader below.
 4094|  22.4k|               if (enter_depth(ctx)) [[unlikely]] {
  ------------------
  |  Branch (4094:20): [True: 11, False: 22.3k]
  ------------------
 4095|     11|                  return;
 4096|     11|               }
 4097|       |
 4098|  22.3k|               ++it;
 4099|       |               if constexpr (not Opts.null_terminated) {
 4100|       |                  if (it == end) [[unlikely]] {
 4101|       |                     ctx.error = error_code::unexpected_end;
 4102|       |                     return;
 4103|       |                  }
 4104|       |               }
 4105|  22.3k|               using type_counts = variant_type_count<T>;
 4106|  22.3k|               constexpr auto n_object_candidates = variant_object_candidate_count_v<Opts, T>;
 4107|       |               if constexpr (n_object_candidates < 1) {
 4108|       |                  ctx.error = error_code::no_matching_variant_type;
 4109|       |                  return;
 4110|       |               }
 4111|  22.3k|               else if constexpr (n_object_candidates == 1 && tag_v<T>.empty()) {
 4112|  22.3k|                  constexpr auto first_idx = variant_first_object_candidate_v<Opts, T>;
 4113|  22.3k|                  using V = std::variant_alternative_t<first_idx, T>;
 4114|  22.3k|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4114:23): [True: 21.9k, False: 402]
  ------------------
 4115|  22.3k|                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
 4116|  22.3k|                  return;
 4117|       |               }
 4118|       |               else {
 4119|       |                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
 4120|       |                  static constexpr auto& deduction_bits = variant_deduction_bits<T>;
 4121|       |                  static constexpr size_t deduction_key_count = variant_deduction_key_count<T>;
 4122|       |                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
 4123|       |
 4124|       |                  // Track if we've encountered a tag and what value it had
 4125|       |                  std::optional<size_t> tag_specified_index{};
 4126|       |
 4127|       |                  if (skip_ws<Opts>(ctx, it, end)) {
 4128|       |                     return;
 4129|       |                  }
 4130|       |                  // Once the reader knows which alternative this object holds it may have to read
 4131|       |                  // it again from here. Anchor the position rather than keep the pointer: the scan
 4132|       |                  // below skips values, and a streaming skip refills, which moves the window out
 4133|       |                  // from under a raw pointer (see rewind_anchor).
 4134|       |                  auto start = make_rewind_anchor(ctx, it);
 4135|       |                  bool first_key = true;
 4136|       |                  // Parse bifurcation for tagged variants:
 4137|       |                  //
 4138|       |                  // Without this optimization, tagged variant parsing always uses two passes:
 4139|       |                  //   1. Scan all keys to find the tag (e.g. "type"), skipping values
 4140|       |                  //   2. Reset `it = start` and re-parse the entire object into the resolved type
 4141|       |                  //
 4142|       |                  // When the tag is the first key, the second pass redundantly re-reads every
 4143|       |                  // field that follows it. This lambda avoids that: if the tag was the first key,
 4144|       |                  // it advances past the trailing comma so the object parser picks up at the
 4145|       |                  // second field. If the tag was found later, it falls back to the full re-parse.
 4146|       |                  //
 4147|       |                  // One exception: if the tag name is also a field on the resolved struct
 4148|       |                  // (contains_tag), we must re-parse regardless so the value is stored in
 4149|       |                  // the struct field. This override is applied inside each std::visit lambda.
 4150|       |                  //
 4151|       |                  // Either way the rewind can fail under a streaming read: the window only holds so
 4152|       |                  // much, and an object wider than it has no start left to return to.
 4153|       |                  auto position_after_tag = [&] {
 4154|       |                     if (first_key) {
 4155|       |                        if (*it == ',') ++it; // skip comma; handles tag-only objects where *it == '}'
 4156|       |                        return true;
 4157|       |                     }
 4158|       |                     return start.rewind(ctx, it, end); // tag came later, re-parse from the beginning
 4159|       |                  };
 4160|       |                  // `first_key` also answers "were we reset to the object start", which is what
 4161|       |                  // position_after_tag does for every key but the first.
 4162|       |                  for (; *it != '}'; first_key = false) {
 4163|       |                     if (!first_key) {
 4164|       |                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
 4165|       |                           return;
 4166|       |                        }
 4167|       |                     }
 4168|       |
 4169|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4170|       |                        return;
 4171|       |                     }
 4172|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4173|       |                        return;
 4174|       |                     }
 4175|       |
 4176|       |                     auto* key_start = it;
 4177|       |                     skip_string_view(ctx, it, end);
 4178|       |                     if (bool(ctx.error)) [[unlikely]]
 4179|       |                        return;
 4180|       |                     if (validate_utf8_span<Opts>(ctx, key_start, it)) [[unlikely]]
 4181|       |                        return;
 4182|       |                     const sv key = {key_start, size_t(it - key_start)};
 4183|       |
 4184|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4185|       |                        return;
 4186|       |                     }
 4187|       |
 4188|       |                     if constexpr (deduction_key_count > 0) {
 4189|       |                        // We first check if a tag is defined and see if the key matches the tag
 4190|       |                        if constexpr (not tag_v<T>.empty()) {
 4191|       |                           if (key == tag_v<T>) {
 4192|       |                              if (parse_ws_colon<Opts>(ctx, it, end)) {
 4193|       |                                 return;
 4194|       |                              }
 4195|       |
 4196|       |                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
 4197|       |
 4198|       |                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
 4199|       |                              if constexpr (std::integral<id_type>) {
 4200|       |                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
 4201|       |                              }
 4202|       |                              else {
 4203|       |                                 // The id is turned into an index below and never leaves this
 4204|       |                                 // reader, so the view of the window it borrows cannot outlive it.
 4205|       |                                 parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4206|       |                              }
 4207|       |                              if (bool(ctx.error)) [[unlikely]]
 4208|       |                                 return;
 4209|       |                              if (skip_ws<Opts>(ctx, it, end)) {
 4210|       |                                 return;
 4211|       |                              }
 4212|       |                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
 4213|       |                                 ctx.error = error_code::syntax_error;
 4214|       |                                 return;
 4215|       |                              }
 4216|       |
 4217|       |                              size_t type_index;
 4218|       |                              if constexpr (std::integral<id_type>) {
 4219|       |                                 type_index = variant_id_to_index<T>::op(type_id);
 4220|       |                              }
 4221|       |                              else {
 4222|       |                                 type_index = variant_id_to_index<T>::op(
 4223|       |                                    type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4224|       |                              }
 4225|       |                              if (type_index < ids_v<T>.size()) [[likely]] {
 4226|       |                                 // Check if the deduced types include the tag-specified type
 4227|       |                                 // If not, the tag doesn't match the fields
 4228|       |                                 // We're already inside if constexpr (deduction_registry.size()), so we know deduction
 4229|       |                                 // is happening. At this point, possible_types has been narrowed by field deduction.
 4230|       |                                 // Check if the tag-specified type is still possible
 4231|       |                                 const bool type_is_possible = possible_types[type_index];
 4232|       |                                 if (!type_is_possible) {
 4233|       |                                    // Tag specifies a type that doesn't match the fields seen so far
 4234|       |                                    ctx.error = error_code::no_matching_variant_type;
 4235|       |                                    return;
 4236|       |                                 }
 4237|       |
 4238|       |                                 if (!position_after_tag()) return;
 4239|       |                                 tag_specified_index = type_index; // Store the tag-specified type
 4240|       |                                 if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4241|       |                                 std::visit(
 4242|       |                                    [&](auto&& v) {
 4243|       |                                       using V = std::decay_t<decltype(v)>;
 4244|       |                                       constexpr bool is_object =
 4245|       |                                          (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4246|       |                                       if constexpr (variant_unit_alternative<V>) {
 4247|       |                                          // A unit alternative carries no data; its object holds only the
 4248|       |                                          // discriminator. Consume that body through an empty reflected object so
 4249|       |                                          // unknown-key policy and terminator handling match every other alternative.
 4250|       |                                          detail::variant_unit_body unit_body{};
 4251|       |                                          from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4252|       |                                                                                             tag_literal>(unit_body,
 4253|       |                                                                                                          ctx, it, end);
 4254|       |                                       }
 4255|       |                                       else if constexpr (is_object) {
 4256|       |                                          if constexpr (contains_tag<V, tag_literal>()) {
 4257|       |                                             // tag is a struct field, must re-parse
 4258|       |                                             if (!start.rewind(ctx, it, end)) return;
 4259|       |                                          }
 4260|       |                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
 4261|       |                                                                                                           end);
 4262|       |                                       }
 4263|       |                                       else if constexpr (is_memory_object<V>) {
 4264|       |                                          if (!v) {
 4265|       |                                             if constexpr (is_specialization_v<V, std::optional>) {
 4266|       |                                                if constexpr (requires { v.emplace(); }) {
 4267|       |                                                   v.emplace();
 4268|       |                                                }
 4269|       |                                                else {
 4270|       |                                                   v = typename V::value_type{};
 4271|       |                                                }
 4272|       |                                             }
 4273|       |                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4274|       |                                                v = std::make_unique<typename V::element_type>();
 4275|       |                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4276|       |                                                v = std::make_shared<typename V::element_type>();
 4277|       |                                             else if constexpr (constructible<V>) {
 4278|       |                                                v = meta_construct_v<V>();
 4279|       |                                             }
 4280|       |                                             else if constexpr (std::is_pointer_v<V> &&
 4281|       |                                                                can_allocate_raw_pointer<Opts,
 4282|       |                                                                                         std::decay_t<decltype(ctx)>>) {
 4283|       |                                                if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4284|       |                                                   return;
 4285|       |                                                }
 4286|       |                                             }
 4287|       |                                             else {
 4288|       |                                                ctx.error = error_code::invalid_nullable_read;
 4289|       |                                                return;
 4290|       |                                                // Cannot read into unset nullable that is not std::optional,
 4291|       |                                                // std::unique_ptr, or std::shared_ptr
 4292|       |                                             }
 4293|       |                                          }
 4294|       |                                          if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4295|       |                                             // tag is a struct field, must re-parse
 4296|       |                                             if (!start.rewind(ctx, it, end)) return;
 4297|       |                                          }
 4298|       |                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4299|       |                                             *v, ctx, it, end);
 4300|       |                                       }
 4301|       |                                       else if constexpr (custom_read<V>) {
 4302|       |                                          // Custom handlers parse the remaining body themselves and do not
 4303|       |                                          // accept the tag template parameter; the tag was already consumed.
 4304|       |                                          // This only works when the tag was the first key. If it came later,
 4305|       |                                          // we were reset to the object start and the custom handler would
 4306|       |                                          // absorb the tag, so error rather than corrupt the value.
 4307|       |                                          if (!first_key) {
 4308|       |                                             ctx.error = error_code::feature_not_supported;
 4309|       |                                             ctx.custom_error_message =
 4310|       |                                                "the tag must be the first key for a custom variant alternative";
 4311|       |                                             return;
 4312|       |                                          }
 4313|       |                                          from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4314|       |                                       }
 4315|       |                                    },
 4316|       |                                    value);
 4317|       |
 4318|       |                                 return; // we've decoded our target type
 4319|       |                              }
 4320|       |                              else [[unlikely]] {
 4321|       |                                 // Check if we have a default type (ids array shorter than variant)
 4322|       |                                 constexpr auto ids_size = ids_v<T>.size();
 4323|       |                                 constexpr auto variant_size = std::variant_size_v<T>;
 4324|       |                                 if constexpr (ids_size < variant_size) {
 4325|       |                                    // Use the first unlabeled type as the default
 4326|       |                                    const auto default_type_index = ids_size;
 4327|       |
 4328|       |                                    if (!position_after_tag()) return;
 4329|       |                                    tag_specified_index = default_type_index; // Store the default type index
 4330|       |                                    if (value.index() != default_type_index)
 4331|       |                                       emplace_runtime_variant(value, default_type_index);
 4332|       |                                    std::visit(
 4333|       |                                       [&](auto&& v) {
 4334|       |                                          using V = std::decay_t<decltype(v)>;
 4335|       |                                          constexpr bool is_object =
 4336|       |                                             (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4337|       |                                          if constexpr (variant_unit_alternative<V>) {
 4338|       |                                             // A unit alternative carries no data; its object holds only the
 4339|       |                                             // discriminator. Consume that body through an empty reflected object so
 4340|       |                                             // unknown-key policy and terminator handling match every other
 4341|       |                                             // alternative.
 4342|       |                                             detail::variant_unit_body unit_body{};
 4343|       |                                             from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4344|       |                                                                                                tag_literal>(
 4345|       |                                                unit_body, ctx, it, end);
 4346|       |                                          }
 4347|       |                                          else if constexpr (is_object) {
 4348|       |                                             if constexpr (contains_tag<V, tag_literal>()) {
 4349|       |                                                // tag is a struct field, must re-parse
 4350|       |                                                if (!start.rewind(ctx, it, end)) return;
 4351|       |                                             }
 4352|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4353|       |                                          }
 4354|       |                                          else if constexpr (is_memory_object<V>) {
 4355|       |                                             if (!v) {
 4356|       |                                                if constexpr (is_specialization_v<V, std::optional>) {
 4357|       |                                                   if constexpr (requires { v.emplace(); }) {
 4358|       |                                                      v.emplace();
 4359|       |                                                   }
 4360|       |                                                   else {
 4361|       |                                                      v = typename V::value_type{};
 4362|       |                                                   }
 4363|       |                                                }
 4364|       |                                                else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4365|       |                                                   v = std::make_unique<typename V::element_type>();
 4366|       |                                                else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4367|       |                                                   v = std::make_shared<typename V::element_type>();
 4368|       |                                                else if constexpr (constructible<V>) {
 4369|       |                                                   v = meta_construct_v<V>();
 4370|       |                                                }
 4371|       |                                                else if constexpr (std::is_pointer_v<V> &&
 4372|       |                                                                   can_allocate_raw_pointer<
 4373|       |                                                                      Opts, std::decay_t<decltype(ctx)>>) {
 4374|       |                                                   if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4375|       |                                                      return;
 4376|       |                                                   }
 4377|       |                                                }
 4378|       |                                                else {
 4379|       |                                                   ctx.error = error_code::invalid_nullable_read;
 4380|       |                                                   return;
 4381|       |                                                }
 4382|       |                                             }
 4383|       |                                             if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4384|       |                                                // tag is a struct field, must re-parse
 4385|       |                                                if (!start.rewind(ctx, it, end)) return;
 4386|       |                                             }
 4387|       |                                             from<JSON, memory_type<V>>::template op<opening_handled<Opts>()>(*v, ctx,
 4388|       |                                                                                                              it, end);
 4389|       |                                          }
 4390|       |                                          else if constexpr (custom_read<V>) {
 4391|       |                                             // Custom handlers parse the remaining body themselves; this only
 4392|       |                                             // works when the tag was the first key (see above). If it came
 4393|       |                                             // later we were reset to the object start, so error rather than
 4394|       |                                             // let the custom handler absorb the tag.
 4395|       |                                             if (!first_key) {
 4396|       |                                                ctx.error = error_code::feature_not_supported;
 4397|       |                                                ctx.custom_error_message =
 4398|       |                                                   "the tag must be the first key for a custom variant alternative";
 4399|       |                                                return;
 4400|       |                                             }
 4401|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4402|       |                                          }
 4403|       |                                       },
 4404|       |                                       value);
 4405|       |
 4406|       |                                    return;
 4407|       |                                 }
 4408|       |                                 else {
 4409|       |                                    ctx.error = error_code::no_matching_variant_type;
 4410|       |                                    ctx.custom_error_message = variant_ids_string_v<T>;
 4411|       |                                    return;
 4412|       |                                 }
 4413|       |                              }
 4414|       |                           }
 4415|       |                        }
 4416|       |
 4417|       |                        // Inline decode_hash lookup for variant deduction
 4418|       |                        using deduction_keys_t = keys_wrapper<variant_deduction_keys<T>>;
 4419|       |                        constexpr auto& DeductionHashInfo = hash_info<deduction_keys_t>;
 4420|       |                        const auto deduction_index =
 4421|       |                           decode_hash_with_size<JSON, deduction_keys_t, DeductionHashInfo, DeductionHashInfo.type>::op(
 4422|       |                              key.data(), key.data() + key.size(), key.size());
 4423|       |                        if (deduction_index < deduction_key_count && variant_deduction_keys<T>[deduction_index] == key)
 4424|       |                           [[likely]] {
 4425|       |                           possible_types &= deduction_bits[deduction_index];
 4426|       |                        }
 4427|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4428|       |                           ctx.error = error_code::unknown_key;
 4429|       |                           return;
 4430|       |                        }
 4431|       |                     }
 4432|       |                     else if constexpr (not tag_v<T>.empty()) {
 4433|       |                        // empty object case for variant, if there are no normal elements
 4434|       |                        if (key == tag_v<T>) {
 4435|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4436|       |                              return;
 4437|       |                           }
 4438|       |
 4439|       |                           // The id is turned into an index below and never leaves this reader,
 4440|       |                           // so the view of the window it borrows cannot outlive that window.
 4441|       |                           std::string_view type_id{};
 4442|       |                           parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4443|       |                           if (bool(ctx.error)) [[unlikely]]
 4444|       |                              return;
 4445|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4446|       |                              return;
 4447|       |                           }
 4448|       |
 4449|       |                           const auto type_index = variant_id_to_index<T>::op(
 4450|       |                              type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4451|       |                           if (type_index < ids_v<T>.size()) [[likely]] {
 4452|       |                              if (!position_after_tag()) return;
 4453|       |                              tag_specified_index = type_index; // Store the tag-specified type
 4454|       |                              if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4455|       |                           }
 4456|       |                           else {
 4457|       |                              // Check if we have a default type (ids array shorter than variant)
 4458|       |                              constexpr auto ids_size = ids_v<T>.size();
 4459|       |                              constexpr auto variant_size = std::variant_size_v<T>;
 4460|       |                              if constexpr (ids_size < variant_size) {
 4461|       |                                 // Use the first unlabeled type as the default
 4462|       |                                 if (!position_after_tag()) return;
 4463|       |                                 const auto default_index = ids_size;
 4464|       |                                 tag_specified_index = default_index; // Store the default type index
 4465|       |                                 if (value.index() != default_index) emplace_runtime_variant(value, default_index);
 4466|       |                              }
 4467|       |                              else {
 4468|       |                                 ctx.error = error_code::no_matching_variant_type;
 4469|       |                                 ctx.custom_error_message = variant_ids_string_v<T>;
 4470|       |                                 return;
 4471|       |                              }
 4472|       |                           }
 4473|       |                           // Parse the type (handles tag skipping and unknown keys)
 4474|       |                           std::visit(
 4475|       |                              [&](auto&& v) {
 4476|       |                                 using V = std::decay_t<decltype(v)>;
 4477|       |                                 if constexpr (custom_read<V>) {
 4478|       |                                    // Custom handlers parse the remaining object body themselves and do not
 4479|       |                                    // accept the tag template parameter that reflected objects use to skip an
 4480|       |                                    // interior tag key. That only works when the tag is the first key (it was
 4481|       |                                    // just consumed). If the tag came after other keys, position_after_tag()
 4482|       |                                    // reset us to the object start and the custom handler would absorb the tag
 4483|       |                                    // into its value, so error here rather than corrupt the result.
 4484|       |                                    if (!first_key) {
 4485|       |                                       ctx.error = error_code::feature_not_supported;
 4486|       |                                       ctx.custom_error_message =
 4487|       |                                          "the tag must be the first key for a custom variant alternative";
 4488|       |                                       return;
 4489|       |                                    }
 4490|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4491|       |                                 }
 4492|       |                                 else {
 4493|       |                                    if constexpr (contains_tag<V, tag_literal>()) {
 4494|       |                                       // tag is a struct field, must re-parse
 4495|       |                                       if (!start.rewind(ctx, it, end)) return;
 4496|       |                                    }
 4497|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4498|       |                                 }
 4499|       |                              },
 4500|       |                              value);
 4501|       |                           return;
 4502|       |                        }
 4503|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4504|       |                           ctx.error = error_code::unknown_key;
 4505|       |                           return;
 4506|       |                        }
 4507|       |                        else {
 4508|       |                           // Skip unknown key's value (non-tag key in empty variant)
 4509|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4510|       |                              return;
 4511|       |                           }
 4512|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 4513|       |                           if (bool(ctx.error)) [[unlikely]]
 4514|       |                              return;
 4515|       |                           resync_window_end(ctx, end); // a streaming skip refills
 4516|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4517|       |                              return;
 4518|       |                           }
 4519|       |                           continue; // Continue loop to find the tag
 4520|       |                        }
 4521|       |                     }
 4522|       |                     else if constexpr (Opts.error_on_unknown_keys) {
 4523|       |                        ctx.error = error_code::unknown_key;
 4524|       |                        return;
 4525|       |                     }
 4526|       |
 4527|       |                     auto matching_types = possible_types.popcount();
 4528|       |                     if (matching_types == 0) {
 4529|       |                        ctx.error = error_code::no_matching_variant_type;
 4530|       |                        return;
 4531|       |                     }
 4532|       |                     // Only short-circuit for variants without tags
 4533|       |                     else if constexpr (tag_v<T>.empty()) {
 4534|       |                        if (matching_types == 1) {
 4535|       |                           if (!start.rewind(ctx, it, end)) return;
 4536|       |                           const auto type_index = possible_types.countr_zero();
 4537|       |
 4538|       |                           if (value.index() != static_cast<size_t>(type_index))
 4539|       |                              emplace_runtime_variant(value, type_index);
 4540|       |                           std::visit(
 4541|       |                              [&](auto&& v) {
 4542|       |                                 using V = std::decay_t<decltype(v)>;
 4543|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4544|       |                                 if constexpr (variant_unit_alternative<V>) {
 4545|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4546|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4547|       |                                    // terminator handling match every other alternative.
 4548|       |                                    detail::variant_unit_body unit_body{};
 4549|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4550|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4551|       |                                                                                                    end);
 4552|       |                                 }
 4553|       |                                 else if constexpr (is_object) {
 4554|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4555|       |                                 }
 4556|       |                                 else if constexpr (is_memory_object<V>) {
 4557|       |                                    if (!v) {
 4558|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4559|       |                                          if constexpr (requires { v.emplace(); }) {
 4560|       |                                             v.emplace();
 4561|       |                                          }
 4562|       |                                          else {
 4563|       |                                             v = typename V::value_type{};
 4564|       |                                          }
 4565|       |                                       }
 4566|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4567|       |                                          v = std::make_unique<typename V::element_type>();
 4568|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4569|       |                                          v = std::make_shared<typename V::element_type>();
 4570|       |                                       else if constexpr (constructible<V>) {
 4571|       |                                          v = meta_construct_v<V>();
 4572|       |                                       }
 4573|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4574|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4575|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4576|       |                                             return;
 4577|       |                                          }
 4578|       |                                       }
 4579|       |                                       else {
 4580|       |                                          ctx.error = error_code::invalid_nullable_read;
 4581|       |                                          return;
 4582|       |                                          // Cannot read into unset nullable that is not std::optional,
 4583|       |                                          // std::unique_ptr, or std::shared_ptr
 4584|       |                                       }
 4585|       |                                    }
 4586|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4587|       |                                       *v, ctx, it, end);
 4588|       |                                 }
 4589|       |                                 else if constexpr (custom_read<V>) {
 4590|       |                                    // Custom handlers parse the remaining body themselves.
 4591|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4592|       |                                 }
 4593|       |                              },
 4594|       |                              value);
 4595|       |
 4596|       |                           return; // we've decoded our target type
 4597|       |                        }
 4598|       |                     }
 4599|       |                     // For tagged variants, continue processing to validate tags
 4600|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 4601|       |                        return;
 4602|       |                     }
 4603|       |
 4604|       |                     skip_value<JSON>::op<Opts>(ctx, it, end);
 4605|       |                     if (bool(ctx.error)) [[unlikely]]
 4606|       |                        return;
 4607|       |                     resync_window_end(ctx, end); // a streaming skip refills
 4608|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4609|       |                        return;
 4610|       |                     }
 4611|       |                  }
 4612|       |                  // Only apply ambiguous variant resolution if we have multiple object types
 4613|       |                  if constexpr ((type_counts::n_object + type_counts::n_nullable_object) > 1) {
 4614|       |                     // After parsing all keys, check if we have multiple matching types
 4615|       |                     // If so, choose the one with the fewest fields
 4616|       |                     auto final_matching = possible_types.popcount();
 4617|       |                     if (final_matching == 0) {
 4618|       |                        ctx.error = error_code::no_matching_variant_type;
 4619|       |                     }
 4620|       |                     else if (final_matching == 1) {
 4621|       |                        // Single type remains after field deduction
 4622|       |                        const auto type_index = possible_types.countr_zero();
 4623|       |
 4624|       |                        // Validate against tag if one was specified
 4625|       |                        if (tag_specified_index.has_value() &&
 4626|       |                            tag_specified_index.value() != static_cast<size_t>(type_index)) {
 4627|       |                           ctx.error = error_code::no_matching_variant_type;
 4628|       |                           return;
 4629|       |                        }
 4630|       |
 4631|       |                        if (!start.rewind(ctx, it, end)) return;
 4632|       |                        if (value.index() != static_cast<size_t>(type_index))
 4633|       |                           emplace_runtime_variant(value, type_index);
 4634|       |                        std::visit(
 4635|       |                           [&](auto&& v) {
 4636|       |                              using V = std::decay_t<decltype(v)>;
 4637|       |                              constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4638|       |                              if constexpr (variant_unit_alternative<V>) {
 4639|       |                                 // A unit alternative carries no data; its object holds only the discriminator.
 4640|       |                                 // Consume that body through an empty reflected object so unknown-key policy and
 4641|       |                                 // terminator handling match every other alternative.
 4642|       |                                 detail::variant_unit_body unit_body{};
 4643|       |                                 from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4644|       |                                                                                    tag_literal>(unit_body, ctx, it,
 4645|       |                                                                                                 end);
 4646|       |                              }
 4647|       |                              else if constexpr (is_object) {
 4648|       |                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4649|       |                              }
 4650|       |                              else if constexpr (is_memory_object<V>) {
 4651|       |                                 if (!v) {
 4652|       |                                    if constexpr (is_specialization_v<V, std::optional>) {
 4653|       |                                       if constexpr (requires { v.emplace(); }) {
 4654|       |                                          v.emplace();
 4655|       |                                       }
 4656|       |                                       else {
 4657|       |                                          v = typename V::value_type{};
 4658|       |                                       }
 4659|       |                                    }
 4660|       |                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4661|       |                                       v = std::make_unique<typename V::element_type>();
 4662|       |                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4663|       |                                       v = std::make_shared<typename V::element_type>();
 4664|       |                                    else if constexpr (constructible<V>) {
 4665|       |                                       v = meta_construct_v<V>();
 4666|       |                                    }
 4667|       |                                    else if constexpr (std::is_pointer_v<V> &&
 4668|       |                                                       can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4669|       |                                       if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4670|       |                                          return;
 4671|       |                                       }
 4672|       |                                    }
 4673|       |                                    else {
 4674|       |                                       ctx.error = error_code::invalid_nullable_read;
 4675|       |                                       return;
 4676|       |                                    }
 4677|       |                                 }
 4678|       |                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
 4679|       |                                                                                                               it, end);
 4680|       |                              }
 4681|       |                              else if constexpr (custom_read<V>) {
 4682|       |                                 // Custom handlers parse the remaining body themselves.
 4683|       |                                 from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4684|       |                              }
 4685|       |                           },
 4686|       |                           value);
 4687|       |                     }
 4688|       |                     else if (final_matching > 1) {
 4689|       |                        constexpr auto N = std::variant_size_v<T>;
 4690|       |
 4691|       |                        // Compile-time array of field counts for each variant type
 4692|       |                        constexpr auto field_counts = []<size_t... I>(std::index_sequence<I...>) {
 4693|       |                           return std::array<size_t, N> {
 4694|       |                              ([]<size_t J = I>() -> size_t {
 4695|       |                                 using V = std::decay_t<std::variant_alternative_t<J, T>>;
 4696|       |                                 if constexpr (glaze_object_t<V> || reflectable<V>) {
 4697|       |                                    return reflect<V>::size;
 4698|       |                                 }
 4699|       |                                 else if constexpr (is_memory_object<V>) {
 4700|       |                                    using X = memory_type<V>;
 4701|       |                                    if constexpr (glaze_object_t<X> || reflectable<X>) {
 4702|       |                                       return reflect<X>::size;
 4703|       |                                    }
 4704|       |                                    else {
 4705|       |                                       return (std::numeric_limits<size_t>::max)();
 4706|       |                                    }
 4707|       |                                 }
 4708|       |                                 else {
 4709|       |                                    return (std::numeric_limits<size_t>::max)();
 4710|       |                                 }
 4711|       |                              }.template operator()<I>())...
 4712|       |                           };
 4713|       |                        }(std::make_index_sequence<N>{});
 4714|       |
 4715|       |                        // Find the type with minimum field count among the possible types
 4716|       |                        size_t min_fields = (std::numeric_limits<size_t>::max)();
 4717|       |                        size_t chosen_index = N; // Invalid index initially
 4718|       |
 4719|       |                        for (size_t i = 0; i < N; ++i) {
 4720|       |                           if (possible_types[i] && field_counts[i] < min_fields) {
 4721|       |                              min_fields = field_counts[i];
 4722|       |                              chosen_index = i;
 4723|       |                           }
 4724|       |                        }
 4725|       |
 4726|       |                        if (chosen_index < N) {
 4727|       |                           // Validate against tag if one was specified
 4728|       |                           if (tag_specified_index.has_value() && tag_specified_index.value() != chosen_index) {
 4729|       |                              ctx.error = error_code::no_matching_variant_type;
 4730|       |                              return;
 4731|       |                           }
 4732|       |
 4733|       |                           if (!start.rewind(ctx, it, end)) return;
 4734|       |                           if (value.index() != chosen_index) emplace_runtime_variant(value, chosen_index);
 4735|       |                           std::visit(
 4736|       |                              [&](auto&& v) {
 4737|       |                                 using V = std::decay_t<decltype(v)>;
 4738|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4739|       |                                 if constexpr (variant_unit_alternative<V>) {
 4740|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4741|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4742|       |                                    // terminator handling match every other alternative.
 4743|       |                                    detail::variant_unit_body unit_body{};
 4744|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4745|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4746|       |                                                                                                    end);
 4747|       |                                 }
 4748|       |                                 else if constexpr (is_object) {
 4749|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4750|       |                                 }
 4751|       |                                 else if constexpr (is_memory_object<V>) {
 4752|       |                                    if (!v) {
 4753|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4754|       |                                          if constexpr (requires { v.emplace(); }) {
 4755|       |                                             v.emplace();
 4756|       |                                          }
 4757|       |                                          else {
 4758|       |                                             v = typename V::value_type{};
 4759|       |                                          }
 4760|       |                                       }
 4761|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4762|       |                                          v = std::make_unique<typename V::element_type>();
 4763|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4764|       |                                          v = std::make_shared<typename V::element_type>();
 4765|       |                                       else if constexpr (constructible<V>) {
 4766|       |                                          v = meta_construct_v<V>();
 4767|       |                                       }
 4768|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4769|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4770|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4771|       |                                             return;
 4772|       |                                          }
 4773|       |                                       }
 4774|       |                                       else {
 4775|       |                                          ctx.error = error_code::invalid_nullable_read;
 4776|       |                                          return;
 4777|       |                                       }
 4778|       |                                    }
 4779|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4780|       |                                       *v, ctx, it, end);
 4781|       |                                 }
 4782|       |                                 else if constexpr (custom_read<V>) {
 4783|       |                                    // Custom handlers parse the remaining body themselves.
 4784|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4785|       |                                 }
 4786|       |                              },
 4787|       |                              value);
 4788|       |                        }
 4789|       |                        else {
 4790|       |                           ctx.error = error_code::no_matching_variant_type;
 4791|       |                        }
 4792|       |                     }
 4793|       |                  }
 4794|       |                  else {
 4795|       |                     // For variants with 0 or 1 object types, use the original error handling
 4796|       |                     ctx.error = error_code::no_matching_variant_type;
 4797|       |                  }
 4798|       |               }
 4799|      0|               break;
 4800|  22.4k|            }
 4801|   596k|            case '[':
  ------------------
  |  Branch (4801:13): [True: 596k, False: 2.21M]
  ------------------
 4802|       |               // As with '{' above: the array reader each alternative goes through counts the level.
 4803|   596k|               process_variant_alternatives<T, is_variant_array>::template op<Opts>(value, ctx, it, end);
 4804|   596k|               break;
 4805|  5.11k|            case '"': {
  ------------------
  |  Branch (4805:13): [True: 5.11k, False: 2.81M]
  ------------------
 4806|  5.11k|               process_variant_alternatives<T, is_variant_str>::template op<Opts>(value, ctx, it, end);
 4807|  5.11k|               break;
 4808|  22.4k|            }
 4809|    902|            case 't':
  ------------------
  |  Branch (4809:13): [True: 902, False: 2.81M]
  ------------------
 4810|  1.19k|            case 'f': {
  ------------------
  |  Branch (4810:13): [True: 297, False: 2.81M]
  ------------------
 4811|  1.19k|               process_variant_alternatives<T, is_variant_bool>::template op<Opts>(value, ctx, it, end);
 4812|  1.19k|               break;
 4813|    902|            }
 4814|    584|            case 'n':
  ------------------
  |  Branch (4814:13): [True: 584, False: 2.81M]
  ------------------
 4815|       |               if constexpr (variant_count_v<T, is_variant_null> == 0) {
 4816|       |                  ctx.error = error_code::no_matching_variant_type;
 4817|       |               }
 4818|    584|               else {
 4819|    584|                  constexpr auto first_idx = variant_first_index_v<T, is_variant_null>;
 4820|    584|                  using V = std::variant_alternative_t<first_idx, T>;
 4821|    584|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4821:23): [True: 199, False: 385]
  ------------------
 4822|    584|                  match<"null", Opts>(ctx, it, end);
 4823|    584|               }
 4824|    584|               break;
 4825|  2.18M|            default: {
  ------------------
  |  Branch (4825:13): [True: 2.18M, False: 627k]
  ------------------
 4826|       |               // Not bool, string, object, or array so must be number or null
 4827|  2.18M|               process_variant_alternatives<T, is_variant_num>::template op<Opts>(value, ctx, it, end);
 4828|  2.18M|            }
 4829|  2.81M|            }
 4830|       |         }
 4831|       |         else {
 4832|       |            // For non-auto-deducible variants, try each type until one succeeds
 4833|       |            constexpr auto N = std::variant_size_v<T>;
 4834|       |            bool parsed = false;
 4835|       |            bool exhausted = false; // speculation budget spent; see charge_speculation
 4836|       |
 4837|       |            for_each<N>([&]<size_t I>() {
 4838|       |               if (parsed || exhausted || variant_alternative_exhausted(ctx)) return;
 4839|       |
 4840|       |               auto copy_it = it;
 4841|       |               // A rejected alternative may have bailed out inside a container, which leaves its
 4842|       |               // nesting level counted (see enter_depth), so the depth rewinds with the iterator.
 4843|       |               const auto copy_depth = ctx.depth;
 4844|       |
 4845|       |               // Try parsing as this type
 4846|       |               if (value.index() != I) {
 4847|       |                  emplace_runtime_variant(value, I);
 4848|       |               }
 4849|       |
 4850|       |               std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
 4851|       |               if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 4852|       |                  exhausted = true; // only rejected attempts are charged; see charge_speculation
 4853|       |               }
 4854|       |
 4855|       |               if (!bool(ctx.error)) {
 4856|       |                  parsed = true;
 4857|       |               }
 4858|       |               else if constexpr (not Options.null_terminated) {
 4859|       |                  // In non-null-terminated mode, if we hit end_reached after advancing the iterator,
 4860|       |                  // it means we successfully parsed the value but couldn't skip trailing whitespace
 4861|       |                  if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 4862|       |                     // We advanced the iterator, so we did parse something -- unless what advanced it
 4863|       |                     // was an abandoned attempt, which is what a spent speculation budget means.
 4864|       |                     parsed = true;
 4865|       |                     ctx.error = error_code::none;
 4866|       |                  }
 4867|       |                  else {
 4868|       |                     // Reset for next attempt (unless this is the last type)
 4869|       |                     it = copy_it;
 4870|       |                     rewind_depth<Options>(ctx, copy_depth);
 4871|       |                     if constexpr (I + 1 < N) {
 4872|       |                        if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4873|       |                           ctx.error = error_code::none; // Clear error for next attempt
 4874|       |                        }
 4875|       |                     }
 4876|       |                  }
 4877|       |               }
 4878|       |               else {
 4879|       |                  // Reset for next attempt (unless this is the last type)
 4880|       |                  it = copy_it;
 4881|       |                  rewind_depth<Options>(ctx, copy_depth);
 4882|       |                  if constexpr (I + 1 < N) {
 4883|       |                     if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4884|       |                        ctx.error = error_code::none; // Clear error for next attempt
 4885|       |                     }
 4886|       |                  }
 4887|       |               }
 4888|       |            });
 4889|       |         }
 4890|  2.81M|      }
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|   598k|      {
 3726|   598k|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|   598k|         else {
 3732|   598k|            constexpr auto N = std::variant_size_v<Variant>;
 3733|   598k|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|   598k|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|   598k|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|   598k|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|   598k|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|   598k|               size_t non_const_idx = 0;
 3793|       |
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|   598k|                     return;
 3797|   598k|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|   598k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|   598k|                     auto copy_it{it};
 3801|   598k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|   598k|                     if (!std::holds_alternative<V>(value)) {
 3803|   598k|                        value = V{};
 3804|   598k|                     }
 3805|   598k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|   598k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|   598k|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|   598k|                     }
 3809|   598k|                     if (!bool(ctx.error)) {
 3810|   598k|                        found_match = true;
 3811|   598k|                     }
 3812|   598k|                     else if constexpr (not Options.null_terminated) {
 3813|   598k|                        constexpr bool is_complete_type =
 3814|   598k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|   598k|                        if constexpr (is_complete_type) {
 3817|   598k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|   598k|                              found_match = true;
 3819|   598k|                              ctx.error = error_code::none;
 3820|   598k|                           }
 3821|   598k|                           else {
 3822|   598k|                              it = copy_it;
 3823|   598k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|   598k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|   598k|                                  not variant_alternative_exhausted(ctx)) {
 3826|   598k|                                 ctx.error = error_code::none;
 3827|   598k|                              }
 3828|   598k|                           }
 3829|   598k|                        }
 3830|   598k|                        else {
 3831|   598k|                           it = copy_it;
 3832|   598k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|   598k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|   598k|                               not variant_alternative_exhausted(ctx)) {
 3835|   598k|                              ctx.error = error_code::none;
 3836|   598k|                           }
 3837|   598k|                        }
 3838|   598k|                     }
 3839|   598k|                     else {
 3840|   598k|                        it = copy_it;
 3841|   598k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|   598k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|   598k|                            not variant_alternative_exhausted(ctx)) {
 3844|   598k|                           ctx.error = error_code::none;
 3845|   598k|                        }
 3846|   598k|                     }
 3847|   598k|                     ++non_const_idx;
 3848|   598k|                  }
 3849|   598k|               });
 3850|   598k|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 13.1k, False: 585k]
  ------------------
 3851|  13.1k|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|  13.1k|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|   598k|         }
 3864|   598k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|   598k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|   598k|                     auto copy_it{it};
 3801|   598k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|   598k|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 471k, False: 126k]
  ------------------
 3803|   471k|                        value = V{};
 3804|   471k|                     }
 3805|   598k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|   598k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 13.1k, False: 585k]
  |  Branch (3806:45): [True: 0, False: 13.1k]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|   598k|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 585k, False: 13.1k]
  ------------------
 3810|   585k|                        found_match = true;
 3811|   585k|                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|  13.1k|                     else {
 3840|  13.1k|                        it = copy_it;
 3841|  13.1k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  13.1k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3842:29): [True: 0, False: 13.1k]
  |  Branch (3842:68): [True: 0, False: 0]
  ------------------
 3843|      0|                            not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3843:29): [True: 0, False: 0]
  ------------------
 3844|      0|                           ctx.error = error_code::none;
 3845|      0|                        }
 3846|  13.1k|                     }
 3847|   598k|                     ++non_const_idx;
 3848|   598k|                  }
 3849|   598k|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERNSt3__16vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS4_9allocatorIS9_EEEETkNS_10is_contextERNS_7contextERPKcSH_EEvOT0_OT1_OT2_T3_:
   49|   598k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|   598k|         else {
   60|   598k|            using V = std::remove_cvref_t<T>;
   61|   598k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|   598k|                                             end);
   63|   598k|         }
   64|   598k|      }
_ZN3glz4fromILj10ENSt3__16vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS1_9allocatorIS6_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERS9_TkNS_10is_contextERNS_7contextERPKcSH_EEvOT0_OT1_OT2_T3_:
 2308|   598k|      {
 2309|   598k|         constexpr auto Opts = ws_handled_off<Options>();
 2310|       |         if constexpr (!check_ws_handled(Options)) {
 2311|       |            if (skip_ws<Opts>(ctx, it, end)) {
 2312|       |               return;
 2313|       |            }
 2314|       |         }
 2315|       |
 2316|   598k|         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2316:14): [True: 0, False: 598k]
  ------------------
 2317|      0|            return;
 2318|      0|         }
 2319|       |         // one nesting level (see enter_depth): counted in both modes so the limit binds,
 2320|       |         // released at each syntactic close below
 2321|   598k|         if (enter_depth(ctx)) [[unlikely]] {
  ------------------
  |  Branch (2321:14): [True: 5, False: 598k]
  ------------------
 2322|      5|            return;
 2323|      5|         }
 2324|       |
 2325|   598k|         const auto ws_start = it;
 2326|   598k|         if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2326:14): [True: 0, False: 598k]
  ------------------
 2327|      0|            return;
 2328|      0|         }
 2329|       |
 2330|   598k|         if (*it == ']') {
  ------------------
  |  Branch (2330:14): [True: 7.36k, False: 591k]
  ------------------
 2331|  7.36k|            --ctx.depth;
 2332|  7.36k|            ++it;
 2333|  7.36k|            if constexpr ((resizable<T> || is_inplace_vector<T>) && not check_append_arrays(Opts)) {
 2334|  7.36k|               value.clear();
 2335|       |
 2336|       |               if constexpr (check_shrink_to_fit(Opts) && has_shrink_to_fit<T>) {
 2337|       |                  value.shrink_to_fit();
 2338|       |               }
 2339|  7.36k|            }
 2340|  7.36k|            return;
 2341|  7.36k|         }
 2342|       |
 2343|   591k|         const size_t ws_size = size_t(it - ws_start);
 2344|       |
 2345|   591k|         static constexpr bool should_append = (resizable<T> || is_inplace_vector<T>) && check_append_arrays(Opts);
  ------------------
  |  Branch (2345:49): [True: 591k, Folded]
  |  Branch (2345:65): [Folded, False: 0]
  |  Branch (2345:90): [Folded, False: 0]
  ------------------
 2346|   591k|         if constexpr (not should_append) {
 2347|   591k|            const auto n = value.size();
 2348|       |
 2349|   591k|            auto value_it = value.begin();
 2350|       |
 2351|   597k|            for (size_t i = 0; i < n; ++i) {
  ------------------
  |  Branch (2351:32): [True: 130k, False: 466k]
  ------------------
 2352|   130k|               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
 2353|   130k|               if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (2353:20): [True: 770, False: 129k]
  ------------------
 2354|    770|                  return;
 2355|   129k|               if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2355:20): [True: 0, False: 129k]
  ------------------
 2356|      0|                  return;
 2357|      0|               }
 2358|   129k|               if (*it == ',') {
  ------------------
  |  Branch (2358:20): [True: 6.36k, False: 123k]
  ------------------
 2359|  6.36k|                  ++it;
 2360|       |
 2361|  6.36k|                  if constexpr (!Opts.minified && !Opts.comments) {
 2362|  6.36k|                     if (ws_size && ws_size < size_t(end - it)) {
  ------------------
  |  Branch (2362:26): [True: 3.46k, False: 2.90k]
  |  Branch (2362:37): [True: 3.02k, False: 434]
  ------------------
 2363|  3.02k|                        skip_matching_ws(ws_start, it, ws_size);
 2364|  3.02k|                     }
 2365|  6.36k|                  }
 2366|       |
 2367|  6.36k|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2367:23): [True: 0, False: 6.36k]
  ------------------
 2368|      0|                     return;
 2369|      0|                  }
 2370|  6.36k|               }
 2371|   123k|               else if (*it == ']') {
  ------------------
  |  Branch (2371:25): [True: 123k, False: 76]
  ------------------
 2372|   123k|                  --ctx.depth;
 2373|   123k|                  ++it;
 2374|   123k|                  if constexpr (erasable<T>) {
 2375|   123k|                     value.erase(value_it,
 2376|   123k|                                 value.end()); // use erase rather than resize for non-default constructible elements
 2377|       |
 2378|       |                     if constexpr (check_shrink_to_fit(Opts) && has_shrink_to_fit<T>) {
 2379|       |                        value.shrink_to_fit();
 2380|       |                     }
 2381|   123k|                  }
 2382|   123k|                  return;
 2383|   123k|               }
 2384|     76|               else [[unlikely]] {
 2385|     76|                  ctx.error = error_code::expected_bracket;
 2386|     76|                  return;
 2387|     76|               }
 2388|   129k|            }
 2389|   591k|         }
 2390|       |
 2391|       |         if constexpr (Opts.partial_read) {
 2392|       |            // partial_read stops early on a success path, so give the level back like the
 2393|       |            // syntactic-close paths do; otherwise it accumulates across reads sharing a context.
 2394|       |            --ctx.depth;
 2395|       |            return;
 2396|       |         }
 2397|   591k|         else {
 2398|       |            // growing
 2399|   591k|            if constexpr (emplace_backable<T> || has_try_emplace_back<T>) {
 2400|  1.69M|               while (it < end) {
  ------------------
  |  Branch (2400:23): [True: 1.57M, False: 124k]
  ------------------
 2401|       |                  // Streaming refill point: at start of each iteration, ensure buffer has data
 2402|       |                  if constexpr (has_streaming_state<decltype(ctx)>) {
 2403|       |                     if (ctx.stream.enabled()) {
 2404|       |                        const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 2405|       |                        const size_t remaining = ctx.stream.size() - consumed;
 2406|       |                        // Refill when less than half of buffer remains to ensure space for next element
 2407|       |                        if (remaining <= ctx.stream.size() / 2 || it >= end) {
 2408|       |                           const char* new_it;
 2409|       |                           const char* new_end;
 2410|       |                           ctx.stream.consume_and_refill(consumed, new_it, new_end);
 2411|       |                           it = new_it;
 2412|       |                           end = new_end;
 2413|       |                           if (it >= end && ctx.stream.at_eof()) {
 2414|       |                              break; // No more data, exit loop normally
 2415|       |                           }
 2416|       |                        }
 2417|       |                     }
 2418|       |                  }
 2419|       |
 2420|       |                  if constexpr (has_try_emplace_back<T>) {
 2421|       |                     if (value.try_emplace_back())
 2422|       |                        parse<JSON>::op<ws_handled<Opts>()>(value.back(), ctx, it, end);
 2423|       |                     else
 2424|       |                        ctx.error = error_code::exceeded_static_array_size;
 2425|       |                  }
 2426|  1.57M|                  else {
 2427|  1.57M|                     parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
 2428|  1.57M|                  }
 2429|       |
 2430|  1.57M|                  if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (2430:23): [True: 11.3k, False: 1.56M]
  ------------------
 2431|  11.3k|                     return;
 2432|       |
 2433|       |                  // Streaming refill point: after parsing each element, refill if buffer is low
 2434|       |                  if constexpr (has_streaming_state<decltype(ctx)>) {
 2435|       |                     if (ctx.stream.enabled()) {
 2436|       |                        const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 2437|       |                        // Refill when less than 25% of buffer remains to ensure enough space for next element
 2438|       |                        if (ctx.stream.size() - consumed <= ctx.stream.size() / 4 || it >= end) {
 2439|       |                           const char* new_it;
 2440|       |                           const char* new_end;
 2441|       |                           ctx.stream.consume_and_refill(consumed, new_it, new_end);
 2442|       |                           it = new_it;
 2443|       |                           end = new_end;
 2444|       |                           if (it >= end && ctx.stream.at_eof()) {
 2445|       |                              ctx.error = error_code::unexpected_end;
 2446|       |                              return;
 2447|       |                           }
 2448|       |                        }
 2449|       |                     }
 2450|       |                  }
 2451|       |
 2452|  1.56M|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2452:23): [True: 0, False: 1.56M]
  ------------------
 2453|      0|                     return;
 2454|      0|                  }
 2455|  1.56M|                  if (*it == ',') [[likely]] {
  ------------------
  |  Branch (2455:23): [True: 1.10M, False: 455k]
  ------------------
 2456|  1.10M|                     ++it;
 2457|       |
 2458|  1.10M|                     if constexpr (!Opts.minified && !Opts.comments) {
 2459|  1.10M|                        if (ws_size && ws_size < size_t(end - it)) {
  ------------------
  |  Branch (2459:29): [True: 15.0k, False: 1.09M]
  |  Branch (2459:40): [True: 14.3k, False: 658]
  ------------------
 2460|  14.3k|                           skip_matching_ws(ws_start, it, ws_size);
 2461|  14.3k|                        }
 2462|  1.10M|                     }
 2463|       |
 2464|  1.10M|                     if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2464:26): [True: 0, False: 1.10M]
  ------------------
 2465|      0|                        return;
 2466|      0|                     }
 2467|  1.10M|                  }
 2468|   455k|                  else if (*it == ']') {
  ------------------
  |  Branch (2468:28): [True: 454k, False: 1.02k]
  ------------------
 2469|   454k|                     --ctx.depth;
 2470|   454k|                     ++it;
 2471|       |                     if constexpr (check_shrink_to_fit(Opts) && has_shrink_to_fit<T>) {
 2472|       |                        value.shrink_to_fit();
 2473|       |                     }
 2474|   454k|                     return;
 2475|   454k|                  }
 2476|  1.02k|                  else [[unlikely]] {
 2477|  1.02k|                     ctx.error = error_code::expected_bracket;
 2478|  1.02k|                     return;
 2479|  1.02k|                  }
 2480|  1.56M|               }
 2481|       |
 2482|       |               // A valid array always returns from inside the loop upon reaching ']'.
 2483|       |               // For a null-terminated buffer the loop can only exit here by falling
 2484|       |               // through when `it` reaches the terminator without a closing bracket,
 2485|       |               // which means the input was truncated (e.g. "[", "[1," or "[1,2,").
 2486|       |               // Non-null-terminated buffers surface this through skip_ws/depth
 2487|       |               // tracking (or the streaming refill break), so this guard is limited
 2488|       |               // to the null-terminated case.
 2489|   124k|               if constexpr (Opts.null_terminated) {
 2490|   124k|                  ctx.error = error_code::unexpected_end;
 2491|   124k|               }
 2492|       |            }
 2493|       |            else {
 2494|       |               ctx.error = error_code::exceeded_static_array_size;
 2495|       |            }
 2496|   591k|         }
 2497|   591k|      }
_ZN3glz12rewind_depthITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_10is_contextENS_7contextEEEvRT0_j:
 3697|  16.0k|   {
 3698|  16.0k|      if (ctx.error == error_code::exceeded_max_recursive_depth) [[unlikely]] {
  ------------------
  |  Branch (3698:11): [True: 1.24k, False: 14.7k]
  ------------------
 3699|  1.24k|         return;
 3700|  1.24k|      }
 3701|  14.7k|      if constexpr (Opts.null_terminated) {
 3702|  14.7k|         ctx.depth = depth;
 3703|       |      }
 3704|       |      else {
 3705|       |         if (ctx.error != error_code::end_reached && ctx.error != error_code::unexpected_end) {
 3706|       |            ctx.depth = depth;
 3707|       |         }
 3708|       |      }
 3709|  14.7k|   }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 585k, False: 13.1k]
  |  Branch (3795:38): [True: 0, False: 13.1k]
  |  Branch (3795:51): [True: 1.24k, False: 11.9k]
  ------------------
 3796|   586k|                     return;
 3797|   586k|                  }
 3798|  11.9k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  11.9k|               });
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|  6.27k|      {
 3726|  6.27k|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|  6.27k|         else {
 3732|  6.27k|            constexpr auto N = std::variant_size_v<Variant>;
 3733|  6.27k|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|  6.27k|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|  6.27k|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|  6.27k|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|  6.27k|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|  6.27k|               size_t non_const_idx = 0;
 3793|       |
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|  6.27k|                     return;
 3797|  6.27k|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  6.27k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  6.27k|                     auto copy_it{it};
 3801|  6.27k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  6.27k|                     if (!std::holds_alternative<V>(value)) {
 3803|  6.27k|                        value = V{};
 3804|  6.27k|                     }
 3805|  6.27k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  6.27k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|  6.27k|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|  6.27k|                     }
 3809|  6.27k|                     if (!bool(ctx.error)) {
 3810|  6.27k|                        found_match = true;
 3811|  6.27k|                     }
 3812|  6.27k|                     else if constexpr (not Options.null_terminated) {
 3813|  6.27k|                        constexpr bool is_complete_type =
 3814|  6.27k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|  6.27k|                        if constexpr (is_complete_type) {
 3817|  6.27k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|  6.27k|                              found_match = true;
 3819|  6.27k|                              ctx.error = error_code::none;
 3820|  6.27k|                           }
 3821|  6.27k|                           else {
 3822|  6.27k|                              it = copy_it;
 3823|  6.27k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  6.27k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|  6.27k|                                  not variant_alternative_exhausted(ctx)) {
 3826|  6.27k|                                 ctx.error = error_code::none;
 3827|  6.27k|                              }
 3828|  6.27k|                           }
 3829|  6.27k|                        }
 3830|  6.27k|                        else {
 3831|  6.27k|                           it = copy_it;
 3832|  6.27k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  6.27k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|  6.27k|                               not variant_alternative_exhausted(ctx)) {
 3835|  6.27k|                              ctx.error = error_code::none;
 3836|  6.27k|                           }
 3837|  6.27k|                        }
 3838|  6.27k|                     }
 3839|  6.27k|                     else {
 3840|  6.27k|                        it = copy_it;
 3841|  6.27k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  6.27k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|  6.27k|                            not variant_alternative_exhausted(ctx)) {
 3844|  6.27k|                           ctx.error = error_code::none;
 3845|  6.27k|                        }
 3846|  6.27k|                     }
 3847|  6.27k|                     ++non_const_idx;
 3848|  6.27k|                  }
 3849|  6.27k|               });
 3850|  6.27k|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 884, False: 5.38k]
  ------------------
 3851|    884|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|    884|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|  6.27k|         }
 3864|  6.27k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 6.27k]
  |  Branch (3795:38): [True: 0, False: 6.27k]
  |  Branch (3795:51): [True: 0, False: 6.27k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  6.27k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 6.27k]
  |  Branch (3795:38): [True: 0, False: 6.27k]
  |  Branch (3795:51): [True: 0, False: 6.27k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  6.27k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 6.27k]
  |  Branch (3795:38): [True: 0, False: 6.27k]
  |  Branch (3795:51): [True: 0, False: 6.27k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  6.27k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  6.27k|                     auto copy_it{it};
 3801|  6.27k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  6.27k|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 4.75k, False: 1.51k]
  ------------------
 3803|  4.75k|                        value = V{};
 3804|  4.75k|                     }
 3805|  6.27k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  6.27k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 884, False: 5.38k]
  |  Branch (3806:45): [True: 0, False: 884]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|  6.27k|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 5.38k, False: 884]
  ------------------
 3810|  5.38k|                        found_match = true;
 3811|  5.38k|                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|    884|                     else {
 3840|    884|                        it = copy_it;
 3841|    884|                        rewind_depth<Options>(ctx, copy_depth);
 3842|    884|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3842:29): [True: 0, False: 884]
  |  Branch (3842:68): [True: 0, False: 0]
  ------------------
 3843|      0|                            not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3843:29): [True: 0, False: 0]
  ------------------
 3844|      0|                           ctx.error = error_code::none;
 3845|      0|                        }
 3846|    884|                     }
 3847|  6.27k|                     ++non_const_idx;
 3848|  6.27k|                  }
 3849|  6.27k|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_T3_:
   49|  6.27k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  6.27k|         else {
   60|  6.27k|            using V = std::remove_cvref_t<T>;
   61|  6.27k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  6.27k|                                             end);
   63|  6.27k|         }
   64|  6.27k|      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERPKcSC_S7_TkNS_10is_contextERNS_7contextEQntcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_T1_:
 1043|  6.27k|      {
 1044|       |         if constexpr (check_string_as_number(Opts)) {
 1045|       |            auto start = it;
 1046|       |            skip_number<Opts>(ctx, it, end);
 1047|       |            if (bool(ctx.error)) [[unlikely]] {
 1048|       |               return;
 1049|       |            }
 1050|       |            if (start == it) [[unlikely]] {
 1051|       |               ctx.error = error_code::parse_number_failure;
 1052|       |               return;
 1053|       |            }
 1054|       |            value.append(start, size_t(it - start));
 1055|       |         }
 1056|  6.27k|         else {
 1057|  6.27k|            if constexpr (!check_opening_handled(Opts)) {
 1058|       |               if constexpr (!check_ws_handled(Opts)) {
 1059|       |                  if (skip_ws<Opts>(ctx, it, end)) {
 1060|       |                     return;
 1061|       |                  }
 1062|       |               }
 1063|       |
 1064|  6.27k|               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (1064:20): [True: 0, False: 6.27k]
  ------------------
 1065|      0|                  return;
 1066|      0|               }
 1067|  6.27k|            }
 1068|       |
 1069|  6.27k|            if constexpr (not check_raw_string(Opts)) {
 1070|  6.27k|               static constexpr auto string_padding_bytes = 8;
 1071|       |
 1072|  6.27k|               if (size_t(end - it) >= 8) {
  ------------------
  |  Branch (1072:20): [True: 5.73k, False: 538]
  ------------------
 1073|  5.73k|                  auto start = it;
 1074|  5.73k|                  uint64_t ascii_acc{};
 1075|  5.73k|                  const auto end8 = end - 8;
 1076|  1.27M|                  while (true) {
  ------------------
  |  Branch (1076:26): [True: 1.27M, Folded]
  ------------------
 1077|  1.27M|                     if (it >= end8) [[unlikely]] {
  ------------------
  |  Branch (1077:26): [True: 544, False: 1.27M]
  ------------------
 1078|    544|                        break;
 1079|    544|                     }
 1080|       |
 1081|  1.27M|                     uint64_t chunk;
 1082|  1.27M|                     std::memcpy(&chunk, it, 8);
 1083|       |                     if constexpr (std::endian::native == std::endian::big) {
 1084|       |                        chunk = std::byteswap(chunk);
 1085|       |                     }
 1086|  1.27M|                     ascii_acc |= chunk;
 1087|  1.27M|                     const uint64_t test_chars = has_quote(chunk);
 1088|  1.27M|                     if (test_chars) {
  ------------------
  |  Branch (1088:26): [True: 6.92k, False: 1.26M]
  ------------------
 1089|  6.92k|                        it += (countr_zero(test_chars) >> 3);
 1090|       |
 1091|  6.92k|                        auto* prev = it - 1;
 1092|  9.17k|                        while (*prev == '\\') {
  ------------------
  |  Branch (1092:32): [True: 2.25k, False: 6.92k]
  ------------------
 1093|  2.25k|                           --prev;
 1094|  2.25k|                        }
 1095|  6.92k|                        if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (1095:29): [True: 5.18k, False: 1.73k]
  ------------------
 1096|  5.18k|                           goto continue_decode;
 1097|  5.18k|                        }
 1098|  1.73k|                        ++it; // skip the escaped quote
 1099|  1.73k|                     }
 1100|  1.26M|                     else {
 1101|  1.26M|                        it += 8;
 1102|  1.26M|                     }
 1103|  1.27M|                  }
 1104|       |
 1105|  1.93k|                  while (it[-1] == '\\') [[unlikely]] {
  ------------------
  |  Branch (1105:26): [True: 1.38k, False: 544]
  ------------------
 1106|       |                     // if we ended on an escape character then we need to rewind
 1107|       |                     // because we lost our context
 1108|  1.38k|                     --it;
 1109|  1.38k|                  }
 1110|       |
 1111|       |                  // The byte-wise tail keeps feeding the accumulator: it has to cover every byte of
 1112|       |                  // the string, or a non-ASCII byte reached here would be waved through unvalidated.
 1113|  3.69k|                  for (; it < end; ++it) {
  ------------------
  |  Branch (1113:26): [True: 3.57k, False: 126]
  ------------------
 1114|  3.57k|                     ascii_acc |= uint8_t(*it);
 1115|  3.57k|                     if (*it == '"') {
  ------------------
  |  Branch (1115:26): [True: 490, False: 3.08k]
  ------------------
 1116|    490|                        auto* prev = it - 1;
 1117|  1.14k|                        while (*prev == '\\') {
  ------------------
  |  Branch (1117:32): [True: 650, False: 490]
  ------------------
 1118|    650|                           --prev;
 1119|    650|                        }
 1120|    490|                        if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (1120:29): [True: 418, False: 72]
  ------------------
 1121|    418|                           goto continue_decode;
 1122|    418|                        }
 1123|    490|                     }
 1124|  3.57k|                  }
 1125|       |
 1126|    126|                  ctx.error = error_code::unexpected_end;
 1127|    126|                  return;
 1128|       |
 1129|  5.60k|               continue_decode:
 1130|       |
 1131|  5.60k|                  if (validate_utf8_span<Opts>(ctx, start, it, ascii_acc)) [[unlikely]] {
  ------------------
  |  Branch (1131:23): [True: 175, False: 5.43k]
  ------------------
 1132|    175|                     return;
 1133|    175|                  }
 1134|       |
 1135|  5.43k|                  const auto available_padding = size_t(end - it);
 1136|  5.43k|                  auto n = size_t(it - start);
 1137|  5.43k|                  if (available_padding >= 8) [[likely]] {
  ------------------
  |  Branch (1137:23): [True: 5.04k, False: 382]
  ------------------
 1138|  5.04k|                     value.resize(n + string_padding_bytes);
 1139|       |
 1140|  5.04k|                     auto* p = value.data();
 1141|       |
 1142|  27.4k|                     while (true) {
  ------------------
  |  Branch (1142:29): [True: 27.4k, Folded]
  ------------------
 1143|  27.4k|                        if (start >= it) {
  ------------------
  |  Branch (1143:29): [True: 4.61k, False: 22.8k]
  ------------------
 1144|  4.61k|                           break;
 1145|  4.61k|                        }
 1146|       |
 1147|  22.8k|                        std::memcpy(p, start, 8);
 1148|  22.8k|                        uint64_t swar;
 1149|  22.8k|                        std::memcpy(&swar, p, 8);
 1150|       |                        if constexpr (std::endian::native == std::endian::big) {
 1151|       |                           swar = std::byteswap(swar);
 1152|       |                        }
 1153|       |
 1154|  22.8k|                        constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
 1155|  22.8k|                        const uint64_t lo7 = swar & lo7_mask;
 1156|  22.8k|                        const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
 1157|  22.8k|                        const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
 1158|  22.8k|                        uint64_t next = ~((backslash & less_32) | swar);
 1159|       |
 1160|  22.8k|                        next &= repeat_byte8(0b10000000);
 1161|  22.8k|                        if (next == 0) {
  ------------------
  |  Branch (1161:29): [True: 20.3k, False: 2.45k]
  ------------------
 1162|  20.3k|                           start += 8;
 1163|  20.3k|                           p += 8;
 1164|  20.3k|                           continue;
 1165|  20.3k|                        }
 1166|       |
 1167|  2.45k|                        next = countr_zero(next) >> 3;
 1168|  2.45k|                        start += next;
 1169|  2.45k|                        if (start >= it) {
  ------------------
  |  Branch (1169:29): [True: 307, False: 2.14k]
  ------------------
 1170|    307|                           break;
 1171|    307|                        }
 1172|       |
 1173|  2.14k|                        if ((*start & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1173:29): [True: 38, False: 2.10k]
  ------------------
 1174|     38|                           ctx.error = error_code::syntax_error;
 1175|     38|                           return;
 1176|     38|                        }
 1177|  2.10k|                        ++start; // skip the escape
 1178|  2.10k|                        if (*start == 'u') {
  ------------------
  |  Branch (1178:29): [True: 1.32k, False: 785]
  ------------------
 1179|  1.32k|                           ++start;
 1180|  1.32k|                           p += next;
 1181|  1.32k|                           const auto mark = start;
 1182|  1.32k|                           const auto offset = handle_unicode_code_point(start, p, end);
 1183|  1.32k|                           if (offset == 0) [[unlikely]] {
  ------------------
  |  Branch (1183:32): [True: 81, False: 1.24k]
  ------------------
 1184|     81|                              ctx.error = error_code::unicode_escape_conversion_failure;
 1185|     81|                              return;
 1186|     81|                           }
 1187|  1.24k|                           n += offset;
 1188|       |                           // escape + u + unicode code points
 1189|  1.24k|                           n -= 2 + uint32_t(start - mark);
 1190|  1.24k|                        }
 1191|    785|                        else {
 1192|    785|                           p += next;
 1193|    785|                           *p = char_unescape_table[uint8_t(*start)];
 1194|    785|                           if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1194:32): [True: 12, False: 773]
  ------------------
 1195|     12|                              ctx.error = error_code::invalid_escape;
 1196|     12|                              return;
 1197|     12|                           }
 1198|    773|                           ++p;
 1199|    773|                           ++start;
 1200|    773|                           --n;
 1201|    773|                        }
 1202|  2.10k|                     }
 1203|       |
 1204|  4.91k|                     value.resize(n);
 1205|  4.91k|                     ++it;
 1206|  4.91k|                  }
 1207|    382|                  else {
 1208|       |                     // For large inputs this case of running out of buffer is very rare
 1209|    382|                     value.resize(n);
 1210|    382|                     auto* p = value.data();
 1211|       |
 1212|    382|                     it = start;
 1213|   599k|                     while (it < end) [[likely]] {
  ------------------
  |  Branch (1213:29): [True: 599k, False: 0]
  ------------------
 1214|   599k|                        if (*it == '"') {
  ------------------
  |  Branch (1214:29): [True: 244, False: 599k]
  ------------------
 1215|    244|                           value.resize(size_t(p - value.data()));
 1216|    244|                           ++it;
 1217|    244|                           return;
 1218|    244|                        }
 1219|       |
 1220|   599k|                        if ((*it & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1220:29): [True: 40, False: 599k]
  ------------------
 1221|     40|                           ctx.error = error_code::syntax_error;
 1222|     40|                           return;
 1223|     40|                        }
 1224|       |
 1225|   599k|                        *p = *it;
 1226|       |
 1227|   599k|                        if (*it == '\\') {
  ------------------
  |  Branch (1227:29): [True: 1.72k, False: 597k]
  ------------------
 1228|  1.72k|                           ++it; // skip the escape
 1229|  1.72k|                           if (*it == 'u') {
  ------------------
  |  Branch (1229:32): [True: 1.12k, False: 597]
  ------------------
 1230|  1.12k|                              ++it;
 1231|  1.12k|                              if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
  ------------------
  |  Branch (1231:35): [True: 80, False: 1.04k]
  ------------------
 1232|     80|                                 ctx.error = error_code::unicode_escape_conversion_failure;
 1233|     80|                                 return;
 1234|     80|                              }
 1235|  1.12k|                           }
 1236|    597|                           else {
 1237|    597|                              *p = char_unescape_table[uint8_t(*it)];
 1238|    597|                              if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1238:35): [True: 18, False: 579]
  ------------------
 1239|     18|                                 ctx.error = error_code::invalid_escape;
 1240|     18|                                 return;
 1241|     18|                              }
 1242|    579|                              ++p;
 1243|    579|                              ++it;
 1244|    579|                           }
 1245|  1.72k|                        }
 1246|   597k|                        else {
 1247|   597k|                           ++it;
 1248|   597k|                           ++p;
 1249|   597k|                        }
 1250|   599k|                     }
 1251|       |
 1252|      0|                     ctx.error = error_code::unexpected_end;
 1253|      0|                  }
 1254|  5.43k|               }
 1255|    538|               else {
 1256|       |                  // For short strings
 1257|       |
 1258|    538|                  std::array<char, 8> buffer{};
 1259|       |
 1260|    538|                  auto* p = buffer.data();
 1261|    538|                  const auto* const utf8_start = it;
 1262|       |
 1263|  1.20k|                  while (it < end) [[likely]] {
  ------------------
  |  Branch (1263:26): [True: 1.20k, False: 0]
  ------------------
 1264|  1.20k|                     *p = *it;
 1265|  1.20k|                     if (*it == '"') {
  ------------------
  |  Branch (1265:26): [True: 294, False: 907]
  ------------------
 1266|    294|                        if (validate_utf8_span<Opts>(ctx, utf8_start, it)) [[unlikely]] {
  ------------------
  |  Branch (1266:29): [True: 70, False: 224]
  ------------------
 1267|     70|                           return;
 1268|     70|                        }
 1269|    224|                        const size_t n = size_t(p - buffer.data());
 1270|    224|#if __has_cpp_attribute(assume) >= 202207L
 1271|    224|                        [[assume(n <= sizeof(buffer))]];
 1272|    224|#endif
 1273|    224|                        value.assign(buffer.data(), n);
 1274|    224|                        ++it;
 1275|       |                        if constexpr (not Opts.null_terminated) {
 1276|       |                           if (it == end) {
 1277|       |                              ctx.error = error_code::end_reached;
 1278|       |                              return;
 1279|       |                           }
 1280|       |                        }
 1281|    224|                        return;
 1282|    294|                     }
 1283|    907|                     else if (*it == '\\') {
  ------------------
  |  Branch (1283:31): [True: 95, False: 812]
  ------------------
 1284|     95|                        ++it; // skip the escape
 1285|       |                        if constexpr (not Opts.null_terminated) {
 1286|       |                           if (it == end) [[unlikely]] {
 1287|       |                              ctx.error = error_code::unexpected_end;
 1288|       |                              return;
 1289|       |                           }
 1290|       |                        }
 1291|     95|                        if (*it == 'u') {
  ------------------
  |  Branch (1291:29): [True: 52, False: 43]
  ------------------
 1292|     52|                           ++it;
 1293|       |                           if constexpr (not Opts.null_terminated) {
 1294|       |                              if (it == end) [[unlikely]] {
 1295|       |                                 ctx.error = error_code::unexpected_end;
 1296|       |                                 return;
 1297|       |                              }
 1298|       |                           }
 1299|     52|                           if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
  ------------------
  |  Branch (1299:32): [True: 13, False: 39]
  ------------------
 1300|     13|                              ctx.error = error_code::unicode_escape_conversion_failure;
 1301|     13|                              return;
 1302|     13|                           }
 1303|     52|                        }
 1304|     43|                        else {
 1305|     43|                           *p = char_unescape_table[uint8_t(*it)];
 1306|     43|                           if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1306:32): [True: 10, False: 33]
  ------------------
 1307|     10|                              ctx.error = error_code::invalid_escape;
 1308|     10|                              return;
 1309|     10|                           }
 1310|     33|                           ++p;
 1311|     33|                           ++it;
 1312|     33|                        }
 1313|     95|                     }
 1314|    812|                     else if ((*it & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (1314:31): [True: 221, False: 591]
  ------------------
 1315|    221|                        ctx.error = error_code::syntax_error;
 1316|    221|                        return;
 1317|    221|                     }
 1318|    591|                     else {
 1319|    591|                        ++it;
 1320|    591|                        ++p;
 1321|    591|                     }
 1322|  1.20k|                  }
 1323|       |
 1324|      0|                  ctx.error = error_code::unexpected_end;
 1325|      0|               }
 1326|       |            }
 1327|       |            else {
 1328|       |               // raw_string
 1329|       |               auto start = it;
 1330|       |               skip_string_view(ctx, it, end);
 1331|       |               if (bool(ctx.error)) [[unlikely]]
 1332|       |                  return;
 1333|       |
 1334|       |               if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]] {
 1335|       |                  return;
 1336|       |               }
 1337|       |
 1338|       |               value.assign(start, size_t(it - start));
 1339|       |               ++it;
 1340|       |            }
 1341|  6.27k|         }
 1342|  6.27k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 5.38k, False: 884]
  |  Branch (3795:38): [True: 0, False: 884]
  |  Branch (3795:51): [True: 0, False: 884]
  ------------------
 3796|  5.38k|                     return;
 3797|  5.38k|                  }
 3798|    884|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    884|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 5.38k, False: 884]
  |  Branch (3795:38): [True: 0, False: 884]
  |  Branch (3795:51): [True: 0, False: 884]
  ------------------
 3796|  5.38k|                     return;
 3797|  5.38k|                  }
 3798|    884|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    884|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 5.38k, False: 884]
  |  Branch (3795:38): [True: 0, False: 884]
  |  Branch (3795:51): [True: 0, False: 884]
  ------------------
 3796|  5.38k|                     return;
 3797|  5.38k|                  }
 3798|    884|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    884|               });
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|  1.38k|      {
 3726|  1.38k|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|  1.38k|         else {
 3732|  1.38k|            constexpr auto N = std::variant_size_v<Variant>;
 3733|  1.38k|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|  1.38k|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|  1.38k|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|  1.38k|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|  1.38k|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|  1.38k|               size_t non_const_idx = 0;
 3793|       |
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|  1.38k|                     return;
 3797|  1.38k|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  1.38k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  1.38k|                     auto copy_it{it};
 3801|  1.38k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  1.38k|                     if (!std::holds_alternative<V>(value)) {
 3803|  1.38k|                        value = V{};
 3804|  1.38k|                     }
 3805|  1.38k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  1.38k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|  1.38k|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|  1.38k|                     }
 3809|  1.38k|                     if (!bool(ctx.error)) {
 3810|  1.38k|                        found_match = true;
 3811|  1.38k|                     }
 3812|  1.38k|                     else if constexpr (not Options.null_terminated) {
 3813|  1.38k|                        constexpr bool is_complete_type =
 3814|  1.38k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|  1.38k|                        if constexpr (is_complete_type) {
 3817|  1.38k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|  1.38k|                              found_match = true;
 3819|  1.38k|                              ctx.error = error_code::none;
 3820|  1.38k|                           }
 3821|  1.38k|                           else {
 3822|  1.38k|                              it = copy_it;
 3823|  1.38k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  1.38k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|  1.38k|                                  not variant_alternative_exhausted(ctx)) {
 3826|  1.38k|                                 ctx.error = error_code::none;
 3827|  1.38k|                              }
 3828|  1.38k|                           }
 3829|  1.38k|                        }
 3830|  1.38k|                        else {
 3831|  1.38k|                           it = copy_it;
 3832|  1.38k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  1.38k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|  1.38k|                               not variant_alternative_exhausted(ctx)) {
 3835|  1.38k|                              ctx.error = error_code::none;
 3836|  1.38k|                           }
 3837|  1.38k|                        }
 3838|  1.38k|                     }
 3839|  1.38k|                     else {
 3840|  1.38k|                        it = copy_it;
 3841|  1.38k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  1.38k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|  1.38k|                            not variant_alternative_exhausted(ctx)) {
 3844|  1.38k|                           ctx.error = error_code::none;
 3845|  1.38k|                        }
 3846|  1.38k|                     }
 3847|  1.38k|                     ++non_const_idx;
 3848|  1.38k|                  }
 3849|  1.38k|               });
 3850|  1.38k|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 250, False: 1.13k]
  ------------------
 3851|    250|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|    250|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|  1.38k|         }
 3864|  1.38k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.38k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.38k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.38k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  1.38k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  1.38k|                     auto copy_it{it};
 3801|  1.38k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  1.38k|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 1.18k, False: 194]
  ------------------
 3803|  1.18k|                        value = V{};
 3804|  1.18k|                     }
 3805|  1.38k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  1.38k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 250, False: 1.13k]
  |  Branch (3806:45): [True: 0, False: 250]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|  1.38k|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 1.13k, False: 250]
  ------------------
 3810|  1.13k|                        found_match = true;
 3811|  1.13k|                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|    250|                     else {
 3840|    250|                        it = copy_it;
 3841|    250|                        rewind_depth<Options>(ctx, copy_depth);
 3842|    250|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3842:29): [True: 0, False: 250]
  |  Branch (3842:68): [True: 0, False: 0]
  ------------------
 3843|      0|                            not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3843:29): [True: 0, False: 0]
  ------------------
 3844|      0|                           ctx.error = error_code::none;
 3845|      0|                        }
 3846|    250|                     }
 3847|  1.38k|                     ++non_const_idx;
 3848|  1.38k|                  }
 3849|  1.38k|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERbTkNS_10is_contextERNS_7contextERPKcS8_EEvOT0_OT1_OT2_T3_:
   49|  1.38k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  1.38k|         else {
   60|  1.38k|            using V = std::remove_cvref_t<T>;
   61|  1.38k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  1.38k|                                             end);
   63|  1.38k|         }
   64|  1.38k|      }
_ZN3glz4fromILj10EbE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEETkNS_6bool_tERbTkNS_10is_contextERNS_7contextERPKcS8_EEvOT0_OT1_OT2_T3_:
  669|  1.38k|      {
  670|       |         if constexpr (check_quoted_num(Opts)) {
  671|       |            if (skip_ws<Opts>(ctx, it, end)) {
  672|       |               return;
  673|       |            }
  674|       |            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  675|       |               return;
  676|       |            }
  677|       |         }
  678|       |
  679|       |         if constexpr (!check_ws_handled(Opts)) {
  680|       |            if (skip_ws<Opts>(ctx, it, end)) {
  681|       |               return;
  682|       |            }
  683|       |         }
  684|       |
  685|       |         if constexpr (check_bools_as_numbers(Opts)) {
  686|       |            if (*it == '1') {
  687|       |               value = true;
  688|       |               ++it;
  689|       |            }
  690|       |            else if (*it == '0') {
  691|       |               value = false;
  692|       |               ++it;
  693|       |            }
  694|       |            else {
  695|       |               ctx.error = error_code::syntax_error;
  696|       |               return;
  697|       |            }
  698|       |         }
  699|  1.38k|         else {
  700|  1.38k|            if constexpr (not check_is_padded(Opts)) {
  701|  1.38k|               if (size_t(end - it) < 4) [[unlikely]] {
  ------------------
  |  Branch (701:20): [True: 44, False: 1.33k]
  ------------------
  702|     44|                  ctx.error = error_code::expected_true_or_false;
  703|     44|                  return;
  704|     44|               }
  705|  1.38k|            }
  706|       |
  707|  1.33k|            uint32_t c;
  708|  1.38k|            static constexpr uint32_t u_true = 0b01100101'01110101'01110010'01110100;
  709|  1.38k|            static constexpr uint32_t u_fals = 0b01110011'01101100'01100001'01100110;
  710|  1.38k|            std::memcpy(&c, it, 4);
  711|       |            if constexpr (std::endian::native == std::endian::big) {
  712|       |               c = std::byteswap(c);
  713|       |            }
  714|  1.38k|            it += 4;
  715|  1.38k|            if (c == u_true) {
  ------------------
  |  Branch (715:17): [True: 862, False: 521]
  ------------------
  716|    862|               value = true;
  717|    862|            }
  718|    521|            else if (it == end) [[unlikely]] {
  ------------------
  |  Branch (718:22): [True: 25, False: 496]
  ------------------
  719|     25|               ctx.error = error_code::unexpected_end;
  720|     25|               return;
  721|     25|            }
  722|    496|            else {
  723|    496|               if (c == u_fals && (*it == 'e')) [[likely]] {
  ------------------
  |  Branch (723:20): [True: 286, False: 210]
  |  Branch (723:35): [True: 271, False: 15]
  ------------------
  724|    271|                  value = false;
  725|    271|                  ++it;
  726|    271|               }
  727|    225|               else [[unlikely]] {
  728|    225|                  ctx.error = error_code::expected_true_or_false;
  729|    225|                  return;
  730|    225|               }
  731|    496|            }
  732|  1.38k|         }
  733|       |
  734|       |         if constexpr (check_quoted_num(Opts)) {
  735|       |            if constexpr (not Opts.null_terminated) {
  736|       |               if (it == end) [[unlikely]] {
  737|       |                  ctx.error = error_code::unexpected_end;
  738|       |                  return;
  739|       |               }
  740|       |            }
  741|       |            if (match<'"'>(ctx, it)) {
  742|       |               return;
  743|       |            }
  744|       |            if constexpr (not Opts.null_terminated) {
  745|       |               if (it == end) {
  746|       |                  ctx.error = error_code::end_reached;
  747|       |                  return;
  748|       |               }
  749|       |            }
  750|       |         }
  751|  1.38k|         else {
  752|       |            if constexpr (not Opts.null_terminated) {
  753|       |               if (it == end) {
  754|       |                  ctx.error = error_code::end_reached;
  755|       |                  return;
  756|       |               }
  757|       |            }
  758|  1.38k|         }
  759|  1.38k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 1.13k, False: 250]
  |  Branch (3795:38): [True: 0, False: 250]
  |  Branch (3795:51): [True: 0, False: 250]
  ------------------
 3796|  1.13k|                     return;
 3797|  1.13k|                  }
 3798|    250|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    250|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 1.13k, False: 250]
  |  Branch (3795:38): [True: 0, False: 250]
  |  Branch (3795:51): [True: 0, False: 250]
  ------------------
 3796|  1.13k|                     return;
 3797|  1.13k|                  }
 3798|    250|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    250|               });
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|  2.19M|      {
 3726|  2.19M|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|  2.19M|         else {
 3732|  2.19M|            constexpr auto N = std::variant_size_v<Variant>;
 3733|  2.19M|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|  2.19M|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|  2.19M|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|  2.19M|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|  2.19M|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|  2.19M|               size_t non_const_idx = 0;
 3793|       |
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|  2.19M|                     return;
 3797|  2.19M|                  }
 3798|  2.19M|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  2.19M|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  2.19M|                     auto copy_it{it};
 3801|  2.19M|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  2.19M|                     if (!std::holds_alternative<V>(value)) {
 3803|  2.19M|                        value = V{};
 3804|  2.19M|                     }
 3805|  2.19M|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  2.19M|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|  2.19M|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|  2.19M|                     }
 3809|  2.19M|                     if (!bool(ctx.error)) {
 3810|  2.19M|                        found_match = true;
 3811|  2.19M|                     }
 3812|  2.19M|                     else if constexpr (not Options.null_terminated) {
 3813|  2.19M|                        constexpr bool is_complete_type =
 3814|  2.19M|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|  2.19M|                        if constexpr (is_complete_type) {
 3817|  2.19M|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|  2.19M|                              found_match = true;
 3819|  2.19M|                              ctx.error = error_code::none;
 3820|  2.19M|                           }
 3821|  2.19M|                           else {
 3822|  2.19M|                              it = copy_it;
 3823|  2.19M|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  2.19M|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|  2.19M|                                  not variant_alternative_exhausted(ctx)) {
 3826|  2.19M|                                 ctx.error = error_code::none;
 3827|  2.19M|                              }
 3828|  2.19M|                           }
 3829|  2.19M|                        }
 3830|  2.19M|                        else {
 3831|  2.19M|                           it = copy_it;
 3832|  2.19M|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  2.19M|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|  2.19M|                               not variant_alternative_exhausted(ctx)) {
 3835|  2.19M|                              ctx.error = error_code::none;
 3836|  2.19M|                           }
 3837|  2.19M|                        }
 3838|  2.19M|                     }
 3839|  2.19M|                     else {
 3840|  2.19M|                        it = copy_it;
 3841|  2.19M|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  2.19M|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|  2.19M|                            not variant_alternative_exhausted(ctx)) {
 3844|  2.19M|                           ctx.error = error_code::none;
 3845|  2.19M|                        }
 3846|  2.19M|                     }
 3847|  2.19M|                     ++non_const_idx;
 3848|  2.19M|                  }
 3849|  2.19M|               });
 3850|  2.19M|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 1.70k, False: 2.18M]
  ------------------
 3851|  1.70k|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|  1.70k|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|  2.19M|         }
 3864|  2.19M|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 2.19M]
  |  Branch (3795:38): [True: 0, False: 2.19M]
  |  Branch (3795:51): [True: 0, False: 2.19M]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  2.19M|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  2.19M|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 2.19M]
  |  Branch (3795:38): [True: 0, False: 2.19M]
  |  Branch (3795:51): [True: 0, False: 2.19M]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  2.19M|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  2.19M|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  2.19M|                     auto copy_it{it};
 3801|  2.19M|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  2.19M|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 1.92M, False: 270k]
  ------------------
 3803|  1.92M|                        value = V{};
 3804|  1.92M|                     }
 3805|  2.19M|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  2.19M|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 1.70k, False: 2.18M]
  |  Branch (3806:45): [True: 0, False: 1.70k]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|  2.19M|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 2.18M, False: 1.70k]
  ------------------
 3810|  2.18M|                        found_match = true;
 3811|  2.18M|                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|  1.70k|                     else {
 3840|  1.70k|                        it = copy_it;
 3841|  1.70k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  1.70k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3842:29): [True: 0, False: 1.70k]
  |  Branch (3842:68): [True: 0, False: 0]
  ------------------
 3843|      0|                            not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3843:29): [True: 0, False: 0]
  ------------------
 3844|      0|                           ctx.error = error_code::none;
 3845|      0|                        }
 3846|  1.70k|                     }
 3847|  2.19M|                     ++non_const_idx;
 3848|  2.19M|                  }
 3849|  2.19M|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERdTkNS_10is_contextERNS_7contextERPKcS8_EEvOT0_OT1_OT2_T3_:
   49|  2.19M|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  2.19M|         else {
   60|  2.19M|            using V = std::remove_cvref_t<T>;
   61|  2.19M|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  2.19M|                                             end);
   63|  2.19M|         }
   64|  2.19M|      }
_ZN3glz4fromILj10EdE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEERPKcRdTkNS_10is_contextERNS_7contextES5_EEvOT1_OT2_OT0_T3_:
  767|  2.19M|      {
  768|       |         if constexpr (check_quoted_num(Opts)) {
  769|       |            if (skip_ws<Opts>(ctx, it, end)) {
  770|       |               return;
  771|       |            }
  772|       |            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  773|       |               return;
  774|       |            }
  775|       |         }
  776|       |
  777|       |         if constexpr (!check_ws_handled(Opts)) {
  778|       |            if (skip_ws<Opts>(ctx, it, end)) {
  779|       |               return;
  780|       |            }
  781|       |         }
  782|       |
  783|  2.19M|         using V = std::decay_t<decltype(value)>;
  784|       |         if constexpr (int_t<V>) {
  785|       |            static_assert(sizeof(*it) == sizeof(char));
  786|       |
  787|       |            if constexpr (Opts.null_terminated) {
  788|       |               if (not glz::atoi(value, it)) [[unlikely]] {
  789|       |                  ctx.error = error_code::parse_number_failure;
  790|       |                  return;
  791|       |               }
  792|       |            }
  793|       |            else {
  794|       |               if (not glz::atoi(value, it, end)) [[unlikely]] {
  795|       |                  ctx.error = error_code::parse_number_failure;
  796|       |                  return;
  797|       |               }
  798|       |            }
  799|       |         }
  800|  2.19M|         else {
  801|       |// float128_t requires std::from_chars for floating-point, unavailable on older Apple platforms (iOS < 16.3)
  802|  2.19M|#if !defined(_LIBCPP_VERSION) || defined(_LIBCPP_AVAILABILITY_HAS_TO_CHARS_FLOATING_POINT)
  803|       |            if constexpr (is_float128<V>) {
  804|       |               auto [ptr, ec] = std::from_chars(it, end, value);
  805|       |               if (ec != std::errc()) {
  806|       |                  ctx.error = error_code::parse_number_failure;
  807|       |                  return;
  808|       |               }
  809|       |               it = ptr;
  810|       |            }
  811|       |            else
  812|       |#endif
  813|  2.19M|            {
  814|       |               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
  815|       |                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
  816|       |                  // place
  817|       |                  V temp;
  818|       |                  if constexpr (is_size_optimized(Opts)) {
  819|       |                     auto [ptr, ec] = simple_float::from_chars<Opts.null_terminated>(it, end, temp);
  820|       |                     if (ec != std::errc{}) [[unlikely]] {
  821|       |                        ctx.error = error_code::parse_number_failure;
  822|       |                        return;
  823|       |                     }
  824|       |                     it = ptr;
  825|       |                  }
  826|       |                  else {
  827|       |                     auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
  828|       |                     if (ec != std::errc()) [[unlikely]] {
  829|       |                        ctx.error = error_code::parse_number_failure;
  830|       |                        return;
  831|       |                     }
  832|       |                     it = ptr;
  833|       |                  }
  834|       |                  value = temp;
  835|       |               }
  836|  2.19M|               else {
  837|       |                  if constexpr (is_size_optimized(Opts)) {
  838|       |                     auto [ptr, ec] = simple_float::from_chars<Opts.null_terminated>(it, end, value);
  839|       |                     if (ec != std::errc{}) [[unlikely]] {
  840|       |                        ctx.error = error_code::parse_number_failure;
  841|       |                        return;
  842|       |                     }
  843|       |                     it = ptr;
  844|       |                  }
  845|  2.19M|                  else {
  846|  2.19M|                     auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
  847|  2.19M|                     if (ec != std::errc()) [[unlikely]] {
  ------------------
  |  Branch (847:26): [True: 1.70k, False: 2.18M]
  ------------------
  848|  1.70k|                        ctx.error = error_code::parse_number_failure;
  849|  1.70k|                        return;
  850|  1.70k|                     }
  851|  2.18M|                     it = ptr;
  852|  2.18M|                  }
  853|  2.19M|               }
  854|  2.19M|            }
  855|  2.19M|         }
  856|       |
  857|       |         if constexpr (check_quoted_num(Opts)) {
  858|       |            if constexpr (not Opts.null_terminated) {
  859|       |               if (it == end) [[unlikely]] {
  860|       |                  ctx.error = error_code::unexpected_end;
  861|       |                  return;
  862|       |               }
  863|       |            }
  864|       |            if (match<'"'>(ctx, it)) {
  865|       |               return;
  866|       |            }
  867|       |            if constexpr (not Opts.null_terminated) {
  868|       |               if (it == end) {
  869|       |                  ctx.error = error_code::end_reached;
  870|       |                  return;
  871|       |               }
  872|       |            }
  873|       |         }
  874|  2.19M|         else {
  875|       |            if constexpr (not Opts.null_terminated) {
  876|       |               if (it == end) {
  877|       |                  ctx.error = error_code::end_reached;
  878|       |                  return;
  879|       |               }
  880|       |            }
  881|  2.19M|         }
  882|  2.19M|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_9is_bufferERNSt3__16vectorIcNS6_9allocatorIcEEEEQnt18is_input_streamingIu20__remove_reference_tIT0_EEEENS_9error_ctxERT_OSC_:
 5266|  11.3k|   {
 5267|  11.3k|      context ctx{};
 5268|  11.3k|      return read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
 5269|  11.3k|   }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERNS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
   49|  11.3k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  11.3k|         else {
   60|  11.3k|            using V = std::remove_cvref_t<T>;
   61|  11.3k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  11.3k|                                             end);
   63|  11.3k|         }
   64|  11.3k|      }
_ZN3glz4fromILj10ENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERS4_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
  150|  11.3k|      {
  151|  11.3k|         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
  152|  11.3k|         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
  153|  11.3k|                                          std::forward<Ctx>(ctx), std::forward<It0>(it), end);
  154|  11.3k|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4065|  11.3k|      {
 4066|       |         if constexpr (tagging == variant_tagging_kind::adjacent) {
 4067|       |            read_adjacent<Options>(value, ctx, it, end);
 4068|       |         }
 4069|  11.3k|         else {
 4070|  11.3k|            read_deduced<Options>(value, ctx, it, end);
 4071|  11.3k|         }
 4072|  11.3k|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE12read_deducedITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4076|  11.3k|      {
 4077|  11.3k|         constexpr auto Opts = ws_handled_off<Options>();
 4078|  11.3k|         if constexpr (variant_is_auto_deducible<T>()) {
 4079|  11.3k|            if constexpr (not check_ws_handled(Options)) {
 4080|  11.3k|               if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (4080:20): [True: 0, False: 11.3k]
  ------------------
 4081|      0|                  return;
 4082|      0|               }
 4083|  11.3k|            }
 4084|       |
 4085|  11.3k|            switch (*it) {
 4086|     15|            case '\0':
  ------------------
  |  Branch (4086:13): [True: 15, False: 11.3k]
  ------------------
 4087|     15|               ctx.error = error_code::unexpected_end;
 4088|     15|               return;
 4089|  5.14k|            case '{': {
  ------------------
  |  Branch (4089:13): [True: 5.14k, False: 6.17k]
  ------------------
 4090|       |               // This branch consumes the brace itself and hands the object to a reader with
 4091|       |               // `opening_handled`, which therefore does not count the level -- but does release it at
 4092|       |               // the closing brace. So the level is taken here, in both buffer modes, and paid back by
 4093|       |               // the reader below.
 4094|  5.14k|               if (enter_depth(ctx)) [[unlikely]] {
  ------------------
  |  Branch (4094:20): [True: 0, False: 5.14k]
  ------------------
 4095|      0|                  return;
 4096|      0|               }
 4097|       |
 4098|  5.14k|               ++it;
 4099|       |               if constexpr (not Opts.null_terminated) {
 4100|       |                  if (it == end) [[unlikely]] {
 4101|       |                     ctx.error = error_code::unexpected_end;
 4102|       |                     return;
 4103|       |                  }
 4104|       |               }
 4105|  5.14k|               using type_counts = variant_type_count<T>;
 4106|  5.14k|               constexpr auto n_object_candidates = variant_object_candidate_count_v<Opts, T>;
 4107|       |               if constexpr (n_object_candidates < 1) {
 4108|       |                  ctx.error = error_code::no_matching_variant_type;
 4109|       |                  return;
 4110|       |               }
 4111|  5.14k|               else if constexpr (n_object_candidates == 1 && tag_v<T>.empty()) {
 4112|  5.14k|                  constexpr auto first_idx = variant_first_object_candidate_v<Opts, T>;
 4113|  5.14k|                  using V = std::variant_alternative_t<first_idx, T>;
 4114|  5.14k|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4114:23): [True: 5.14k, False: 0]
  ------------------
 4115|  5.14k|                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
 4116|  5.14k|                  return;
 4117|       |               }
 4118|       |               else {
 4119|       |                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
 4120|       |                  static constexpr auto& deduction_bits = variant_deduction_bits<T>;
 4121|       |                  static constexpr size_t deduction_key_count = variant_deduction_key_count<T>;
 4122|       |                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
 4123|       |
 4124|       |                  // Track if we've encountered a tag and what value it had
 4125|       |                  std::optional<size_t> tag_specified_index{};
 4126|       |
 4127|       |                  if (skip_ws<Opts>(ctx, it, end)) {
 4128|       |                     return;
 4129|       |                  }
 4130|       |                  // Once the reader knows which alternative this object holds it may have to read
 4131|       |                  // it again from here. Anchor the position rather than keep the pointer: the scan
 4132|       |                  // below skips values, and a streaming skip refills, which moves the window out
 4133|       |                  // from under a raw pointer (see rewind_anchor).
 4134|       |                  auto start = make_rewind_anchor(ctx, it);
 4135|       |                  bool first_key = true;
 4136|       |                  // Parse bifurcation for tagged variants:
 4137|       |                  //
 4138|       |                  // Without this optimization, tagged variant parsing always uses two passes:
 4139|       |                  //   1. Scan all keys to find the tag (e.g. "type"), skipping values
 4140|       |                  //   2. Reset `it = start` and re-parse the entire object into the resolved type
 4141|       |                  //
 4142|       |                  // When the tag is the first key, the second pass redundantly re-reads every
 4143|       |                  // field that follows it. This lambda avoids that: if the tag was the first key,
 4144|       |                  // it advances past the trailing comma so the object parser picks up at the
 4145|       |                  // second field. If the tag was found later, it falls back to the full re-parse.
 4146|       |                  //
 4147|       |                  // One exception: if the tag name is also a field on the resolved struct
 4148|       |                  // (contains_tag), we must re-parse regardless so the value is stored in
 4149|       |                  // the struct field. This override is applied inside each std::visit lambda.
 4150|       |                  //
 4151|       |                  // Either way the rewind can fail under a streaming read: the window only holds so
 4152|       |                  // much, and an object wider than it has no start left to return to.
 4153|       |                  auto position_after_tag = [&] {
 4154|       |                     if (first_key) {
 4155|       |                        if (*it == ',') ++it; // skip comma; handles tag-only objects where *it == '}'
 4156|       |                        return true;
 4157|       |                     }
 4158|       |                     return start.rewind(ctx, it, end); // tag came later, re-parse from the beginning
 4159|       |                  };
 4160|       |                  // `first_key` also answers "were we reset to the object start", which is what
 4161|       |                  // position_after_tag does for every key but the first.
 4162|       |                  for (; *it != '}'; first_key = false) {
 4163|       |                     if (!first_key) {
 4164|       |                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
 4165|       |                           return;
 4166|       |                        }
 4167|       |                     }
 4168|       |
 4169|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4170|       |                        return;
 4171|       |                     }
 4172|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4173|       |                        return;
 4174|       |                     }
 4175|       |
 4176|       |                     auto* key_start = it;
 4177|       |                     skip_string_view(ctx, it, end);
 4178|       |                     if (bool(ctx.error)) [[unlikely]]
 4179|       |                        return;
 4180|       |                     if (validate_utf8_span<Opts>(ctx, key_start, it)) [[unlikely]]
 4181|       |                        return;
 4182|       |                     const sv key = {key_start, size_t(it - key_start)};
 4183|       |
 4184|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4185|       |                        return;
 4186|       |                     }
 4187|       |
 4188|       |                     if constexpr (deduction_key_count > 0) {
 4189|       |                        // We first check if a tag is defined and see if the key matches the tag
 4190|       |                        if constexpr (not tag_v<T>.empty()) {
 4191|       |                           if (key == tag_v<T>) {
 4192|       |                              if (parse_ws_colon<Opts>(ctx, it, end)) {
 4193|       |                                 return;
 4194|       |                              }
 4195|       |
 4196|       |                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
 4197|       |
 4198|       |                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
 4199|       |                              if constexpr (std::integral<id_type>) {
 4200|       |                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
 4201|       |                              }
 4202|       |                              else {
 4203|       |                                 // The id is turned into an index below and never leaves this
 4204|       |                                 // reader, so the view of the window it borrows cannot outlive it.
 4205|       |                                 parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4206|       |                              }
 4207|       |                              if (bool(ctx.error)) [[unlikely]]
 4208|       |                                 return;
 4209|       |                              if (skip_ws<Opts>(ctx, it, end)) {
 4210|       |                                 return;
 4211|       |                              }
 4212|       |                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
 4213|       |                                 ctx.error = error_code::syntax_error;
 4214|       |                                 return;
 4215|       |                              }
 4216|       |
 4217|       |                              size_t type_index;
 4218|       |                              if constexpr (std::integral<id_type>) {
 4219|       |                                 type_index = variant_id_to_index<T>::op(type_id);
 4220|       |                              }
 4221|       |                              else {
 4222|       |                                 type_index = variant_id_to_index<T>::op(
 4223|       |                                    type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4224|       |                              }
 4225|       |                              if (type_index < ids_v<T>.size()) [[likely]] {
 4226|       |                                 // Check if the deduced types include the tag-specified type
 4227|       |                                 // If not, the tag doesn't match the fields
 4228|       |                                 // We're already inside if constexpr (deduction_registry.size()), so we know deduction
 4229|       |                                 // is happening. At this point, possible_types has been narrowed by field deduction.
 4230|       |                                 // Check if the tag-specified type is still possible
 4231|       |                                 const bool type_is_possible = possible_types[type_index];
 4232|       |                                 if (!type_is_possible) {
 4233|       |                                    // Tag specifies a type that doesn't match the fields seen so far
 4234|       |                                    ctx.error = error_code::no_matching_variant_type;
 4235|       |                                    return;
 4236|       |                                 }
 4237|       |
 4238|       |                                 if (!position_after_tag()) return;
 4239|       |                                 tag_specified_index = type_index; // Store the tag-specified type
 4240|       |                                 if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4241|       |                                 std::visit(
 4242|       |                                    [&](auto&& v) {
 4243|       |                                       using V = std::decay_t<decltype(v)>;
 4244|       |                                       constexpr bool is_object =
 4245|       |                                          (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4246|       |                                       if constexpr (variant_unit_alternative<V>) {
 4247|       |                                          // A unit alternative carries no data; its object holds only the
 4248|       |                                          // discriminator. Consume that body through an empty reflected object so
 4249|       |                                          // unknown-key policy and terminator handling match every other alternative.
 4250|       |                                          detail::variant_unit_body unit_body{};
 4251|       |                                          from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4252|       |                                                                                             tag_literal>(unit_body,
 4253|       |                                                                                                          ctx, it, end);
 4254|       |                                       }
 4255|       |                                       else if constexpr (is_object) {
 4256|       |                                          if constexpr (contains_tag<V, tag_literal>()) {
 4257|       |                                             // tag is a struct field, must re-parse
 4258|       |                                             if (!start.rewind(ctx, it, end)) return;
 4259|       |                                          }
 4260|       |                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
 4261|       |                                                                                                           end);
 4262|       |                                       }
 4263|       |                                       else if constexpr (is_memory_object<V>) {
 4264|       |                                          if (!v) {
 4265|       |                                             if constexpr (is_specialization_v<V, std::optional>) {
 4266|       |                                                if constexpr (requires { v.emplace(); }) {
 4267|       |                                                   v.emplace();
 4268|       |                                                }
 4269|       |                                                else {
 4270|       |                                                   v = typename V::value_type{};
 4271|       |                                                }
 4272|       |                                             }
 4273|       |                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4274|       |                                                v = std::make_unique<typename V::element_type>();
 4275|       |                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4276|       |                                                v = std::make_shared<typename V::element_type>();
 4277|       |                                             else if constexpr (constructible<V>) {
 4278|       |                                                v = meta_construct_v<V>();
 4279|       |                                             }
 4280|       |                                             else if constexpr (std::is_pointer_v<V> &&
 4281|       |                                                                can_allocate_raw_pointer<Opts,
 4282|       |                                                                                         std::decay_t<decltype(ctx)>>) {
 4283|       |                                                if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4284|       |                                                   return;
 4285|       |                                                }
 4286|       |                                             }
 4287|       |                                             else {
 4288|       |                                                ctx.error = error_code::invalid_nullable_read;
 4289|       |                                                return;
 4290|       |                                                // Cannot read into unset nullable that is not std::optional,
 4291|       |                                                // std::unique_ptr, or std::shared_ptr
 4292|       |                                             }
 4293|       |                                          }
 4294|       |                                          if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4295|       |                                             // tag is a struct field, must re-parse
 4296|       |                                             if (!start.rewind(ctx, it, end)) return;
 4297|       |                                          }
 4298|       |                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4299|       |                                             *v, ctx, it, end);
 4300|       |                                       }
 4301|       |                                       else if constexpr (custom_read<V>) {
 4302|       |                                          // Custom handlers parse the remaining body themselves and do not
 4303|       |                                          // accept the tag template parameter; the tag was already consumed.
 4304|       |                                          // This only works when the tag was the first key. If it came later,
 4305|       |                                          // we were reset to the object start and the custom handler would
 4306|       |                                          // absorb the tag, so error rather than corrupt the value.
 4307|       |                                          if (!first_key) {
 4308|       |                                             ctx.error = error_code::feature_not_supported;
 4309|       |                                             ctx.custom_error_message =
 4310|       |                                                "the tag must be the first key for a custom variant alternative";
 4311|       |                                             return;
 4312|       |                                          }
 4313|       |                                          from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4314|       |                                       }
 4315|       |                                    },
 4316|       |                                    value);
 4317|       |
 4318|       |                                 return; // we've decoded our target type
 4319|       |                              }
 4320|       |                              else [[unlikely]] {
 4321|       |                                 // Check if we have a default type (ids array shorter than variant)
 4322|       |                                 constexpr auto ids_size = ids_v<T>.size();
 4323|       |                                 constexpr auto variant_size = std::variant_size_v<T>;
 4324|       |                                 if constexpr (ids_size < variant_size) {
 4325|       |                                    // Use the first unlabeled type as the default
 4326|       |                                    const auto default_type_index = ids_size;
 4327|       |
 4328|       |                                    if (!position_after_tag()) return;
 4329|       |                                    tag_specified_index = default_type_index; // Store the default type index
 4330|       |                                    if (value.index() != default_type_index)
 4331|       |                                       emplace_runtime_variant(value, default_type_index);
 4332|       |                                    std::visit(
 4333|       |                                       [&](auto&& v) {
 4334|       |                                          using V = std::decay_t<decltype(v)>;
 4335|       |                                          constexpr bool is_object =
 4336|       |                                             (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4337|       |                                          if constexpr (variant_unit_alternative<V>) {
 4338|       |                                             // A unit alternative carries no data; its object holds only the
 4339|       |                                             // discriminator. Consume that body through an empty reflected object so
 4340|       |                                             // unknown-key policy and terminator handling match every other
 4341|       |                                             // alternative.
 4342|       |                                             detail::variant_unit_body unit_body{};
 4343|       |                                             from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4344|       |                                                                                                tag_literal>(
 4345|       |                                                unit_body, ctx, it, end);
 4346|       |                                          }
 4347|       |                                          else if constexpr (is_object) {
 4348|       |                                             if constexpr (contains_tag<V, tag_literal>()) {
 4349|       |                                                // tag is a struct field, must re-parse
 4350|       |                                                if (!start.rewind(ctx, it, end)) return;
 4351|       |                                             }
 4352|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4353|       |                                          }
 4354|       |                                          else if constexpr (is_memory_object<V>) {
 4355|       |                                             if (!v) {
 4356|       |                                                if constexpr (is_specialization_v<V, std::optional>) {
 4357|       |                                                   if constexpr (requires { v.emplace(); }) {
 4358|       |                                                      v.emplace();
 4359|       |                                                   }
 4360|       |                                                   else {
 4361|       |                                                      v = typename V::value_type{};
 4362|       |                                                   }
 4363|       |                                                }
 4364|       |                                                else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4365|       |                                                   v = std::make_unique<typename V::element_type>();
 4366|       |                                                else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4367|       |                                                   v = std::make_shared<typename V::element_type>();
 4368|       |                                                else if constexpr (constructible<V>) {
 4369|       |                                                   v = meta_construct_v<V>();
 4370|       |                                                }
 4371|       |                                                else if constexpr (std::is_pointer_v<V> &&
 4372|       |                                                                   can_allocate_raw_pointer<
 4373|       |                                                                      Opts, std::decay_t<decltype(ctx)>>) {
 4374|       |                                                   if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4375|       |                                                      return;
 4376|       |                                                   }
 4377|       |                                                }
 4378|       |                                                else {
 4379|       |                                                   ctx.error = error_code::invalid_nullable_read;
 4380|       |                                                   return;
 4381|       |                                                }
 4382|       |                                             }
 4383|       |                                             if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4384|       |                                                // tag is a struct field, must re-parse
 4385|       |                                                if (!start.rewind(ctx, it, end)) return;
 4386|       |                                             }
 4387|       |                                             from<JSON, memory_type<V>>::template op<opening_handled<Opts>()>(*v, ctx,
 4388|       |                                                                                                              it, end);
 4389|       |                                          }
 4390|       |                                          else if constexpr (custom_read<V>) {
 4391|       |                                             // Custom handlers parse the remaining body themselves; this only
 4392|       |                                             // works when the tag was the first key (see above). If it came
 4393|       |                                             // later we were reset to the object start, so error rather than
 4394|       |                                             // let the custom handler absorb the tag.
 4395|       |                                             if (!first_key) {
 4396|       |                                                ctx.error = error_code::feature_not_supported;
 4397|       |                                                ctx.custom_error_message =
 4398|       |                                                   "the tag must be the first key for a custom variant alternative";
 4399|       |                                                return;
 4400|       |                                             }
 4401|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4402|       |                                          }
 4403|       |                                       },
 4404|       |                                       value);
 4405|       |
 4406|       |                                    return;
 4407|       |                                 }
 4408|       |                                 else {
 4409|       |                                    ctx.error = error_code::no_matching_variant_type;
 4410|       |                                    ctx.custom_error_message = variant_ids_string_v<T>;
 4411|       |                                    return;
 4412|       |                                 }
 4413|       |                              }
 4414|       |                           }
 4415|       |                        }
 4416|       |
 4417|       |                        // Inline decode_hash lookup for variant deduction
 4418|       |                        using deduction_keys_t = keys_wrapper<variant_deduction_keys<T>>;
 4419|       |                        constexpr auto& DeductionHashInfo = hash_info<deduction_keys_t>;
 4420|       |                        const auto deduction_index =
 4421|       |                           decode_hash_with_size<JSON, deduction_keys_t, DeductionHashInfo, DeductionHashInfo.type>::op(
 4422|       |                              key.data(), key.data() + key.size(), key.size());
 4423|       |                        if (deduction_index < deduction_key_count && variant_deduction_keys<T>[deduction_index] == key)
 4424|       |                           [[likely]] {
 4425|       |                           possible_types &= deduction_bits[deduction_index];
 4426|       |                        }
 4427|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4428|       |                           ctx.error = error_code::unknown_key;
 4429|       |                           return;
 4430|       |                        }
 4431|       |                     }
 4432|       |                     else if constexpr (not tag_v<T>.empty()) {
 4433|       |                        // empty object case for variant, if there are no normal elements
 4434|       |                        if (key == tag_v<T>) {
 4435|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4436|       |                              return;
 4437|       |                           }
 4438|       |
 4439|       |                           // The id is turned into an index below and never leaves this reader,
 4440|       |                           // so the view of the window it borrows cannot outlive that window.
 4441|       |                           std::string_view type_id{};
 4442|       |                           parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4443|       |                           if (bool(ctx.error)) [[unlikely]]
 4444|       |                              return;
 4445|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4446|       |                              return;
 4447|       |                           }
 4448|       |
 4449|       |                           const auto type_index = variant_id_to_index<T>::op(
 4450|       |                              type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4451|       |                           if (type_index < ids_v<T>.size()) [[likely]] {
 4452|       |                              if (!position_after_tag()) return;
 4453|       |                              tag_specified_index = type_index; // Store the tag-specified type
 4454|       |                              if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4455|       |                           }
 4456|       |                           else {
 4457|       |                              // Check if we have a default type (ids array shorter than variant)
 4458|       |                              constexpr auto ids_size = ids_v<T>.size();
 4459|       |                              constexpr auto variant_size = std::variant_size_v<T>;
 4460|       |                              if constexpr (ids_size < variant_size) {
 4461|       |                                 // Use the first unlabeled type as the default
 4462|       |                                 if (!position_after_tag()) return;
 4463|       |                                 const auto default_index = ids_size;
 4464|       |                                 tag_specified_index = default_index; // Store the default type index
 4465|       |                                 if (value.index() != default_index) emplace_runtime_variant(value, default_index);
 4466|       |                              }
 4467|       |                              else {
 4468|       |                                 ctx.error = error_code::no_matching_variant_type;
 4469|       |                                 ctx.custom_error_message = variant_ids_string_v<T>;
 4470|       |                                 return;
 4471|       |                              }
 4472|       |                           }
 4473|       |                           // Parse the type (handles tag skipping and unknown keys)
 4474|       |                           std::visit(
 4475|       |                              [&](auto&& v) {
 4476|       |                                 using V = std::decay_t<decltype(v)>;
 4477|       |                                 if constexpr (custom_read<V>) {
 4478|       |                                    // Custom handlers parse the remaining object body themselves and do not
 4479|       |                                    // accept the tag template parameter that reflected objects use to skip an
 4480|       |                                    // interior tag key. That only works when the tag is the first key (it was
 4481|       |                                    // just consumed). If the tag came after other keys, position_after_tag()
 4482|       |                                    // reset us to the object start and the custom handler would absorb the tag
 4483|       |                                    // into its value, so error here rather than corrupt the result.
 4484|       |                                    if (!first_key) {
 4485|       |                                       ctx.error = error_code::feature_not_supported;
 4486|       |                                       ctx.custom_error_message =
 4487|       |                                          "the tag must be the first key for a custom variant alternative";
 4488|       |                                       return;
 4489|       |                                    }
 4490|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4491|       |                                 }
 4492|       |                                 else {
 4493|       |                                    if constexpr (contains_tag<V, tag_literal>()) {
 4494|       |                                       // tag is a struct field, must re-parse
 4495|       |                                       if (!start.rewind(ctx, it, end)) return;
 4496|       |                                    }
 4497|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4498|       |                                 }
 4499|       |                              },
 4500|       |                              value);
 4501|       |                           return;
 4502|       |                        }
 4503|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4504|       |                           ctx.error = error_code::unknown_key;
 4505|       |                           return;
 4506|       |                        }
 4507|       |                        else {
 4508|       |                           // Skip unknown key's value (non-tag key in empty variant)
 4509|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4510|       |                              return;
 4511|       |                           }
 4512|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 4513|       |                           if (bool(ctx.error)) [[unlikely]]
 4514|       |                              return;
 4515|       |                           resync_window_end(ctx, end); // a streaming skip refills
 4516|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4517|       |                              return;
 4518|       |                           }
 4519|       |                           continue; // Continue loop to find the tag
 4520|       |                        }
 4521|       |                     }
 4522|       |                     else if constexpr (Opts.error_on_unknown_keys) {
 4523|       |                        ctx.error = error_code::unknown_key;
 4524|       |                        return;
 4525|       |                     }
 4526|       |
 4527|       |                     auto matching_types = possible_types.popcount();
 4528|       |                     if (matching_types == 0) {
 4529|       |                        ctx.error = error_code::no_matching_variant_type;
 4530|       |                        return;
 4531|       |                     }
 4532|       |                     // Only short-circuit for variants without tags
 4533|       |                     else if constexpr (tag_v<T>.empty()) {
 4534|       |                        if (matching_types == 1) {
 4535|       |                           if (!start.rewind(ctx, it, end)) return;
 4536|       |                           const auto type_index = possible_types.countr_zero();
 4537|       |
 4538|       |                           if (value.index() != static_cast<size_t>(type_index))
 4539|       |                              emplace_runtime_variant(value, type_index);
 4540|       |                           std::visit(
 4541|       |                              [&](auto&& v) {
 4542|       |                                 using V = std::decay_t<decltype(v)>;
 4543|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4544|       |                                 if constexpr (variant_unit_alternative<V>) {
 4545|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4546|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4547|       |                                    // terminator handling match every other alternative.
 4548|       |                                    detail::variant_unit_body unit_body{};
 4549|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4550|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4551|       |                                                                                                    end);
 4552|       |                                 }
 4553|       |                                 else if constexpr (is_object) {
 4554|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4555|       |                                 }
 4556|       |                                 else if constexpr (is_memory_object<V>) {
 4557|       |                                    if (!v) {
 4558|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4559|       |                                          if constexpr (requires { v.emplace(); }) {
 4560|       |                                             v.emplace();
 4561|       |                                          }
 4562|       |                                          else {
 4563|       |                                             v = typename V::value_type{};
 4564|       |                                          }
 4565|       |                                       }
 4566|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4567|       |                                          v = std::make_unique<typename V::element_type>();
 4568|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4569|       |                                          v = std::make_shared<typename V::element_type>();
 4570|       |                                       else if constexpr (constructible<V>) {
 4571|       |                                          v = meta_construct_v<V>();
 4572|       |                                       }
 4573|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4574|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4575|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4576|       |                                             return;
 4577|       |                                          }
 4578|       |                                       }
 4579|       |                                       else {
 4580|       |                                          ctx.error = error_code::invalid_nullable_read;
 4581|       |                                          return;
 4582|       |                                          // Cannot read into unset nullable that is not std::optional,
 4583|       |                                          // std::unique_ptr, or std::shared_ptr
 4584|       |                                       }
 4585|       |                                    }
 4586|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4587|       |                                       *v, ctx, it, end);
 4588|       |                                 }
 4589|       |                                 else if constexpr (custom_read<V>) {
 4590|       |                                    // Custom handlers parse the remaining body themselves.
 4591|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4592|       |                                 }
 4593|       |                              },
 4594|       |                              value);
 4595|       |
 4596|       |                           return; // we've decoded our target type
 4597|       |                        }
 4598|       |                     }
 4599|       |                     // For tagged variants, continue processing to validate tags
 4600|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 4601|       |                        return;
 4602|       |                     }
 4603|       |
 4604|       |                     skip_value<JSON>::op<Opts>(ctx, it, end);
 4605|       |                     if (bool(ctx.error)) [[unlikely]]
 4606|       |                        return;
 4607|       |                     resync_window_end(ctx, end); // a streaming skip refills
 4608|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4609|       |                        return;
 4610|       |                     }
 4611|       |                  }
 4612|       |                  // Only apply ambiguous variant resolution if we have multiple object types
 4613|       |                  if constexpr ((type_counts::n_object + type_counts::n_nullable_object) > 1) {
 4614|       |                     // After parsing all keys, check if we have multiple matching types
 4615|       |                     // If so, choose the one with the fewest fields
 4616|       |                     auto final_matching = possible_types.popcount();
 4617|       |                     if (final_matching == 0) {
 4618|       |                        ctx.error = error_code::no_matching_variant_type;
 4619|       |                     }
 4620|       |                     else if (final_matching == 1) {
 4621|       |                        // Single type remains after field deduction
 4622|       |                        const auto type_index = possible_types.countr_zero();
 4623|       |
 4624|       |                        // Validate against tag if one was specified
 4625|       |                        if (tag_specified_index.has_value() &&
 4626|       |                            tag_specified_index.value() != static_cast<size_t>(type_index)) {
 4627|       |                           ctx.error = error_code::no_matching_variant_type;
 4628|       |                           return;
 4629|       |                        }
 4630|       |
 4631|       |                        if (!start.rewind(ctx, it, end)) return;
 4632|       |                        if (value.index() != static_cast<size_t>(type_index))
 4633|       |                           emplace_runtime_variant(value, type_index);
 4634|       |                        std::visit(
 4635|       |                           [&](auto&& v) {
 4636|       |                              using V = std::decay_t<decltype(v)>;
 4637|       |                              constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4638|       |                              if constexpr (variant_unit_alternative<V>) {
 4639|       |                                 // A unit alternative carries no data; its object holds only the discriminator.
 4640|       |                                 // Consume that body through an empty reflected object so unknown-key policy and
 4641|       |                                 // terminator handling match every other alternative.
 4642|       |                                 detail::variant_unit_body unit_body{};
 4643|       |                                 from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4644|       |                                                                                    tag_literal>(unit_body, ctx, it,
 4645|       |                                                                                                 end);
 4646|       |                              }
 4647|       |                              else if constexpr (is_object) {
 4648|       |                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4649|       |                              }
 4650|       |                              else if constexpr (is_memory_object<V>) {
 4651|       |                                 if (!v) {
 4652|       |                                    if constexpr (is_specialization_v<V, std::optional>) {
 4653|       |                                       if constexpr (requires { v.emplace(); }) {
 4654|       |                                          v.emplace();
 4655|       |                                       }
 4656|       |                                       else {
 4657|       |                                          v = typename V::value_type{};
 4658|       |                                       }
 4659|       |                                    }
 4660|       |                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4661|       |                                       v = std::make_unique<typename V::element_type>();
 4662|       |                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4663|       |                                       v = std::make_shared<typename V::element_type>();
 4664|       |                                    else if constexpr (constructible<V>) {
 4665|       |                                       v = meta_construct_v<V>();
 4666|       |                                    }
 4667|       |                                    else if constexpr (std::is_pointer_v<V> &&
 4668|       |                                                       can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4669|       |                                       if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4670|       |                                          return;
 4671|       |                                       }
 4672|       |                                    }
 4673|       |                                    else {
 4674|       |                                       ctx.error = error_code::invalid_nullable_read;
 4675|       |                                       return;
 4676|       |                                    }
 4677|       |                                 }
 4678|       |                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
 4679|       |                                                                                                               it, end);
 4680|       |                              }
 4681|       |                              else if constexpr (custom_read<V>) {
 4682|       |                                 // Custom handlers parse the remaining body themselves.
 4683|       |                                 from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4684|       |                              }
 4685|       |                           },
 4686|       |                           value);
 4687|       |                     }
 4688|       |                     else if (final_matching > 1) {
 4689|       |                        constexpr auto N = std::variant_size_v<T>;
 4690|       |
 4691|       |                        // Compile-time array of field counts for each variant type
 4692|       |                        constexpr auto field_counts = []<size_t... I>(std::index_sequence<I...>) {
 4693|       |                           return std::array<size_t, N> {
 4694|       |                              ([]<size_t J = I>() -> size_t {
 4695|       |                                 using V = std::decay_t<std::variant_alternative_t<J, T>>;
 4696|       |                                 if constexpr (glaze_object_t<V> || reflectable<V>) {
 4697|       |                                    return reflect<V>::size;
 4698|       |                                 }
 4699|       |                                 else if constexpr (is_memory_object<V>) {
 4700|       |                                    using X = memory_type<V>;
 4701|       |                                    if constexpr (glaze_object_t<X> || reflectable<X>) {
 4702|       |                                       return reflect<X>::size;
 4703|       |                                    }
 4704|       |                                    else {
 4705|       |                                       return (std::numeric_limits<size_t>::max)();
 4706|       |                                    }
 4707|       |                                 }
 4708|       |                                 else {
 4709|       |                                    return (std::numeric_limits<size_t>::max)();
 4710|       |                                 }
 4711|       |                              }.template operator()<I>())...
 4712|       |                           };
 4713|       |                        }(std::make_index_sequence<N>{});
 4714|       |
 4715|       |                        // Find the type with minimum field count among the possible types
 4716|       |                        size_t min_fields = (std::numeric_limits<size_t>::max)();
 4717|       |                        size_t chosen_index = N; // Invalid index initially
 4718|       |
 4719|       |                        for (size_t i = 0; i < N; ++i) {
 4720|       |                           if (possible_types[i] && field_counts[i] < min_fields) {
 4721|       |                              min_fields = field_counts[i];
 4722|       |                              chosen_index = i;
 4723|       |                           }
 4724|       |                        }
 4725|       |
 4726|       |                        if (chosen_index < N) {
 4727|       |                           // Validate against tag if one was specified
 4728|       |                           if (tag_specified_index.has_value() && tag_specified_index.value() != chosen_index) {
 4729|       |                              ctx.error = error_code::no_matching_variant_type;
 4730|       |                              return;
 4731|       |                           }
 4732|       |
 4733|       |                           if (!start.rewind(ctx, it, end)) return;
 4734|       |                           if (value.index() != chosen_index) emplace_runtime_variant(value, chosen_index);
 4735|       |                           std::visit(
 4736|       |                              [&](auto&& v) {
 4737|       |                                 using V = std::decay_t<decltype(v)>;
 4738|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4739|       |                                 if constexpr (variant_unit_alternative<V>) {
 4740|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4741|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4742|       |                                    // terminator handling match every other alternative.
 4743|       |                                    detail::variant_unit_body unit_body{};
 4744|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4745|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4746|       |                                                                                                    end);
 4747|       |                                 }
 4748|       |                                 else if constexpr (is_object) {
 4749|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4750|       |                                 }
 4751|       |                                 else if constexpr (is_memory_object<V>) {
 4752|       |                                    if (!v) {
 4753|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4754|       |                                          if constexpr (requires { v.emplace(); }) {
 4755|       |                                             v.emplace();
 4756|       |                                          }
 4757|       |                                          else {
 4758|       |                                             v = typename V::value_type{};
 4759|       |                                          }
 4760|       |                                       }
 4761|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4762|       |                                          v = std::make_unique<typename V::element_type>();
 4763|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4764|       |                                          v = std::make_shared<typename V::element_type>();
 4765|       |                                       else if constexpr (constructible<V>) {
 4766|       |                                          v = meta_construct_v<V>();
 4767|       |                                       }
 4768|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4769|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4770|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4771|       |                                             return;
 4772|       |                                          }
 4773|       |                                       }
 4774|       |                                       else {
 4775|       |                                          ctx.error = error_code::invalid_nullable_read;
 4776|       |                                          return;
 4777|       |                                       }
 4778|       |                                    }
 4779|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4780|       |                                       *v, ctx, it, end);
 4781|       |                                 }
 4782|       |                                 else if constexpr (custom_read<V>) {
 4783|       |                                    // Custom handlers parse the remaining body themselves.
 4784|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4785|       |                                 }
 4786|       |                              },
 4787|       |                              value);
 4788|       |                        }
 4789|       |                        else {
 4790|       |                           ctx.error = error_code::no_matching_variant_type;
 4791|       |                        }
 4792|       |                     }
 4793|       |                  }
 4794|       |                  else {
 4795|       |                     // For variants with 0 or 1 object types, use the original error handling
 4796|       |                     ctx.error = error_code::no_matching_variant_type;
 4797|       |                  }
 4798|       |               }
 4799|      0|               break;
 4800|  5.14k|            }
 4801|  2.19k|            case '[':
  ------------------
  |  Branch (4801:13): [True: 2.19k, False: 9.12k]
  ------------------
 4802|       |               // As with '{' above: the array reader each alternative goes through counts the level.
 4803|  2.19k|               process_variant_alternatives<T, is_variant_array>::template op<Opts>(value, ctx, it, end);
 4804|  2.19k|               break;
 4805|  1.15k|            case '"': {
  ------------------
  |  Branch (4805:13): [True: 1.15k, False: 10.1k]
  ------------------
 4806|  1.15k|               process_variant_alternatives<T, is_variant_str>::template op<Opts>(value, ctx, it, end);
 4807|  1.15k|               break;
 4808|  5.14k|            }
 4809|     78|            case 't':
  ------------------
  |  Branch (4809:13): [True: 78, False: 11.2k]
  ------------------
 4810|    184|            case 'f': {
  ------------------
  |  Branch (4810:13): [True: 106, False: 11.2k]
  ------------------
 4811|    184|               process_variant_alternatives<T, is_variant_bool>::template op<Opts>(value, ctx, it, end);
 4812|    184|               break;
 4813|     78|            }
 4814|     74|            case 'n':
  ------------------
  |  Branch (4814:13): [True: 74, False: 11.2k]
  ------------------
 4815|       |               if constexpr (variant_count_v<T, is_variant_null> == 0) {
 4816|       |                  ctx.error = error_code::no_matching_variant_type;
 4817|       |               }
 4818|     74|               else {
 4819|     74|                  constexpr auto first_idx = variant_first_index_v<T, is_variant_null>;
 4820|     74|                  using V = std::variant_alternative_t<first_idx, T>;
 4821|     74|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4821:23): [True: 0, False: 74]
  ------------------
 4822|     74|                  match<"null", Opts>(ctx, it, end);
 4823|     74|               }
 4824|     74|               break;
 4825|  2.55k|            default: {
  ------------------
  |  Branch (4825:13): [True: 2.55k, False: 8.76k]
  ------------------
 4826|       |               // Not bool, string, object, or array so must be number or null
 4827|  2.55k|               process_variant_alternatives<T, is_variant_num>::template op<Opts>(value, ctx, it, end);
 4828|  2.55k|            }
 4829|  11.3k|            }
 4830|       |         }
 4831|       |         else {
 4832|       |            // For non-auto-deducible variants, try each type until one succeeds
 4833|       |            constexpr auto N = std::variant_size_v<T>;
 4834|       |            bool parsed = false;
 4835|       |            bool exhausted = false; // speculation budget spent; see charge_speculation
 4836|       |
 4837|       |            for_each<N>([&]<size_t I>() {
 4838|       |               if (parsed || exhausted || variant_alternative_exhausted(ctx)) return;
 4839|       |
 4840|       |               auto copy_it = it;
 4841|       |               // A rejected alternative may have bailed out inside a container, which leaves its
 4842|       |               // nesting level counted (see enter_depth), so the depth rewinds with the iterator.
 4843|       |               const auto copy_depth = ctx.depth;
 4844|       |
 4845|       |               // Try parsing as this type
 4846|       |               if (value.index() != I) {
 4847|       |                  emplace_runtime_variant(value, I);
 4848|       |               }
 4849|       |
 4850|       |               std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
 4851|       |               if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 4852|       |                  exhausted = true; // only rejected attempts are charged; see charge_speculation
 4853|       |               }
 4854|       |
 4855|       |               if (!bool(ctx.error)) {
 4856|       |                  parsed = true;
 4857|       |               }
 4858|       |               else if constexpr (not Options.null_terminated) {
 4859|       |                  // In non-null-terminated mode, if we hit end_reached after advancing the iterator,
 4860|       |                  // it means we successfully parsed the value but couldn't skip trailing whitespace
 4861|       |                  if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 4862|       |                     // We advanced the iterator, so we did parse something -- unless what advanced it
 4863|       |                     // was an abandoned attempt, which is what a spent speculation budget means.
 4864|       |                     parsed = true;
 4865|       |                     ctx.error = error_code::none;
 4866|       |                  }
 4867|       |                  else {
 4868|       |                     // Reset for next attempt (unless this is the last type)
 4869|       |                     it = copy_it;
 4870|       |                     rewind_depth<Options>(ctx, copy_depth);
 4871|       |                     if constexpr (I + 1 < N) {
 4872|       |                        if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4873|       |                           ctx.error = error_code::none; // Clear error for next attempt
 4874|       |                        }
 4875|       |                     }
 4876|       |                  }
 4877|       |               }
 4878|       |               else {
 4879|       |                  // Reset for next attempt (unless this is the last type)
 4880|       |                  it = copy_it;
 4881|       |                  rewind_depth<Options>(ctx, copy_depth);
 4882|       |                  if constexpr (I + 1 < N) {
 4883|       |                     if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4884|       |                        ctx.error = error_code::none; // Clear error for next attempt
 4885|       |                     }
 4886|       |                  }
 4887|       |               }
 4888|       |            });
 4889|       |         }
 4890|  11.3k|      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj33EEERNS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES4_EEEETkNS_10is_contextERNS_7contextERPKcSD_EEvOT0_OT1_OT2_T3_:
   49|  27.5k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  27.5k|         else {
   60|  27.5k|            using V = std::remove_cvref_t<T>;
   61|  27.5k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  27.5k|                                             end);
   63|  27.5k|         }
   64|  27.5k|      }
_ZN3glz4fromILj10ENS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES1_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj33EEETnNS_14string_literalEXtlNS9_ILm1EEEEERS5_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT1_OT2_OT3_T4_:
 3044|  27.5k|      {
 3045|  27.5k|         static constexpr auto num_members = reflect<T>::size;
 3046|       |
 3047|  27.5k|         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
 3048|       |         if constexpr (!check_opening_handled(Options)) {
 3049|       |            if constexpr (!check_ws_handled(Options)) {
 3050|       |               if (skip_ws<Opts>(ctx, it, end)) {
 3051|       |                  return;
 3052|       |               }
 3053|       |            }
 3054|       |            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
 3055|       |               return;
 3056|       |            }
 3057|       |            if constexpr (not Opts.null_terminated) {
 3058|       |               if (it == end) [[unlikely]] {
 3059|       |                  ctx.error = error_code::unexpected_end;
 3060|       |                  return;
 3061|       |               }
 3062|       |            }
 3063|       |            // one nesting level (see enter_depth): counted in both modes so the limit binds,
 3064|       |            // released at each syntactic close below
 3065|       |            if (enter_depth(ctx)) [[unlikely]] {
 3066|       |               return;
 3067|       |            }
 3068|       |         }
 3069|  27.5k|         const auto ws_start = it;
 3070|  27.5k|         if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3070:14): [True: 0, False: 27.5k]
  ------------------
 3071|      0|            return;
 3072|      0|         }
 3073|  27.5k|         const size_t ws_size = size_t(it - ws_start);
 3074|       |
 3075|       |         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
 3076|       |            if constexpr (not tag.sv().empty()) {
 3077|       |               if (*it == '"') {
 3078|       |                  ++it;
 3079|       |                  if constexpr (not Opts.null_terminated) {
 3080|       |                     if (it == end) [[unlikely]] {
 3081|       |                        ctx.error = error_code::unexpected_end;
 3082|       |                        return;
 3083|       |                     }
 3084|       |                  }
 3085|       |
 3086|       |                  const auto start = it;
 3087|       |                  skip_string_view(ctx, it, end);
 3088|       |                  if (bool(ctx.error)) [[unlikely]]
 3089|       |                     return;
 3090|       |                  if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]]
 3091|       |                     return;
 3092|       |                  const sv key{start, size_t(it - start)};
 3093|       |                  ++it;
 3094|       |                  if constexpr (not Opts.null_terminated) {
 3095|       |                     if (it == end) [[unlikely]] {
 3096|       |                        ctx.error = error_code::unexpected_end;
 3097|       |                        return;
 3098|       |                     }
 3099|       |                  }
 3100|       |
 3101|       |                  if (key == tag.sv()) {
 3102|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3103|       |                        return;
 3104|       |                     }
 3105|       |
 3106|       |                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
 3107|       |                     if (bool(ctx.error)) [[unlikely]]
 3108|       |                        return;
 3109|       |
 3110|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 3111|       |                        return;
 3112|       |                     }
 3113|       |                  }
 3114|       |                  else {
 3115|       |                     ctx.error = error_code::unknown_key;
 3116|       |                     return;
 3117|       |                  }
 3118|       |               }
 3119|       |            }
 3120|       |
 3121|       |            if (*it == '}') [[likely]] {
 3122|       |               --ctx.depth;
 3123|       |               if constexpr (glaze_object_t<T> || reflectable<T>) {
 3124|       |                  if constexpr (has_self_constraint_v<T> && !check_skip_self_constraint(Opts)) {
 3125|       |                     auto wrapper = self_constraint_v<T>(value);
 3126|       |                     from<JSON, decltype(wrapper)>::template op<ws_handled<Opts>()>(wrapper, ctx, it, end);
 3127|       |                     if (bool(ctx.error)) {
 3128|       |                        return;
 3129|       |                     }
 3130|       |                  }
 3131|       |               }
 3132|       |               ++it;
 3133|       |               if constexpr (not Opts.null_terminated) {
 3134|       |                  if (it == end) {
 3135|       |                     ctx.error = error_code::end_reached;
 3136|       |                     return;
 3137|       |                  }
 3138|       |               }
 3139|       |               if constexpr (Opts.partial_read) {
 3140|       |                  ctx.error = error_code::partial_read_complete;
 3141|       |               }
 3142|       |               return;
 3143|       |            }
 3144|       |            ctx.error = error_code::unknown_key;
 3145|       |            return;
 3146|       |         }
 3147|  27.5k|         else {
 3148|  27.5k|            decltype(auto) fields = [&]() -> decltype(auto) {
 3149|  27.5k|               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
 3150|  27.5k|                             (Opts.error_on_missing_keys || Opts.partial_read)) {
 3151|  27.5k|                  return bit_array<num_members>{};
 3152|  27.5k|               }
 3153|  27.5k|               else {
 3154|  27.5k|                  return nullptr;
 3155|  27.5k|               }
 3156|  27.5k|            }();
 3157|       |
 3158|  27.5k|            size_t read_count{}; // for partial_read
 3159|       |
 3160|  27.5k|            bool first = true;
 3161|  1.14M|            while (true) {
  ------------------
  |  Branch (3161:20): [True: 1.11M, Folded]
  ------------------
 3162|       |               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
 3163|       |                  static constexpr bit_array<num_members> all_fields = [] {
 3164|       |                     bit_array<num_members> arr{};
 3165|       |                     for (size_t i = 0; i < num_members; ++i) {
 3166|       |                        arr[i] = true;
 3167|       |                     }
 3168|       |                     return arr;
 3169|       |                  }();
 3170|       |
 3171|       |                  if ((all_fields & fields) == all_fields) {
 3172|       |                     ctx.error = error_code::partial_read_complete;
 3173|       |                     --ctx.depth; // as above: an early success still closes this level
 3174|       |                     return;
 3175|       |                  }
 3176|       |               }
 3177|       |
 3178|       |               // Streaming refill point: at start of each iteration, ensure buffer has data
 3179|       |               if constexpr (has_streaming_state<decltype(ctx)>) {
 3180|       |                  if (ctx.stream.enabled()) {
 3181|       |                     const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 3182|       |                     const size_t remaining = ctx.stream.size() - consumed;
 3183|       |                     // Refill when less than half of buffer remains to ensure space for next key-value pair
 3184|       |                     if (remaining <= ctx.stream.size() / 2 || it >= end) {
 3185|       |                        const char* new_it;
 3186|       |                        const char* new_end;
 3187|       |                        ctx.stream.consume_and_refill(consumed, new_it, new_end);
 3188|       |                        it = new_it;
 3189|       |                        end = new_end;
 3190|       |                        if (it >= end && ctx.stream.at_eof()) {
 3191|       |                           ctx.error = error_code::unexpected_end;
 3192|       |                           return;
 3193|       |                        }
 3194|       |                     }
 3195|       |                  }
 3196|       |               }
 3197|       |
 3198|  1.11M|               if (*it == '}') {
  ------------------
  |  Branch (3198:20): [True: 2.05k, False: 1.11M]
  ------------------
 3199|  2.05k|                  --ctx.depth;
 3200|       |                  if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
 3201|       |                     constexpr auto req_fields = required_fields<T, Opts>();
 3202|       |                     if ((req_fields & fields) != req_fields) {
 3203|       |                        for (size_t i = 0; i < num_members; ++i) {
 3204|       |                           if (not fields[i] && req_fields[i]) {
 3205|       |                              ctx.custom_error_message = reflect<T>::keys[i];
 3206|       |                              // We just return the first missing key in order to avoid heap allocations
 3207|       |                              break;
 3208|       |                           }
 3209|       |                        }
 3210|       |
 3211|       |                        ctx.error = error_code::missing_key;
 3212|       |                        return;
 3213|       |                     }
 3214|       |                  }
 3215|       |                  if constexpr (glaze_object_t<T> || reflectable<T>) {
 3216|       |                     if constexpr (has_self_constraint_v<T> && !check_skip_self_constraint(Opts)) {
 3217|       |                        auto wrapper = self_constraint_v<T>(value);
 3218|       |                        from<JSON, decltype(wrapper)>::template op<ws_handled<Opts>()>(wrapper, ctx, it, end);
 3219|       |                        if (bool(ctx.error)) {
 3220|       |                           return;
 3221|       |                        }
 3222|       |                     }
 3223|       |                  }
 3224|  2.05k|                  ++it; // Increment after checking for missing keys so errors are within buffer bounds
 3225|       |                  if constexpr (not Opts.null_terminated) {
 3226|       |                     if (it == end) {
 3227|       |                        ctx.error = error_code::end_reached;
 3228|       |                        return;
 3229|       |                     }
 3230|       |                  }
 3231|  2.05k|                  return;
 3232|  2.05k|               }
 3233|  1.11M|               else if (first) {
  ------------------
  |  Branch (3233:25): [True: 25.8k, False: 1.08M]
  ------------------
 3234|  25.8k|                  first = false;
 3235|  25.8k|               }
 3236|  1.08M|               else {
 3237|  1.08M|                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3237:23): [True: 514, False: 1.08M]
  ------------------
 3238|    514|                     return;
 3239|    514|                  }
 3240|       |                  if constexpr (not Opts.null_terminated) {
 3241|       |                     if (it == end) [[unlikely]] {
 3242|       |                        ctx.error = error_code::unexpected_end;
 3243|       |                        return;
 3244|       |                     }
 3245|       |                  }
 3246|       |
 3247|       |                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys) &&
 3248|       |                                (!Opts.comments)) {
 3249|       |                     if (ws_size && ws_size < size_t(end - it)) {
 3250|       |                        skip_matching_ws(ws_start, it, ws_size);
 3251|       |                     }
 3252|       |                  }
 3253|       |
 3254|  1.08M|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3254:23): [True: 0, False: 1.08M]
  ------------------
 3255|      0|                     return;
 3256|      0|                  }
 3257|  1.08M|               }
 3258|       |
 3259|  1.11M|               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
  ------------------
  |  Branch (3259:49): [Folded, False: 0]
  |  Branch (3259:70): [Folded, False: 0]
  ------------------
 3260|       |
 3261|       |               if constexpr (reflection_type && (num_members == 0)) {
 3262|       |                  if constexpr (Opts.error_on_unknown_keys) {
 3263|       |                     static_assert(false_v<T>, "This should be unreachable");
 3264|       |                  }
 3265|       |                  else {
 3266|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 3267|       |                        return;
 3268|       |                     }
 3269|       |
 3270|       |                     // parsing to an empty object, but at this point the JSON presents keys
 3271|       |
 3272|       |                     // Unknown key handler does not unescape keys. Unknown escaped keys are
 3273|       |                     // handled by the user.
 3274|       |
 3275|       |                     const auto start = it;
 3276|       |                     skip_string_view(ctx, it, end);
 3277|       |                     if (bool(ctx.error)) [[unlikely]]
 3278|       |                        return;
 3279|       |                     if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]]
 3280|       |                        return;
 3281|       |                     const sv key{start, size_t(it - start)};
 3282|       |                     ++it;
 3283|       |                     if constexpr (not Opts.null_terminated) {
 3284|       |                        if (it == end) [[unlikely]] {
 3285|       |                           ctx.error = error_code::unexpected_end;
 3286|       |                           return;
 3287|       |                        }
 3288|       |                     }
 3289|       |
 3290|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3291|       |                        return;
 3292|       |                     }
 3293|       |
 3294|       |                     // Check if this key is the variant tag that should be skipped
 3295|       |                     if constexpr (not tag.sv().empty()) {
 3296|       |                        if (key == tag.sv()) {
 3297|       |                           // Skip the tag value
 3298|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 3299|       |                           if (bool(ctx.error)) [[unlikely]]
 3300|       |                              return;
 3301|       |                           resync_window_end(ctx, end); // a streaming skip refills
 3302|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 3303|       |                              return;
 3304|       |                           }
 3305|       |                           continue;
 3306|       |                        }
 3307|       |                     }
 3308|       |
 3309|       |                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
 3310|       |                     if (bool(ctx.error)) [[unlikely]]
 3311|       |                        return;
 3312|       |                     if constexpr (not Opts.null_terminated) {
 3313|       |                        if (it == end) [[unlikely]] {
 3314|       |                           ctx.error = error_code::unexpected_end;
 3315|       |                           return;
 3316|       |                        }
 3317|       |                     }
 3318|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 3319|       |                        return;
 3320|       |                     }
 3321|       |                  }
 3322|       |               }
 3323|       |               else if constexpr (reflection_type) {
 3324|       |                  static_assert(bool(hash_info<T>.type));
 3325|       |
 3326|       |                  if (*it != '"') [[unlikely]] {
 3327|       |                     ctx.error = error_code::expected_quote;
 3328|       |                     return;
 3329|       |                  }
 3330|       |                  ++it;
 3331|       |                  if constexpr (not Opts.null_terminated) {
 3332|       |                     if (it == end) [[unlikely]] {
 3333|       |                        ctx.error = error_code::unexpected_end;
 3334|       |                        return;
 3335|       |                     }
 3336|       |                  }
 3337|       |
 3338|       |                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
 3339|       |                     // For tagged variants we first check to see if the key matches the tag
 3340|       |                     // We only need to do this if the tag is not part of the keys
 3341|       |
 3342|       |                     const auto start = it;
 3343|       |                     skip_string_view(ctx, it, end);
 3344|       |                     if (bool(ctx.error)) [[unlikely]]
 3345|       |                        return;
 3346|       |                     if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]]
 3347|       |                        return;
 3348|       |                     const sv key{start, size_t(it - start)};
 3349|       |                     ++it;
 3350|       |                     if constexpr (not Opts.null_terminated) {
 3351|       |                        if (it == end) [[unlikely]] {
 3352|       |                           ctx.error = error_code::unexpected_end;
 3353|       |                           return;
 3354|       |                        }
 3355|       |                     }
 3356|       |
 3357|       |                     if (key == tag.sv()) {
 3358|       |                        if (parse_ws_colon<Opts>(ctx, it, end)) {
 3359|       |                           return;
 3360|       |                        }
 3361|       |
 3362|       |                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
 3363|       |                        if (bool(ctx.error)) [[unlikely]]
 3364|       |                           return;
 3365|       |
 3366|       |                        if (skip_ws<Opts>(ctx, it, end)) {
 3367|       |                           return;
 3368|       |                        }
 3369|       |                        continue;
 3370|       |                     }
 3371|       |                     else {
 3372|       |                        it = start; // reset the iterator
 3373|       |                     }
 3374|       |                  }
 3375|       |
 3376|       |                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
 3377|       |                     size_t index = num_members;
 3378|       |                     parse_and_invoke<Opts, T>(value, ctx, it, end, index);
 3379|       |                     if (bool(ctx.error)) [[unlikely]]
 3380|       |                        return;
 3381|       |                     if (index < num_members) {
 3382|       |                        fields[index] = true;
 3383|       |                     }
 3384|       |                  }
 3385|       |                  else {
 3386|       |                     parse_and_invoke<Opts, T>(value, ctx, it, end);
 3387|       |                     if (bool(ctx.error)) [[unlikely]]
 3388|       |                        return;
 3389|       |                  }
 3390|       |               }
 3391|  1.11M|               else {
 3392|       |                  // For types like std::map, std::unordered_map
 3393|       |
 3394|  1.11M|                  auto reading = [&](auto&& key) {
 3395|  1.11M|                     if constexpr (Opts.partial_read) {
 3396|  1.11M|                        if (auto element = value.find(key); element != value.end()) {
 3397|  1.11M|                           ++read_count;
 3398|  1.11M|                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
 3399|  1.11M|                        }
 3400|  1.11M|                        else {
 3401|  1.11M|                           skip_value<JSON>::op<Opts>(ctx, it, end);
 3402|  1.11M|                        }
 3403|  1.11M|                     }
 3404|  1.11M|                     else {
 3405|  1.11M|                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
 3406|  1.11M|                     }
 3407|  1.11M|                  };
 3408|       |
 3409|       |                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
 3410|  1.11M|                  using Key = typename T::key_type;
 3411|  1.11M|                  if constexpr (std::is_same_v<Key, std::string>) {
 3412|  1.11M|                     ctx.scratch.clear();
 3413|  1.11M|                     parse<JSON>::op<Opts>(ctx.scratch, ctx, it, end);
 3414|  1.11M|                     if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (3414:26): [True: 1.38k, False: 1.11M]
  ------------------
 3415|  1.38k|                        return;
 3416|       |
 3417|  1.11M|                     if (parse_ws_colon<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3417:26): [True: 739, False: 1.11M]
  ------------------
 3418|    739|                        return;
 3419|    739|                     }
 3420|       |
 3421|  1.11M|                     reading(ctx.scratch);
 3422|       |                     if constexpr (Opts.partial_read) {
 3423|       |                        if (read_count == value.size()) {
 3424|       |                           return;
 3425|       |                        }
 3426|       |                     }
 3427|  1.11M|                     if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (3427:26): [True: 22.8k, False: 1.09M]
  ------------------
 3428|  22.8k|                        return;
 3429|       |                  }
 3430|       |                  else if constexpr (str_t<Key>) {
 3431|       |                     Key key;
 3432|       |                     parse<JSON>::op<Opts>(key, ctx, it, end);
 3433|       |                     if (bool(ctx.error)) [[unlikely]]
 3434|       |                        return;
 3435|       |
 3436|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3437|       |                        return;
 3438|       |                     }
 3439|       |
 3440|       |                     reading(key);
 3441|       |                     if constexpr (Opts.partial_read) {
 3442|       |                        if (read_count == value.size()) {
 3443|       |                           return;
 3444|       |                        }
 3445|       |                     }
 3446|       |                     if (bool(ctx.error)) [[unlikely]]
 3447|       |                        return;
 3448|       |                  }
 3449|       |                  else {
 3450|       |                     Key key_value{};
 3451|       |                     if constexpr (is_named_enum<Key> || mimics_str_t<Key>) {
 3452|       |                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
 3453|       |                     }
 3454|       |                     else if constexpr (std::is_arithmetic_v<Key>) {
 3455|       |                        // prefer over quoted_t below to avoid double parsing of quoted_t
 3456|       |                        parse<JSON>::op<opt_true<Opts, quoted_num_opt_tag{}>>(key_value, ctx, it, end);
 3457|       |                     }
 3458|       |                     else {
 3459|       |                        parse<JSON>::op<opt_false<Opts, raw_string_opt_tag{}>>(quoted_t<Key>{key_value}, ctx, it, end);
 3460|       |                     }
 3461|       |                     if (bool(ctx.error)) [[unlikely]]
 3462|       |                        return;
 3463|       |
 3464|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 3465|       |                        return;
 3466|       |                     }
 3467|       |
 3468|       |                     reading(key_value);
 3469|       |                     if constexpr (Opts.partial_read) {
 3470|       |                        if (read_count == value.size()) {
 3471|       |                           return;
 3472|       |                        }
 3473|       |                     }
 3474|       |                     if (bool(ctx.error)) [[unlikely]]
 3475|       |                        return;
 3476|       |                  }
 3477|  1.11M|               }
 3478|       |
 3479|       |               // Streaming refill point: after parsing each key-value pair, refill if buffer is low
 3480|       |               if constexpr (has_streaming_state<decltype(ctx)>) {
 3481|       |                  if (ctx.stream.enabled()) {
 3482|       |                     const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 3483|       |                     // Refill when less than 25% of buffer remains to ensure enough space for next element
 3484|       |                     if (ctx.stream.size() - consumed <= ctx.stream.size() / 4 || it >= end) {
 3485|       |                        const char* new_it;
 3486|       |                        const char* new_end;
 3487|       |                        ctx.stream.consume_and_refill(consumed, new_it, new_end);
 3488|       |                        it = new_it;
 3489|       |                        end = new_end;
 3490|       |                        if (it >= end && ctx.stream.at_eof()) {
 3491|       |                           ctx.error = error_code::unexpected_end;
 3492|       |                           return;
 3493|       |                        }
 3494|       |                     }
 3495|       |                  }
 3496|       |               }
 3497|       |
 3498|  1.11M|               if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (3498:20): [True: 0, False: 1.11M]
  ------------------
 3499|      0|                  return;
 3500|      0|               }
 3501|  1.11M|            }
 3502|  27.5k|         }
 3503|  27.5k|      }
_ZZN3glz4fromILj10ENS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES1_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj33EEETnNS_14string_literalEXtlNS9_ILm1EEEEERS5_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT1_OT2_OT3_T4_ENKUlvE_clEv:
 3148|  27.5k|            decltype(auto) fields = [&]() -> decltype(auto) {
 3149|       |               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
 3150|       |                             (Opts.error_on_missing_keys || Opts.partial_read)) {
 3151|       |                  return bit_array<num_members>{};
 3152|       |               }
 3153|  27.5k|               else {
 3154|  27.5k|                  return nullptr;
 3155|  27.5k|               }
 3156|  27.5k|            }();
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_T3_:
   49|  1.11M|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  1.11M|         else {
   60|  1.11M|            using V = std::remove_cvref_t<T>;
   61|  1.11M|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  1.11M|                                             end);
   63|  1.11M|         }
   64|  1.11M|      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERPKcSC_S7_TkNS_10is_contextERNS_7contextEQcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_T1_:
  892|  1.11M|      {
  893|       |         if constexpr (check_string_as_number(Opts)) {
  894|       |            auto start = it;
  895|       |            skip_number<Opts>(ctx, it, end);
  896|       |            if (bool(ctx.error)) [[unlikely]] {
  897|       |               return;
  898|       |            }
  899|       |            value.append(start, size_t(it - start));
  900|       |         }
  901|  1.11M|         else {
  902|  1.11M|            if constexpr (!check_opening_handled(Opts)) {
  903|  1.11M|               if constexpr (!check_ws_handled(Opts)) {
  904|  1.11M|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (904:23): [True: 0, False: 1.11M]
  ------------------
  905|      0|                     return;
  906|      0|                  }
  907|  1.11M|               }
  908|       |
  909|  1.11M|               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (909:20): [True: 363, False: 1.11M]
  ------------------
  910|    363|                  return;
  911|    363|               }
  912|  1.11M|            }
  913|       |
  914|  1.11M|            if constexpr (not check_raw_string(Opts)) {
  915|  1.11M|               static constexpr auto string_padding_bytes = 8;
  916|       |
  917|  1.11M|               auto start = it;
  918|  1.11M|               uint64_t ascii_acc{};
  919|  4.13M|               while (true) {
  ------------------
  |  Branch (919:23): [True: 4.13M, Folded]
  ------------------
  920|  4.13M|                  if (it >= end) [[unlikely]] {
  ------------------
  |  Branch (920:23): [True: 525, False: 4.12M]
  ------------------
  921|    525|                     ctx.error = error_code::unexpected_end;
  922|    525|                     return;
  923|    525|                  }
  924|       |
  925|  4.12M|                  uint64_t chunk;
  926|  4.12M|                  std::memcpy(&chunk, it, 8);
  927|       |                  if constexpr (std::endian::native == std::endian::big) {
  928|       |                     chunk = std::byteswap(chunk);
  929|       |                  }
  930|  4.12M|                  ascii_acc |= chunk;
  931|  4.12M|                  const uint64_t test_chars = has_quote(chunk);
  932|  4.12M|                  if (test_chars) {
  ------------------
  |  Branch (932:23): [True: 1.11M, False: 3.01M]
  ------------------
  933|  1.11M|                     it += (countr_zero(test_chars) >> 3);
  934|       |
  935|  1.11M|                     auto* prev = it - 1;
  936|  1.11M|                     while (*prev == '\\') {
  ------------------
  |  Branch (936:29): [True: 2.91k, False: 1.11M]
  ------------------
  937|  2.91k|                        --prev;
  938|  2.91k|                     }
  939|  1.11M|                     if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (939:26): [True: 1.11M, False: 1.47k]
  ------------------
  940|  1.11M|                        break;
  941|  1.11M|                     }
  942|  1.47k|                     ++it; // skip the escaped quote
  943|  1.47k|                  }
  944|  3.01M|                  else {
  945|  3.01M|                     it += 8;
  946|  3.01M|                  }
  947|  4.12M|               }
  948|       |
  949|  1.11M|               if (validate_utf8_span<Opts>(ctx, start, it, ascii_acc)) [[unlikely]] {
  ------------------
  |  Branch (949:20): [True: 248, False: 1.11M]
  ------------------
  950|    248|                  return;
  951|    248|               }
  952|       |
  953|  1.11M|               auto n = size_t(it - start);
  954|  1.11M|               value.resize(n + string_padding_bytes);
  955|       |
  956|  1.11M|               auto* p = value.data();
  957|       |
  958|  4.76M|               while (true) {
  ------------------
  |  Branch (958:23): [True: 4.76M, Folded]
  ------------------
  959|  4.76M|                  if (start >= it) {
  ------------------
  |  Branch (959:23): [True: 1.10M, False: 3.65M]
  ------------------
  960|  1.10M|                     break;
  961|  1.10M|                  }
  962|       |
  963|  3.65M|                  std::memcpy(p, start, 8);
  964|  3.65M|                  uint64_t swar;
  965|  3.65M|                  std::memcpy(&swar, p, 8);
  966|       |                  if constexpr (std::endian::native == std::endian::big) {
  967|       |                     swar = std::byteswap(swar);
  968|       |                  }
  969|       |
  970|  3.65M|                  constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
  971|  3.65M|                  const uint64_t lo7 = swar & lo7_mask;
  972|  3.65M|                  const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
  973|  3.65M|                  const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
  974|  3.65M|                  uint64_t next = ~((backslash & less_32) | swar);
  975|       |
  976|  3.65M|                  next &= repeat_byte8(0b10000000);
  977|  3.65M|                  if (next == 0) {
  ------------------
  |  Branch (977:23): [True: 3.64M, False: 13.8k]
  ------------------
  978|  3.64M|                     start += 8;
  979|  3.64M|                     p += 8;
  980|  3.64M|                     continue;
  981|  3.64M|                  }
  982|       |
  983|  13.8k|                  next = countr_zero(next) >> 3;
  984|  13.8k|                  start += next;
  985|  13.8k|                  if (start >= it) {
  ------------------
  |  Branch (985:23): [True: 4.20k, False: 9.65k]
  ------------------
  986|  4.20k|                     break;
  987|  4.20k|                  }
  988|       |
  989|  9.65k|                  if ((*start & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (989:23): [True: 80, False: 9.57k]
  ------------------
  990|     80|                     ctx.error = error_code::syntax_error;
  991|     80|                     return;
  992|     80|                  }
  993|  9.57k|                  ++start; // skip the escape
  994|  9.57k|                  if (*start == 'u') {
  ------------------
  |  Branch (994:23): [True: 7.26k, False: 2.30k]
  ------------------
  995|  7.26k|                     ++start;
  996|  7.26k|                     p += next;
  997|  7.26k|                     const auto mark = start;
  998|  7.26k|                     const auto offset = handle_unicode_code_point(start, p, end);
  999|  7.26k|                     if (offset == 0) [[unlikely]] {
  ------------------
  |  Branch (999:26): [True: 142, False: 7.12k]
  ------------------
 1000|    142|                        ctx.error = error_code::unicode_escape_conversion_failure;
 1001|    142|                        return;
 1002|    142|                     }
 1003|  7.12k|                     n += offset;
 1004|       |                     // escape + u + unicode code points
 1005|  7.12k|                     n -= 2 + uint32_t(start - mark);
 1006|  7.12k|                  }
 1007|  2.30k|                  else {
 1008|  2.30k|                     p += next;
 1009|  2.30k|                     *p = char_unescape_table[uint8_t(*start)];
 1010|  2.30k|                     if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1010:26): [True: 25, False: 2.28k]
  ------------------
 1011|     25|                        ctx.error = error_code::invalid_escape;
 1012|     25|                        return;
 1013|     25|                     }
 1014|  2.28k|                     ++p;
 1015|  2.28k|                     ++start;
 1016|  2.28k|                     --n;
 1017|  2.28k|                  }
 1018|  9.57k|               }
 1019|       |
 1020|  1.11M|               value.resize(n);
 1021|  1.11M|               ++it;
 1022|       |            }
 1023|       |            else {
 1024|       |               // raw_string
 1025|       |               auto start = it;
 1026|       |               skip_string_view(ctx, it, end);
 1027|       |               if (bool(ctx.error)) [[unlikely]]
 1028|       |                  return;
 1029|       |
 1030|       |               if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]] {
 1031|       |                  return;
 1032|       |               }
 1033|       |
 1034|       |               value.assign(start, size_t(it - start));
 1035|       |               ++it;
 1036|       |            }
 1037|  1.11M|         }
 1038|  1.11M|      }
_ZN3glz14parse_ws_colonITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEETkNS_10is_contextENS_7contextERPKcS4_EEbRT0_OT1_T2_:
  159|  1.11M|   {
  160|  1.11M|      if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (160:11): [True: 0, False: 1.11M]
  ------------------
  161|      0|         return true;
  162|      0|      }
  163|  1.11M|      if (match_invalid_end<':', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (163:11): [True: 739, False: 1.11M]
  ------------------
  164|    739|         return true;
  165|    739|      }
  166|  1.11M|      if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (166:11): [True: 0, False: 1.11M]
  ------------------
  167|      0|         return true;
  168|      0|      }
  169|  1.11M|      return false;
  170|  1.11M|   }
_ZZN3glz4fromILj10ENS_17ordered_small_mapINS_12generic_jsonILNS_8num_modeE0ES1_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj33EEETnNS_14string_literalEXtlNS9_ILm1EEEEERS5_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT1_OT2_OT3_T4_ENKUlOT_E_clIRNSt3__112basic_stringIcNSS_11char_traitsIcEENSS_9allocatorIcEEEEEEDaSP_:
 3394|  1.11M|                  auto reading = [&](auto&& key) {
 3395|       |                     if constexpr (Opts.partial_read) {
 3396|       |                        if (auto element = value.find(key); element != value.end()) {
 3397|       |                           ++read_count;
 3398|       |                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
 3399|       |                        }
 3400|       |                        else {
 3401|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 3402|       |                        }
 3403|       |                     }
 3404|  1.11M|                     else {
 3405|  1.11M|                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
 3406|  1.11M|                     }
 3407|  1.11M|                  };
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERNS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEETkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
   49|  2.81M|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  2.81M|         else {
   60|  2.81M|            using V = std::remove_cvref_t<T>;
   61|  2.81M|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  2.81M|                                             end);
   63|  2.81M|         }
   64|  2.81M|      }
_ZN3glz4fromILj10ENS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERS4_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_T3_:
  150|  2.81M|      {
  151|  2.81M|         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
  152|  2.81M|         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
  153|  2.81M|                                          std::forward<Ctx>(ctx), std::forward<It0>(it), end);
  154|  2.81M|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4065|  2.81M|      {
 4066|       |         if constexpr (tagging == variant_tagging_kind::adjacent) {
 4067|       |            read_adjacent<Options>(value, ctx, it, end);
 4068|       |         }
 4069|  2.81M|         else {
 4070|  2.81M|            read_deduced<Options>(value, ctx, it, end);
 4071|  2.81M|         }
 4072|  2.81M|      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEEE12read_deducedITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERSH_TkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_T3_:
 4076|  2.81M|      {
 4077|  2.81M|         constexpr auto Opts = ws_handled_off<Options>();
 4078|  2.81M|         if constexpr (variant_is_auto_deducible<T>()) {
 4079|       |            if constexpr (not check_ws_handled(Options)) {
 4080|       |               if (skip_ws<Opts>(ctx, it, end)) {
 4081|       |                  return;
 4082|       |               }
 4083|       |            }
 4084|       |
 4085|  2.81M|            switch (*it) {
 4086|  1.74k|            case '\0':
  ------------------
  |  Branch (4086:13): [True: 1.74k, False: 2.81M]
  ------------------
 4087|  1.74k|               ctx.error = error_code::unexpected_end;
 4088|  1.74k|               return;
 4089|  22.4k|            case '{': {
  ------------------
  |  Branch (4089:13): [True: 22.4k, False: 2.79M]
  ------------------
 4090|       |               // This branch consumes the brace itself and hands the object to a reader with
 4091|       |               // `opening_handled`, which therefore does not count the level -- but does release it at
 4092|       |               // the closing brace. So the level is taken here, in both buffer modes, and paid back by
 4093|       |               // the reader below.
 4094|  22.4k|               if (enter_depth(ctx)) [[unlikely]] {
  ------------------
  |  Branch (4094:20): [True: 11, False: 22.3k]
  ------------------
 4095|     11|                  return;
 4096|     11|               }
 4097|       |
 4098|  22.3k|               ++it;
 4099|       |               if constexpr (not Opts.null_terminated) {
 4100|       |                  if (it == end) [[unlikely]] {
 4101|       |                     ctx.error = error_code::unexpected_end;
 4102|       |                     return;
 4103|       |                  }
 4104|       |               }
 4105|  22.3k|               using type_counts = variant_type_count<T>;
 4106|  22.3k|               constexpr auto n_object_candidates = variant_object_candidate_count_v<Opts, T>;
 4107|       |               if constexpr (n_object_candidates < 1) {
 4108|       |                  ctx.error = error_code::no_matching_variant_type;
 4109|       |                  return;
 4110|       |               }
 4111|  22.3k|               else if constexpr (n_object_candidates == 1 && tag_v<T>.empty()) {
 4112|  22.3k|                  constexpr auto first_idx = variant_first_object_candidate_v<Opts, T>;
 4113|  22.3k|                  using V = std::variant_alternative_t<first_idx, T>;
 4114|  22.3k|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4114:23): [True: 21.9k, False: 402]
  ------------------
 4115|  22.3k|                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
 4116|  22.3k|                  return;
 4117|       |               }
 4118|       |               else {
 4119|       |                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
 4120|       |                  static constexpr auto& deduction_bits = variant_deduction_bits<T>;
 4121|       |                  static constexpr size_t deduction_key_count = variant_deduction_key_count<T>;
 4122|       |                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
 4123|       |
 4124|       |                  // Track if we've encountered a tag and what value it had
 4125|       |                  std::optional<size_t> tag_specified_index{};
 4126|       |
 4127|       |                  if (skip_ws<Opts>(ctx, it, end)) {
 4128|       |                     return;
 4129|       |                  }
 4130|       |                  // Once the reader knows which alternative this object holds it may have to read
 4131|       |                  // it again from here. Anchor the position rather than keep the pointer: the scan
 4132|       |                  // below skips values, and a streaming skip refills, which moves the window out
 4133|       |                  // from under a raw pointer (see rewind_anchor).
 4134|       |                  auto start = make_rewind_anchor(ctx, it);
 4135|       |                  bool first_key = true;
 4136|       |                  // Parse bifurcation for tagged variants:
 4137|       |                  //
 4138|       |                  // Without this optimization, tagged variant parsing always uses two passes:
 4139|       |                  //   1. Scan all keys to find the tag (e.g. "type"), skipping values
 4140|       |                  //   2. Reset `it = start` and re-parse the entire object into the resolved type
 4141|       |                  //
 4142|       |                  // When the tag is the first key, the second pass redundantly re-reads every
 4143|       |                  // field that follows it. This lambda avoids that: if the tag was the first key,
 4144|       |                  // it advances past the trailing comma so the object parser picks up at the
 4145|       |                  // second field. If the tag was found later, it falls back to the full re-parse.
 4146|       |                  //
 4147|       |                  // One exception: if the tag name is also a field on the resolved struct
 4148|       |                  // (contains_tag), we must re-parse regardless so the value is stored in
 4149|       |                  // the struct field. This override is applied inside each std::visit lambda.
 4150|       |                  //
 4151|       |                  // Either way the rewind can fail under a streaming read: the window only holds so
 4152|       |                  // much, and an object wider than it has no start left to return to.
 4153|       |                  auto position_after_tag = [&] {
 4154|       |                     if (first_key) {
 4155|       |                        if (*it == ',') ++it; // skip comma; handles tag-only objects where *it == '}'
 4156|       |                        return true;
 4157|       |                     }
 4158|       |                     return start.rewind(ctx, it, end); // tag came later, re-parse from the beginning
 4159|       |                  };
 4160|       |                  // `first_key` also answers "were we reset to the object start", which is what
 4161|       |                  // position_after_tag does for every key but the first.
 4162|       |                  for (; *it != '}'; first_key = false) {
 4163|       |                     if (!first_key) {
 4164|       |                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
 4165|       |                           return;
 4166|       |                        }
 4167|       |                     }
 4168|       |
 4169|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4170|       |                        return;
 4171|       |                     }
 4172|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4173|       |                        return;
 4174|       |                     }
 4175|       |
 4176|       |                     auto* key_start = it;
 4177|       |                     skip_string_view(ctx, it, end);
 4178|       |                     if (bool(ctx.error)) [[unlikely]]
 4179|       |                        return;
 4180|       |                     if (validate_utf8_span<Opts>(ctx, key_start, it)) [[unlikely]]
 4181|       |                        return;
 4182|       |                     const sv key = {key_start, size_t(it - key_start)};
 4183|       |
 4184|       |                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
 4185|       |                        return;
 4186|       |                     }
 4187|       |
 4188|       |                     if constexpr (deduction_key_count > 0) {
 4189|       |                        // We first check if a tag is defined and see if the key matches the tag
 4190|       |                        if constexpr (not tag_v<T>.empty()) {
 4191|       |                           if (key == tag_v<T>) {
 4192|       |                              if (parse_ws_colon<Opts>(ctx, it, end)) {
 4193|       |                                 return;
 4194|       |                              }
 4195|       |
 4196|       |                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
 4197|       |
 4198|       |                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
 4199|       |                              if constexpr (std::integral<id_type>) {
 4200|       |                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
 4201|       |                              }
 4202|       |                              else {
 4203|       |                                 // The id is turned into an index below and never leaves this
 4204|       |                                 // reader, so the view of the window it borrows cannot outlive it.
 4205|       |                                 parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4206|       |                              }
 4207|       |                              if (bool(ctx.error)) [[unlikely]]
 4208|       |                                 return;
 4209|       |                              if (skip_ws<Opts>(ctx, it, end)) {
 4210|       |                                 return;
 4211|       |                              }
 4212|       |                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
 4213|       |                                 ctx.error = error_code::syntax_error;
 4214|       |                                 return;
 4215|       |                              }
 4216|       |
 4217|       |                              size_t type_index;
 4218|       |                              if constexpr (std::integral<id_type>) {
 4219|       |                                 type_index = variant_id_to_index<T>::op(type_id);
 4220|       |                              }
 4221|       |                              else {
 4222|       |                                 type_index = variant_id_to_index<T>::op(
 4223|       |                                    type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4224|       |                              }
 4225|       |                              if (type_index < ids_v<T>.size()) [[likely]] {
 4226|       |                                 // Check if the deduced types include the tag-specified type
 4227|       |                                 // If not, the tag doesn't match the fields
 4228|       |                                 // We're already inside if constexpr (deduction_registry.size()), so we know deduction
 4229|       |                                 // is happening. At this point, possible_types has been narrowed by field deduction.
 4230|       |                                 // Check if the tag-specified type is still possible
 4231|       |                                 const bool type_is_possible = possible_types[type_index];
 4232|       |                                 if (!type_is_possible) {
 4233|       |                                    // Tag specifies a type that doesn't match the fields seen so far
 4234|       |                                    ctx.error = error_code::no_matching_variant_type;
 4235|       |                                    return;
 4236|       |                                 }
 4237|       |
 4238|       |                                 if (!position_after_tag()) return;
 4239|       |                                 tag_specified_index = type_index; // Store the tag-specified type
 4240|       |                                 if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4241|       |                                 std::visit(
 4242|       |                                    [&](auto&& v) {
 4243|       |                                       using V = std::decay_t<decltype(v)>;
 4244|       |                                       constexpr bool is_object =
 4245|       |                                          (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4246|       |                                       if constexpr (variant_unit_alternative<V>) {
 4247|       |                                          // A unit alternative carries no data; its object holds only the
 4248|       |                                          // discriminator. Consume that body through an empty reflected object so
 4249|       |                                          // unknown-key policy and terminator handling match every other alternative.
 4250|       |                                          detail::variant_unit_body unit_body{};
 4251|       |                                          from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4252|       |                                                                                             tag_literal>(unit_body,
 4253|       |                                                                                                          ctx, it, end);
 4254|       |                                       }
 4255|       |                                       else if constexpr (is_object) {
 4256|       |                                          if constexpr (contains_tag<V, tag_literal>()) {
 4257|       |                                             // tag is a struct field, must re-parse
 4258|       |                                             if (!start.rewind(ctx, it, end)) return;
 4259|       |                                          }
 4260|       |                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
 4261|       |                                                                                                           end);
 4262|       |                                       }
 4263|       |                                       else if constexpr (is_memory_object<V>) {
 4264|       |                                          if (!v) {
 4265|       |                                             if constexpr (is_specialization_v<V, std::optional>) {
 4266|       |                                                if constexpr (requires { v.emplace(); }) {
 4267|       |                                                   v.emplace();
 4268|       |                                                }
 4269|       |                                                else {
 4270|       |                                                   v = typename V::value_type{};
 4271|       |                                                }
 4272|       |                                             }
 4273|       |                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4274|       |                                                v = std::make_unique<typename V::element_type>();
 4275|       |                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4276|       |                                                v = std::make_shared<typename V::element_type>();
 4277|       |                                             else if constexpr (constructible<V>) {
 4278|       |                                                v = meta_construct_v<V>();
 4279|       |                                             }
 4280|       |                                             else if constexpr (std::is_pointer_v<V> &&
 4281|       |                                                                can_allocate_raw_pointer<Opts,
 4282|       |                                                                                         std::decay_t<decltype(ctx)>>) {
 4283|       |                                                if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4284|       |                                                   return;
 4285|       |                                                }
 4286|       |                                             }
 4287|       |                                             else {
 4288|       |                                                ctx.error = error_code::invalid_nullable_read;
 4289|       |                                                return;
 4290|       |                                                // Cannot read into unset nullable that is not std::optional,
 4291|       |                                                // std::unique_ptr, or std::shared_ptr
 4292|       |                                             }
 4293|       |                                          }
 4294|       |                                          if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4295|       |                                             // tag is a struct field, must re-parse
 4296|       |                                             if (!start.rewind(ctx, it, end)) return;
 4297|       |                                          }
 4298|       |                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4299|       |                                             *v, ctx, it, end);
 4300|       |                                       }
 4301|       |                                       else if constexpr (custom_read<V>) {
 4302|       |                                          // Custom handlers parse the remaining body themselves and do not
 4303|       |                                          // accept the tag template parameter; the tag was already consumed.
 4304|       |                                          // This only works when the tag was the first key. If it came later,
 4305|       |                                          // we were reset to the object start and the custom handler would
 4306|       |                                          // absorb the tag, so error rather than corrupt the value.
 4307|       |                                          if (!first_key) {
 4308|       |                                             ctx.error = error_code::feature_not_supported;
 4309|       |                                             ctx.custom_error_message =
 4310|       |                                                "the tag must be the first key for a custom variant alternative";
 4311|       |                                             return;
 4312|       |                                          }
 4313|       |                                          from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4314|       |                                       }
 4315|       |                                    },
 4316|       |                                    value);
 4317|       |
 4318|       |                                 return; // we've decoded our target type
 4319|       |                              }
 4320|       |                              else [[unlikely]] {
 4321|       |                                 // Check if we have a default type (ids array shorter than variant)
 4322|       |                                 constexpr auto ids_size = ids_v<T>.size();
 4323|       |                                 constexpr auto variant_size = std::variant_size_v<T>;
 4324|       |                                 if constexpr (ids_size < variant_size) {
 4325|       |                                    // Use the first unlabeled type as the default
 4326|       |                                    const auto default_type_index = ids_size;
 4327|       |
 4328|       |                                    if (!position_after_tag()) return;
 4329|       |                                    tag_specified_index = default_type_index; // Store the default type index
 4330|       |                                    if (value.index() != default_type_index)
 4331|       |                                       emplace_runtime_variant(value, default_type_index);
 4332|       |                                    std::visit(
 4333|       |                                       [&](auto&& v) {
 4334|       |                                          using V = std::decay_t<decltype(v)>;
 4335|       |                                          constexpr bool is_object =
 4336|       |                                             (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4337|       |                                          if constexpr (variant_unit_alternative<V>) {
 4338|       |                                             // A unit alternative carries no data; its object holds only the
 4339|       |                                             // discriminator. Consume that body through an empty reflected object so
 4340|       |                                             // unknown-key policy and terminator handling match every other
 4341|       |                                             // alternative.
 4342|       |                                             detail::variant_unit_body unit_body{};
 4343|       |                                             from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4344|       |                                                                                                tag_literal>(
 4345|       |                                                unit_body, ctx, it, end);
 4346|       |                                          }
 4347|       |                                          else if constexpr (is_object) {
 4348|       |                                             if constexpr (contains_tag<V, tag_literal>()) {
 4349|       |                                                // tag is a struct field, must re-parse
 4350|       |                                                if (!start.rewind(ctx, it, end)) return;
 4351|       |                                             }
 4352|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4353|       |                                          }
 4354|       |                                          else if constexpr (is_memory_object<V>) {
 4355|       |                                             if (!v) {
 4356|       |                                                if constexpr (is_specialization_v<V, std::optional>) {
 4357|       |                                                   if constexpr (requires { v.emplace(); }) {
 4358|       |                                                      v.emplace();
 4359|       |                                                   }
 4360|       |                                                   else {
 4361|       |                                                      v = typename V::value_type{};
 4362|       |                                                   }
 4363|       |                                                }
 4364|       |                                                else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4365|       |                                                   v = std::make_unique<typename V::element_type>();
 4366|       |                                                else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4367|       |                                                   v = std::make_shared<typename V::element_type>();
 4368|       |                                                else if constexpr (constructible<V>) {
 4369|       |                                                   v = meta_construct_v<V>();
 4370|       |                                                }
 4371|       |                                                else if constexpr (std::is_pointer_v<V> &&
 4372|       |                                                                   can_allocate_raw_pointer<
 4373|       |                                                                      Opts, std::decay_t<decltype(ctx)>>) {
 4374|       |                                                   if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4375|       |                                                      return;
 4376|       |                                                   }
 4377|       |                                                }
 4378|       |                                                else {
 4379|       |                                                   ctx.error = error_code::invalid_nullable_read;
 4380|       |                                                   return;
 4381|       |                                                }
 4382|       |                                             }
 4383|       |                                             if constexpr (contains_tag<memory_type<V>, tag_literal>()) {
 4384|       |                                                // tag is a struct field, must re-parse
 4385|       |                                                if (!start.rewind(ctx, it, end)) return;
 4386|       |                                             }
 4387|       |                                             from<JSON, memory_type<V>>::template op<opening_handled<Opts>()>(*v, ctx,
 4388|       |                                                                                                              it, end);
 4389|       |                                          }
 4390|       |                                          else if constexpr (custom_read<V>) {
 4391|       |                                             // Custom handlers parse the remaining body themselves; this only
 4392|       |                                             // works when the tag was the first key (see above). If it came
 4393|       |                                             // later we were reset to the object start, so error rather than
 4394|       |                                             // let the custom handler absorb the tag.
 4395|       |                                             if (!first_key) {
 4396|       |                                                ctx.error = error_code::feature_not_supported;
 4397|       |                                                ctx.custom_error_message =
 4398|       |                                                   "the tag must be the first key for a custom variant alternative";
 4399|       |                                                return;
 4400|       |                                             }
 4401|       |                                             from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4402|       |                                          }
 4403|       |                                       },
 4404|       |                                       value);
 4405|       |
 4406|       |                                    return;
 4407|       |                                 }
 4408|       |                                 else {
 4409|       |                                    ctx.error = error_code::no_matching_variant_type;
 4410|       |                                    ctx.custom_error_message = variant_ids_string_v<T>;
 4411|       |                                    return;
 4412|       |                                 }
 4413|       |                              }
 4414|       |                           }
 4415|       |                        }
 4416|       |
 4417|       |                        // Inline decode_hash lookup for variant deduction
 4418|       |                        using deduction_keys_t = keys_wrapper<variant_deduction_keys<T>>;
 4419|       |                        constexpr auto& DeductionHashInfo = hash_info<deduction_keys_t>;
 4420|       |                        const auto deduction_index =
 4421|       |                           decode_hash_with_size<JSON, deduction_keys_t, DeductionHashInfo, DeductionHashInfo.type>::op(
 4422|       |                              key.data(), key.data() + key.size(), key.size());
 4423|       |                        if (deduction_index < deduction_key_count && variant_deduction_keys<T>[deduction_index] == key)
 4424|       |                           [[likely]] {
 4425|       |                           possible_types &= deduction_bits[deduction_index];
 4426|       |                        }
 4427|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4428|       |                           ctx.error = error_code::unknown_key;
 4429|       |                           return;
 4430|       |                        }
 4431|       |                     }
 4432|       |                     else if constexpr (not tag_v<T>.empty()) {
 4433|       |                        // empty object case for variant, if there are no normal elements
 4434|       |                        if (key == tag_v<T>) {
 4435|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4436|       |                              return;
 4437|       |                           }
 4438|       |
 4439|       |                           // The id is turned into an index below and never leaves this reader,
 4440|       |                           // so the view of the window it borrows cannot outlive that window.
 4441|       |                           std::string_view type_id{};
 4442|       |                           parse_transient_string_view<ws_handled<Opts>()>(type_id, ctx, it, end);
 4443|       |                           if (bool(ctx.error)) [[unlikely]]
 4444|       |                              return;
 4445|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4446|       |                              return;
 4447|       |                           }
 4448|       |
 4449|       |                           const auto type_index = variant_id_to_index<T>::op(
 4450|       |                              type_id.data(), type_id.data() + type_id.size(), type_id.size());
 4451|       |                           if (type_index < ids_v<T>.size()) [[likely]] {
 4452|       |                              if (!position_after_tag()) return;
 4453|       |                              tag_specified_index = type_index; // Store the tag-specified type
 4454|       |                              if (value.index() != type_index) emplace_runtime_variant(value, type_index);
 4455|       |                           }
 4456|       |                           else {
 4457|       |                              // Check if we have a default type (ids array shorter than variant)
 4458|       |                              constexpr auto ids_size = ids_v<T>.size();
 4459|       |                              constexpr auto variant_size = std::variant_size_v<T>;
 4460|       |                              if constexpr (ids_size < variant_size) {
 4461|       |                                 // Use the first unlabeled type as the default
 4462|       |                                 if (!position_after_tag()) return;
 4463|       |                                 const auto default_index = ids_size;
 4464|       |                                 tag_specified_index = default_index; // Store the default type index
 4465|       |                                 if (value.index() != default_index) emplace_runtime_variant(value, default_index);
 4466|       |                              }
 4467|       |                              else {
 4468|       |                                 ctx.error = error_code::no_matching_variant_type;
 4469|       |                                 ctx.custom_error_message = variant_ids_string_v<T>;
 4470|       |                                 return;
 4471|       |                              }
 4472|       |                           }
 4473|       |                           // Parse the type (handles tag skipping and unknown keys)
 4474|       |                           std::visit(
 4475|       |                              [&](auto&& v) {
 4476|       |                                 using V = std::decay_t<decltype(v)>;
 4477|       |                                 if constexpr (custom_read<V>) {
 4478|       |                                    // Custom handlers parse the remaining object body themselves and do not
 4479|       |                                    // accept the tag template parameter that reflected objects use to skip an
 4480|       |                                    // interior tag key. That only works when the tag is the first key (it was
 4481|       |                                    // just consumed). If the tag came after other keys, position_after_tag()
 4482|       |                                    // reset us to the object start and the custom handler would absorb the tag
 4483|       |                                    // into its value, so error here rather than corrupt the result.
 4484|       |                                    if (!first_key) {
 4485|       |                                       ctx.error = error_code::feature_not_supported;
 4486|       |                                       ctx.custom_error_message =
 4487|       |                                          "the tag must be the first key for a custom variant alternative";
 4488|       |                                       return;
 4489|       |                                    }
 4490|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4491|       |                                 }
 4492|       |                                 else {
 4493|       |                                    if constexpr (contains_tag<V, tag_literal>()) {
 4494|       |                                       // tag is a struct field, must re-parse
 4495|       |                                       if (!start.rewind(ctx, it, end)) return;
 4496|       |                                    }
 4497|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4498|       |                                 }
 4499|       |                              },
 4500|       |                              value);
 4501|       |                           return;
 4502|       |                        }
 4503|       |                        else if constexpr (Opts.error_on_unknown_keys) {
 4504|       |                           ctx.error = error_code::unknown_key;
 4505|       |                           return;
 4506|       |                        }
 4507|       |                        else {
 4508|       |                           // Skip unknown key's value (non-tag key in empty variant)
 4509|       |                           if (parse_ws_colon<Opts>(ctx, it, end)) {
 4510|       |                              return;
 4511|       |                           }
 4512|       |                           skip_value<JSON>::op<Opts>(ctx, it, end);
 4513|       |                           if (bool(ctx.error)) [[unlikely]]
 4514|       |                              return;
 4515|       |                           resync_window_end(ctx, end); // a streaming skip refills
 4516|       |                           if (skip_ws<Opts>(ctx, it, end)) {
 4517|       |                              return;
 4518|       |                           }
 4519|       |                           continue; // Continue loop to find the tag
 4520|       |                        }
 4521|       |                     }
 4522|       |                     else if constexpr (Opts.error_on_unknown_keys) {
 4523|       |                        ctx.error = error_code::unknown_key;
 4524|       |                        return;
 4525|       |                     }
 4526|       |
 4527|       |                     auto matching_types = possible_types.popcount();
 4528|       |                     if (matching_types == 0) {
 4529|       |                        ctx.error = error_code::no_matching_variant_type;
 4530|       |                        return;
 4531|       |                     }
 4532|       |                     // Only short-circuit for variants without tags
 4533|       |                     else if constexpr (tag_v<T>.empty()) {
 4534|       |                        if (matching_types == 1) {
 4535|       |                           if (!start.rewind(ctx, it, end)) return;
 4536|       |                           const auto type_index = possible_types.countr_zero();
 4537|       |
 4538|       |                           if (value.index() != static_cast<size_t>(type_index))
 4539|       |                              emplace_runtime_variant(value, type_index);
 4540|       |                           std::visit(
 4541|       |                              [&](auto&& v) {
 4542|       |                                 using V = std::decay_t<decltype(v)>;
 4543|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4544|       |                                 if constexpr (variant_unit_alternative<V>) {
 4545|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4546|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4547|       |                                    // terminator handling match every other alternative.
 4548|       |                                    detail::variant_unit_body unit_body{};
 4549|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4550|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4551|       |                                                                                                    end);
 4552|       |                                 }
 4553|       |                                 else if constexpr (is_object) {
 4554|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4555|       |                                 }
 4556|       |                                 else if constexpr (is_memory_object<V>) {
 4557|       |                                    if (!v) {
 4558|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4559|       |                                          if constexpr (requires { v.emplace(); }) {
 4560|       |                                             v.emplace();
 4561|       |                                          }
 4562|       |                                          else {
 4563|       |                                             v = typename V::value_type{};
 4564|       |                                          }
 4565|       |                                       }
 4566|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4567|       |                                          v = std::make_unique<typename V::element_type>();
 4568|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4569|       |                                          v = std::make_shared<typename V::element_type>();
 4570|       |                                       else if constexpr (constructible<V>) {
 4571|       |                                          v = meta_construct_v<V>();
 4572|       |                                       }
 4573|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4574|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4575|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4576|       |                                             return;
 4577|       |                                          }
 4578|       |                                       }
 4579|       |                                       else {
 4580|       |                                          ctx.error = error_code::invalid_nullable_read;
 4581|       |                                          return;
 4582|       |                                          // Cannot read into unset nullable that is not std::optional,
 4583|       |                                          // std::unique_ptr, or std::shared_ptr
 4584|       |                                       }
 4585|       |                                    }
 4586|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4587|       |                                       *v, ctx, it, end);
 4588|       |                                 }
 4589|       |                                 else if constexpr (custom_read<V>) {
 4590|       |                                    // Custom handlers parse the remaining body themselves.
 4591|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4592|       |                                 }
 4593|       |                              },
 4594|       |                              value);
 4595|       |
 4596|       |                           return; // we've decoded our target type
 4597|       |                        }
 4598|       |                     }
 4599|       |                     // For tagged variants, continue processing to validate tags
 4600|       |                     if (parse_ws_colon<Opts>(ctx, it, end)) {
 4601|       |                        return;
 4602|       |                     }
 4603|       |
 4604|       |                     skip_value<JSON>::op<Opts>(ctx, it, end);
 4605|       |                     if (bool(ctx.error)) [[unlikely]]
 4606|       |                        return;
 4607|       |                     resync_window_end(ctx, end); // a streaming skip refills
 4608|       |                     if (skip_ws<Opts>(ctx, it, end)) {
 4609|       |                        return;
 4610|       |                     }
 4611|       |                  }
 4612|       |                  // Only apply ambiguous variant resolution if we have multiple object types
 4613|       |                  if constexpr ((type_counts::n_object + type_counts::n_nullable_object) > 1) {
 4614|       |                     // After parsing all keys, check if we have multiple matching types
 4615|       |                     // If so, choose the one with the fewest fields
 4616|       |                     auto final_matching = possible_types.popcount();
 4617|       |                     if (final_matching == 0) {
 4618|       |                        ctx.error = error_code::no_matching_variant_type;
 4619|       |                     }
 4620|       |                     else if (final_matching == 1) {
 4621|       |                        // Single type remains after field deduction
 4622|       |                        const auto type_index = possible_types.countr_zero();
 4623|       |
 4624|       |                        // Validate against tag if one was specified
 4625|       |                        if (tag_specified_index.has_value() &&
 4626|       |                            tag_specified_index.value() != static_cast<size_t>(type_index)) {
 4627|       |                           ctx.error = error_code::no_matching_variant_type;
 4628|       |                           return;
 4629|       |                        }
 4630|       |
 4631|       |                        if (!start.rewind(ctx, it, end)) return;
 4632|       |                        if (value.index() != static_cast<size_t>(type_index))
 4633|       |                           emplace_runtime_variant(value, type_index);
 4634|       |                        std::visit(
 4635|       |                           [&](auto&& v) {
 4636|       |                              using V = std::decay_t<decltype(v)>;
 4637|       |                              constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4638|       |                              if constexpr (variant_unit_alternative<V>) {
 4639|       |                                 // A unit alternative carries no data; its object holds only the discriminator.
 4640|       |                                 // Consume that body through an empty reflected object so unknown-key policy and
 4641|       |                                 // terminator handling match every other alternative.
 4642|       |                                 detail::variant_unit_body unit_body{};
 4643|       |                                 from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4644|       |                                                                                    tag_literal>(unit_body, ctx, it,
 4645|       |                                                                                                 end);
 4646|       |                              }
 4647|       |                              else if constexpr (is_object) {
 4648|       |                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4649|       |                              }
 4650|       |                              else if constexpr (is_memory_object<V>) {
 4651|       |                                 if (!v) {
 4652|       |                                    if constexpr (is_specialization_v<V, std::optional>) {
 4653|       |                                       if constexpr (requires { v.emplace(); }) {
 4654|       |                                          v.emplace();
 4655|       |                                       }
 4656|       |                                       else {
 4657|       |                                          v = typename V::value_type{};
 4658|       |                                       }
 4659|       |                                    }
 4660|       |                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4661|       |                                       v = std::make_unique<typename V::element_type>();
 4662|       |                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4663|       |                                       v = std::make_shared<typename V::element_type>();
 4664|       |                                    else if constexpr (constructible<V>) {
 4665|       |                                       v = meta_construct_v<V>();
 4666|       |                                    }
 4667|       |                                    else if constexpr (std::is_pointer_v<V> &&
 4668|       |                                                       can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4669|       |                                       if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4670|       |                                          return;
 4671|       |                                       }
 4672|       |                                    }
 4673|       |                                    else {
 4674|       |                                       ctx.error = error_code::invalid_nullable_read;
 4675|       |                                       return;
 4676|       |                                    }
 4677|       |                                 }
 4678|       |                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
 4679|       |                                                                                                               it, end);
 4680|       |                              }
 4681|       |                              else if constexpr (custom_read<V>) {
 4682|       |                                 // Custom handlers parse the remaining body themselves.
 4683|       |                                 from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4684|       |                              }
 4685|       |                           },
 4686|       |                           value);
 4687|       |                     }
 4688|       |                     else if (final_matching > 1) {
 4689|       |                        constexpr auto N = std::variant_size_v<T>;
 4690|       |
 4691|       |                        // Compile-time array of field counts for each variant type
 4692|       |                        constexpr auto field_counts = []<size_t... I>(std::index_sequence<I...>) {
 4693|       |                           return std::array<size_t, N> {
 4694|       |                              ([]<size_t J = I>() -> size_t {
 4695|       |                                 using V = std::decay_t<std::variant_alternative_t<J, T>>;
 4696|       |                                 if constexpr (glaze_object_t<V> || reflectable<V>) {
 4697|       |                                    return reflect<V>::size;
 4698|       |                                 }
 4699|       |                                 else if constexpr (is_memory_object<V>) {
 4700|       |                                    using X = memory_type<V>;
 4701|       |                                    if constexpr (glaze_object_t<X> || reflectable<X>) {
 4702|       |                                       return reflect<X>::size;
 4703|       |                                    }
 4704|       |                                    else {
 4705|       |                                       return (std::numeric_limits<size_t>::max)();
 4706|       |                                    }
 4707|       |                                 }
 4708|       |                                 else {
 4709|       |                                    return (std::numeric_limits<size_t>::max)();
 4710|       |                                 }
 4711|       |                              }.template operator()<I>())...
 4712|       |                           };
 4713|       |                        }(std::make_index_sequence<N>{});
 4714|       |
 4715|       |                        // Find the type with minimum field count among the possible types
 4716|       |                        size_t min_fields = (std::numeric_limits<size_t>::max)();
 4717|       |                        size_t chosen_index = N; // Invalid index initially
 4718|       |
 4719|       |                        for (size_t i = 0; i < N; ++i) {
 4720|       |                           if (possible_types[i] && field_counts[i] < min_fields) {
 4721|       |                              min_fields = field_counts[i];
 4722|       |                              chosen_index = i;
 4723|       |                           }
 4724|       |                        }
 4725|       |
 4726|       |                        if (chosen_index < N) {
 4727|       |                           // Validate against tag if one was specified
 4728|       |                           if (tag_specified_index.has_value() && tag_specified_index.value() != chosen_index) {
 4729|       |                              ctx.error = error_code::no_matching_variant_type;
 4730|       |                              return;
 4731|       |                           }
 4732|       |
 4733|       |                           if (!start.rewind(ctx, it, end)) return;
 4734|       |                           if (value.index() != chosen_index) emplace_runtime_variant(value, chosen_index);
 4735|       |                           std::visit(
 4736|       |                              [&](auto&& v) {
 4737|       |                                 using V = std::decay_t<decltype(v)>;
 4738|       |                                 constexpr bool is_object = (glaze_object_t<V> || reflectable<V>) && not custom_read<V>;
 4739|       |                                 if constexpr (variant_unit_alternative<V>) {
 4740|       |                                    // A unit alternative carries no data; its object holds only the discriminator.
 4741|       |                                    // Consume that body through an empty reflected object so unknown-key policy and
 4742|       |                                    // terminator handling match every other alternative.
 4743|       |                                    detail::variant_unit_body unit_body{};
 4744|       |                                    from<JSON, detail::variant_unit_body>::template op<opening_handled<Opts>(),
 4745|       |                                                                                       tag_literal>(unit_body, ctx, it,
 4746|       |                                                                                                    end);
 4747|       |                                 }
 4748|       |                                 else if constexpr (is_object) {
 4749|       |                                    from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
 4750|       |                                 }
 4751|       |                                 else if constexpr (is_memory_object<V>) {
 4752|       |                                    if (!v) {
 4753|       |                                       if constexpr (is_specialization_v<V, std::optional>) {
 4754|       |                                          if constexpr (requires { v.emplace(); }) {
 4755|       |                                             v.emplace();
 4756|       |                                          }
 4757|       |                                          else {
 4758|       |                                             v = typename V::value_type{};
 4759|       |                                          }
 4760|       |                                       }
 4761|       |                                       else if constexpr (is_specialization_v<V, std::unique_ptr>)
 4762|       |                                          v = std::make_unique<typename V::element_type>();
 4763|       |                                       else if constexpr (is_specialization_v<V, std::shared_ptr>)
 4764|       |                                          v = std::make_shared<typename V::element_type>();
 4765|       |                                       else if constexpr (constructible<V>) {
 4766|       |                                          v = meta_construct_v<V>();
 4767|       |                                       }
 4768|       |                                       else if constexpr (std::is_pointer_v<V> &&
 4769|       |                                                          can_allocate_raw_pointer<Opts, std::decay_t<decltype(ctx)>>) {
 4770|       |                                          if (!try_allocate_raw_pointer<Opts>(v, ctx)) {
 4771|       |                                             return;
 4772|       |                                          }
 4773|       |                                       }
 4774|       |                                       else {
 4775|       |                                          ctx.error = error_code::invalid_nullable_read;
 4776|       |                                          return;
 4777|       |                                       }
 4778|       |                                    }
 4779|       |                                    from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
 4780|       |                                       *v, ctx, it, end);
 4781|       |                                 }
 4782|       |                                 else if constexpr (custom_read<V>) {
 4783|       |                                    // Custom handlers parse the remaining body themselves.
 4784|       |                                    from<JSON, V>::template op<opening_handled<Opts>()>(v, ctx, it, end);
 4785|       |                                 }
 4786|       |                              },
 4787|       |                              value);
 4788|       |                        }
 4789|       |                        else {
 4790|       |                           ctx.error = error_code::no_matching_variant_type;
 4791|       |                        }
 4792|       |                     }
 4793|       |                  }
 4794|       |                  else {
 4795|       |                     // For variants with 0 or 1 object types, use the original error handling
 4796|       |                     ctx.error = error_code::no_matching_variant_type;
 4797|       |                  }
 4798|       |               }
 4799|      0|               break;
 4800|  22.4k|            }
 4801|   596k|            case '[':
  ------------------
  |  Branch (4801:13): [True: 596k, False: 2.21M]
  ------------------
 4802|       |               // As with '{' above: the array reader each alternative goes through counts the level.
 4803|   596k|               process_variant_alternatives<T, is_variant_array>::template op<Opts>(value, ctx, it, end);
 4804|   596k|               break;
 4805|  5.11k|            case '"': {
  ------------------
  |  Branch (4805:13): [True: 5.11k, False: 2.81M]
  ------------------
 4806|  5.11k|               process_variant_alternatives<T, is_variant_str>::template op<Opts>(value, ctx, it, end);
 4807|  5.11k|               break;
 4808|  22.4k|            }
 4809|    902|            case 't':
  ------------------
  |  Branch (4809:13): [True: 902, False: 2.81M]
  ------------------
 4810|  1.19k|            case 'f': {
  ------------------
  |  Branch (4810:13): [True: 297, False: 2.81M]
  ------------------
 4811|  1.19k|               process_variant_alternatives<T, is_variant_bool>::template op<Opts>(value, ctx, it, end);
 4812|  1.19k|               break;
 4813|    902|            }
 4814|    584|            case 'n':
  ------------------
  |  Branch (4814:13): [True: 584, False: 2.81M]
  ------------------
 4815|       |               if constexpr (variant_count_v<T, is_variant_null> == 0) {
 4816|       |                  ctx.error = error_code::no_matching_variant_type;
 4817|       |               }
 4818|    584|               else {
 4819|    584|                  constexpr auto first_idx = variant_first_index_v<T, is_variant_null>;
 4820|    584|                  using V = std::variant_alternative_t<first_idx, T>;
 4821|    584|                  if (!std::holds_alternative<V>(value)) value = V{};
  ------------------
  |  Branch (4821:23): [True: 199, False: 385]
  ------------------
 4822|    584|                  match<"null", Opts>(ctx, it, end);
 4823|    584|               }
 4824|    584|               break;
 4825|  2.18M|            default: {
  ------------------
  |  Branch (4825:13): [True: 2.18M, False: 627k]
  ------------------
 4826|       |               // Not bool, string, object, or array so must be number or null
 4827|  2.18M|               process_variant_alternatives<T, is_variant_num>::template op<Opts>(value, ctx, it, end);
 4828|  2.18M|            }
 4829|  2.81M|            }
 4830|       |         }
 4831|       |         else {
 4832|       |            // For non-auto-deducible variants, try each type until one succeeds
 4833|       |            constexpr auto N = std::variant_size_v<T>;
 4834|       |            bool parsed = false;
 4835|       |            bool exhausted = false; // speculation budget spent; see charge_speculation
 4836|       |
 4837|       |            for_each<N>([&]<size_t I>() {
 4838|       |               if (parsed || exhausted || variant_alternative_exhausted(ctx)) return;
 4839|       |
 4840|       |               auto copy_it = it;
 4841|       |               // A rejected alternative may have bailed out inside a container, which leaves its
 4842|       |               // nesting level counted (see enter_depth), so the depth rewinds with the iterator.
 4843|       |               const auto copy_depth = ctx.depth;
 4844|       |
 4845|       |               // Try parsing as this type
 4846|       |               if (value.index() != I) {
 4847|       |                  emplace_runtime_variant(value, I);
 4848|       |               }
 4849|       |
 4850|       |               std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
 4851|       |               if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 4852|       |                  exhausted = true; // only rejected attempts are charged; see charge_speculation
 4853|       |               }
 4854|       |
 4855|       |               if (!bool(ctx.error)) {
 4856|       |                  parsed = true;
 4857|       |               }
 4858|       |               else if constexpr (not Options.null_terminated) {
 4859|       |                  // In non-null-terminated mode, if we hit end_reached after advancing the iterator,
 4860|       |                  // it means we successfully parsed the value but couldn't skip trailing whitespace
 4861|       |                  if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 4862|       |                     // We advanced the iterator, so we did parse something -- unless what advanced it
 4863|       |                     // was an abandoned attempt, which is what a spent speculation budget means.
 4864|       |                     parsed = true;
 4865|       |                     ctx.error = error_code::none;
 4866|       |                  }
 4867|       |                  else {
 4868|       |                     // Reset for next attempt (unless this is the last type)
 4869|       |                     it = copy_it;
 4870|       |                     rewind_depth<Options>(ctx, copy_depth);
 4871|       |                     if constexpr (I + 1 < N) {
 4872|       |                        if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4873|       |                           ctx.error = error_code::none; // Clear error for next attempt
 4874|       |                        }
 4875|       |                     }
 4876|       |                  }
 4877|       |               }
 4878|       |               else {
 4879|       |                  // Reset for next attempt (unless this is the last type)
 4880|       |                  it = copy_it;
 4881|       |                  rewind_depth<Options>(ctx, copy_depth);
 4882|       |                  if constexpr (I + 1 < N) {
 4883|       |                     if (not exhausted && not variant_alternative_exhausted(ctx)) {
 4884|       |                        ctx.error = error_code::none; // Clear error for next attempt
 4885|       |                     }
 4886|       |                  }
 4887|       |               }
 4888|       |            });
 4889|       |         }
 4890|  2.81M|      }
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|   598k|      {
 3726|   598k|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|   598k|         else {
 3732|   598k|            constexpr auto N = std::variant_size_v<Variant>;
 3733|   598k|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|   598k|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|   598k|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|   598k|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|   598k|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|   598k|               size_t non_const_idx = 0;
 3793|       |
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|   598k|                     return;
 3797|   598k|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|   598k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|   598k|                     auto copy_it{it};
 3801|   598k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|   598k|                     if (!std::holds_alternative<V>(value)) {
 3803|   598k|                        value = V{};
 3804|   598k|                     }
 3805|   598k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|   598k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|   598k|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|   598k|                     }
 3809|   598k|                     if (!bool(ctx.error)) {
 3810|   598k|                        found_match = true;
 3811|   598k|                     }
 3812|   598k|                     else if constexpr (not Options.null_terminated) {
 3813|   598k|                        constexpr bool is_complete_type =
 3814|   598k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|   598k|                        if constexpr (is_complete_type) {
 3817|   598k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|   598k|                              found_match = true;
 3819|   598k|                              ctx.error = error_code::none;
 3820|   598k|                           }
 3821|   598k|                           else {
 3822|   598k|                              it = copy_it;
 3823|   598k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|   598k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|   598k|                                  not variant_alternative_exhausted(ctx)) {
 3826|   598k|                                 ctx.error = error_code::none;
 3827|   598k|                              }
 3828|   598k|                           }
 3829|   598k|                        }
 3830|   598k|                        else {
 3831|   598k|                           it = copy_it;
 3832|   598k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|   598k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|   598k|                               not variant_alternative_exhausted(ctx)) {
 3835|   598k|                              ctx.error = error_code::none;
 3836|   598k|                           }
 3837|   598k|                        }
 3838|   598k|                     }
 3839|   598k|                     else {
 3840|   598k|                        it = copy_it;
 3841|   598k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|   598k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|   598k|                            not variant_alternative_exhausted(ctx)) {
 3844|   598k|                           ctx.error = error_code::none;
 3845|   598k|                        }
 3846|   598k|                     }
 3847|   598k|                     ++non_const_idx;
 3848|   598k|                  }
 3849|   598k|               });
 3850|   598k|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 13.1k, False: 585k]
  ------------------
 3851|  13.1k|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|  13.1k|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|   598k|         }
 3864|   598k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|   598k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 598k]
  |  Branch (3795:38): [True: 0, False: 598k]
  |  Branch (3795:51): [True: 0, False: 598k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|   598k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|   598k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|   598k|                     auto copy_it{it};
 3801|   598k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|   598k|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 471k, False: 126k]
  ------------------
 3803|   471k|                        value = V{};
 3804|   471k|                     }
 3805|   598k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|   598k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 13.1k, False: 585k]
  |  Branch (3806:45): [True: 0, False: 13.1k]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|   598k|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 585k, False: 13.1k]
  ------------------
 3810|   585k|                        found_match = true;
 3811|   585k|                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|  13.1k|                     else {
 3840|  13.1k|                        it = copy_it;
 3841|  13.1k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  13.1k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3842:29): [True: 0, False: 13.1k]
  |  Branch (3842:68): [True: 0, False: 0]
  ------------------
 3843|      0|                            not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3843:29): [True: 0, False: 0]
  ------------------
 3844|      0|                           ctx.error = error_code::none;
 3845|      0|                        }
 3846|  13.1k|                     }
 3847|   598k|                     ++non_const_idx;
 3848|   598k|                  }
 3849|   598k|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERNSt3__16vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS4_9allocatorIS9_EEEETkNS_10is_contextERNS_7contextERPKcSH_EEvOT0_OT1_OT2_T3_:
   49|   598k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|   598k|         else {
   60|   598k|            using V = std::remove_cvref_t<T>;
   61|   598k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|   598k|                                             end);
   63|   598k|         }
   64|   598k|      }
_ZN3glz4fromILj10ENSt3__16vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS1_9allocatorIS6_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERS9_TkNS_10is_contextERNS_7contextERPKcSH_EEvOT0_OT1_OT2_T3_:
 2308|   598k|      {
 2309|   598k|         constexpr auto Opts = ws_handled_off<Options>();
 2310|       |         if constexpr (!check_ws_handled(Options)) {
 2311|       |            if (skip_ws<Opts>(ctx, it, end)) {
 2312|       |               return;
 2313|       |            }
 2314|       |         }
 2315|       |
 2316|   598k|         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2316:14): [True: 0, False: 598k]
  ------------------
 2317|      0|            return;
 2318|      0|         }
 2319|       |         // one nesting level (see enter_depth): counted in both modes so the limit binds,
 2320|       |         // released at each syntactic close below
 2321|   598k|         if (enter_depth(ctx)) [[unlikely]] {
  ------------------
  |  Branch (2321:14): [True: 5, False: 598k]
  ------------------
 2322|      5|            return;
 2323|      5|         }
 2324|       |
 2325|   598k|         const auto ws_start = it;
 2326|   598k|         if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2326:14): [True: 0, False: 598k]
  ------------------
 2327|      0|            return;
 2328|      0|         }
 2329|       |
 2330|   598k|         if (*it == ']') {
  ------------------
  |  Branch (2330:14): [True: 7.36k, False: 591k]
  ------------------
 2331|  7.36k|            --ctx.depth;
 2332|  7.36k|            ++it;
 2333|  7.36k|            if constexpr ((resizable<T> || is_inplace_vector<T>) && not check_append_arrays(Opts)) {
 2334|  7.36k|               value.clear();
 2335|       |
 2336|       |               if constexpr (check_shrink_to_fit(Opts) && has_shrink_to_fit<T>) {
 2337|       |                  value.shrink_to_fit();
 2338|       |               }
 2339|  7.36k|            }
 2340|  7.36k|            return;
 2341|  7.36k|         }
 2342|       |
 2343|   591k|         const size_t ws_size = size_t(it - ws_start);
 2344|       |
 2345|   591k|         static constexpr bool should_append = (resizable<T> || is_inplace_vector<T>) && check_append_arrays(Opts);
  ------------------
  |  Branch (2345:49): [True: 591k, Folded]
  |  Branch (2345:65): [Folded, False: 0]
  |  Branch (2345:90): [Folded, False: 0]
  ------------------
 2346|   591k|         if constexpr (not should_append) {
 2347|   591k|            const auto n = value.size();
 2348|       |
 2349|   591k|            auto value_it = value.begin();
 2350|       |
 2351|   597k|            for (size_t i = 0; i < n; ++i) {
  ------------------
  |  Branch (2351:32): [True: 130k, False: 466k]
  ------------------
 2352|   130k|               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
 2353|   130k|               if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (2353:20): [True: 770, False: 129k]
  ------------------
 2354|    770|                  return;
 2355|   129k|               if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2355:20): [True: 0, False: 129k]
  ------------------
 2356|      0|                  return;
 2357|      0|               }
 2358|   129k|               if (*it == ',') {
  ------------------
  |  Branch (2358:20): [True: 6.36k, False: 123k]
  ------------------
 2359|  6.36k|                  ++it;
 2360|       |
 2361|  6.36k|                  if constexpr (!Opts.minified && !Opts.comments) {
 2362|  6.36k|                     if (ws_size && ws_size < size_t(end - it)) {
  ------------------
  |  Branch (2362:26): [True: 3.46k, False: 2.90k]
  |  Branch (2362:37): [True: 3.02k, False: 434]
  ------------------
 2363|  3.02k|                        skip_matching_ws(ws_start, it, ws_size);
 2364|  3.02k|                     }
 2365|  6.36k|                  }
 2366|       |
 2367|  6.36k|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2367:23): [True: 0, False: 6.36k]
  ------------------
 2368|      0|                     return;
 2369|      0|                  }
 2370|  6.36k|               }
 2371|   123k|               else if (*it == ']') {
  ------------------
  |  Branch (2371:25): [True: 123k, False: 76]
  ------------------
 2372|   123k|                  --ctx.depth;
 2373|   123k|                  ++it;
 2374|   123k|                  if constexpr (erasable<T>) {
 2375|   123k|                     value.erase(value_it,
 2376|   123k|                                 value.end()); // use erase rather than resize for non-default constructible elements
 2377|       |
 2378|       |                     if constexpr (check_shrink_to_fit(Opts) && has_shrink_to_fit<T>) {
 2379|       |                        value.shrink_to_fit();
 2380|       |                     }
 2381|   123k|                  }
 2382|   123k|                  return;
 2383|   123k|               }
 2384|     76|               else [[unlikely]] {
 2385|     76|                  ctx.error = error_code::expected_bracket;
 2386|     76|                  return;
 2387|     76|               }
 2388|   129k|            }
 2389|   591k|         }
 2390|       |
 2391|       |         if constexpr (Opts.partial_read) {
 2392|       |            // partial_read stops early on a success path, so give the level back like the
 2393|       |            // syntactic-close paths do; otherwise it accumulates across reads sharing a context.
 2394|       |            --ctx.depth;
 2395|       |            return;
 2396|       |         }
 2397|   591k|         else {
 2398|       |            // growing
 2399|   591k|            if constexpr (emplace_backable<T> || has_try_emplace_back<T>) {
 2400|  1.69M|               while (it < end) {
  ------------------
  |  Branch (2400:23): [True: 1.57M, False: 124k]
  ------------------
 2401|       |                  // Streaming refill point: at start of each iteration, ensure buffer has data
 2402|       |                  if constexpr (has_streaming_state<decltype(ctx)>) {
 2403|       |                     if (ctx.stream.enabled()) {
 2404|       |                        const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 2405|       |                        const size_t remaining = ctx.stream.size() - consumed;
 2406|       |                        // Refill when less than half of buffer remains to ensure space for next element
 2407|       |                        if (remaining <= ctx.stream.size() / 2 || it >= end) {
 2408|       |                           const char* new_it;
 2409|       |                           const char* new_end;
 2410|       |                           ctx.stream.consume_and_refill(consumed, new_it, new_end);
 2411|       |                           it = new_it;
 2412|       |                           end = new_end;
 2413|       |                           if (it >= end && ctx.stream.at_eof()) {
 2414|       |                              break; // No more data, exit loop normally
 2415|       |                           }
 2416|       |                        }
 2417|       |                     }
 2418|       |                  }
 2419|       |
 2420|       |                  if constexpr (has_try_emplace_back<T>) {
 2421|       |                     if (value.try_emplace_back())
 2422|       |                        parse<JSON>::op<ws_handled<Opts>()>(value.back(), ctx, it, end);
 2423|       |                     else
 2424|       |                        ctx.error = error_code::exceeded_static_array_size;
 2425|       |                  }
 2426|  1.57M|                  else {
 2427|  1.57M|                     parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
 2428|  1.57M|                  }
 2429|       |
 2430|  1.57M|                  if (bool(ctx.error)) [[unlikely]]
  ------------------
  |  Branch (2430:23): [True: 11.3k, False: 1.56M]
  ------------------
 2431|  11.3k|                     return;
 2432|       |
 2433|       |                  // Streaming refill point: after parsing each element, refill if buffer is low
 2434|       |                  if constexpr (has_streaming_state<decltype(ctx)>) {
 2435|       |                     if (ctx.stream.enabled()) {
 2436|       |                        const size_t consumed = static_cast<size_t>(it - ctx.stream.data());
 2437|       |                        // Refill when less than 25% of buffer remains to ensure enough space for next element
 2438|       |                        if (ctx.stream.size() - consumed <= ctx.stream.size() / 4 || it >= end) {
 2439|       |                           const char* new_it;
 2440|       |                           const char* new_end;
 2441|       |                           ctx.stream.consume_and_refill(consumed, new_it, new_end);
 2442|       |                           it = new_it;
 2443|       |                           end = new_end;
 2444|       |                           if (it >= end && ctx.stream.at_eof()) {
 2445|       |                              ctx.error = error_code::unexpected_end;
 2446|       |                              return;
 2447|       |                           }
 2448|       |                        }
 2449|       |                     }
 2450|       |                  }
 2451|       |
 2452|  1.56M|                  if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2452:23): [True: 0, False: 1.56M]
  ------------------
 2453|      0|                     return;
 2454|      0|                  }
 2455|  1.56M|                  if (*it == ',') [[likely]] {
  ------------------
  |  Branch (2455:23): [True: 1.10M, False: 455k]
  ------------------
 2456|  1.10M|                     ++it;
 2457|       |
 2458|  1.10M|                     if constexpr (!Opts.minified && !Opts.comments) {
 2459|  1.10M|                        if (ws_size && ws_size < size_t(end - it)) {
  ------------------
  |  Branch (2459:29): [True: 15.0k, False: 1.09M]
  |  Branch (2459:40): [True: 14.3k, False: 658]
  ------------------
 2460|  14.3k|                           skip_matching_ws(ws_start, it, ws_size);
 2461|  14.3k|                        }
 2462|  1.10M|                     }
 2463|       |
 2464|  1.10M|                     if (skip_ws<Opts>(ctx, it, end)) {
  ------------------
  |  Branch (2464:26): [True: 0, False: 1.10M]
  ------------------
 2465|      0|                        return;
 2466|      0|                     }
 2467|  1.10M|                  }
 2468|   455k|                  else if (*it == ']') {
  ------------------
  |  Branch (2468:28): [True: 454k, False: 1.02k]
  ------------------
 2469|   454k|                     --ctx.depth;
 2470|   454k|                     ++it;
 2471|       |                     if constexpr (check_shrink_to_fit(Opts) && has_shrink_to_fit<T>) {
 2472|       |                        value.shrink_to_fit();
 2473|       |                     }
 2474|   454k|                     return;
 2475|   454k|                  }
 2476|  1.02k|                  else [[unlikely]] {
 2477|  1.02k|                     ctx.error = error_code::expected_bracket;
 2478|  1.02k|                     return;
 2479|  1.02k|                  }
 2480|  1.56M|               }
 2481|       |
 2482|       |               // A valid array always returns from inside the loop upon reaching ']'.
 2483|       |               // For a null-terminated buffer the loop can only exit here by falling
 2484|       |               // through when `it` reaches the terminator without a closing bracket,
 2485|       |               // which means the input was truncated (e.g. "[", "[1," or "[1,2,").
 2486|       |               // Non-null-terminated buffers surface this through skip_ws/depth
 2487|       |               // tracking (or the streaming refill break), so this guard is limited
 2488|       |               // to the null-terminated case.
 2489|   124k|               if constexpr (Opts.null_terminated) {
 2490|   124k|                  ctx.error = error_code::unexpected_end;
 2491|   124k|               }
 2492|       |            }
 2493|       |            else {
 2494|       |               ctx.error = error_code::exceeded_static_array_size;
 2495|       |            }
 2496|   591k|         }
 2497|   591k|      }
_ZN3glz12rewind_depthITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEETkNS_10is_contextENS_7contextEEEvRT0_j:
 3697|  16.0k|   {
 3698|  16.0k|      if (ctx.error == error_code::exceeded_max_recursive_depth) [[unlikely]] {
  ------------------
  |  Branch (3698:11): [True: 1.24k, False: 14.7k]
  ------------------
 3699|  1.24k|         return;
 3700|  1.24k|      }
 3701|  14.7k|      if constexpr (Opts.null_terminated) {
 3702|  14.7k|         ctx.depth = depth;
 3703|       |      }
 3704|       |      else {
 3705|       |         if (ctx.error != error_code::end_reached && ctx.error != error_code::unexpected_end) {
 3706|       |            ctx.depth = depth;
 3707|       |         }
 3708|       |      }
 3709|  14.7k|   }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|   598k|               for_each<N>([&]<size_t I>() {
 3795|   598k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 585k, False: 13.1k]
  |  Branch (3795:38): [True: 0, False: 13.1k]
  |  Branch (3795:51): [True: 1.24k, False: 11.9k]
  ------------------
 3796|   586k|                     return;
 3797|   586k|                  }
 3798|  11.9k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  11.9k|               });
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|  6.27k|      {
 3726|  6.27k|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|  6.27k|         else {
 3732|  6.27k|            constexpr auto N = std::variant_size_v<Variant>;
 3733|  6.27k|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|  6.27k|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|  6.27k|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|  6.27k|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|  6.27k|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|  6.27k|               size_t non_const_idx = 0;
 3793|       |
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|  6.27k|                     return;
 3797|  6.27k|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  6.27k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  6.27k|                     auto copy_it{it};
 3801|  6.27k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  6.27k|                     if (!std::holds_alternative<V>(value)) {
 3803|  6.27k|                        value = V{};
 3804|  6.27k|                     }
 3805|  6.27k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  6.27k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|  6.27k|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|  6.27k|                     }
 3809|  6.27k|                     if (!bool(ctx.error)) {
 3810|  6.27k|                        found_match = true;
 3811|  6.27k|                     }
 3812|  6.27k|                     else if constexpr (not Options.null_terminated) {
 3813|  6.27k|                        constexpr bool is_complete_type =
 3814|  6.27k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|  6.27k|                        if constexpr (is_complete_type) {
 3817|  6.27k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|  6.27k|                              found_match = true;
 3819|  6.27k|                              ctx.error = error_code::none;
 3820|  6.27k|                           }
 3821|  6.27k|                           else {
 3822|  6.27k|                              it = copy_it;
 3823|  6.27k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  6.27k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|  6.27k|                                  not variant_alternative_exhausted(ctx)) {
 3826|  6.27k|                                 ctx.error = error_code::none;
 3827|  6.27k|                              }
 3828|  6.27k|                           }
 3829|  6.27k|                        }
 3830|  6.27k|                        else {
 3831|  6.27k|                           it = copy_it;
 3832|  6.27k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  6.27k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|  6.27k|                               not variant_alternative_exhausted(ctx)) {
 3835|  6.27k|                              ctx.error = error_code::none;
 3836|  6.27k|                           }
 3837|  6.27k|                        }
 3838|  6.27k|                     }
 3839|  6.27k|                     else {
 3840|  6.27k|                        it = copy_it;
 3841|  6.27k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  6.27k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|  6.27k|                            not variant_alternative_exhausted(ctx)) {
 3844|  6.27k|                           ctx.error = error_code::none;
 3845|  6.27k|                        }
 3846|  6.27k|                     }
 3847|  6.27k|                     ++non_const_idx;
 3848|  6.27k|                  }
 3849|  6.27k|               });
 3850|  6.27k|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 884, False: 5.38k]
  ------------------
 3851|    884|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|    884|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|  6.27k|         }
 3864|  6.27k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 6.27k]
  |  Branch (3795:38): [True: 0, False: 6.27k]
  |  Branch (3795:51): [True: 0, False: 6.27k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  6.27k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 6.27k]
  |  Branch (3795:38): [True: 0, False: 6.27k]
  |  Branch (3795:51): [True: 0, False: 6.27k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  6.27k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 6.27k]
  |  Branch (3795:38): [True: 0, False: 6.27k]
  |  Branch (3795:51): [True: 0, False: 6.27k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  6.27k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  6.27k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  6.27k|                     auto copy_it{it};
 3801|  6.27k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  6.27k|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 4.75k, False: 1.51k]
  ------------------
 3803|  4.75k|                        value = V{};
 3804|  4.75k|                     }
 3805|  6.27k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  6.27k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 884, False: 5.38k]
  |  Branch (3806:45): [True: 0, False: 884]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|  6.27k|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 5.38k, False: 884]
  ------------------
 3810|  5.38k|                        found_match = true;
 3811|  5.38k|                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|    884|                     else {
 3840|    884|                        it = copy_it;
 3841|    884|                        rewind_depth<Options>(ctx, copy_depth);
 3842|    884|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3842:29): [True: 0, False: 884]
  |  Branch (3842:68): [True: 0, False: 0]
  ------------------
 3843|      0|                            not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3843:29): [True: 0, False: 0]
  ------------------
 3844|      0|                           ctx.error = error_code::none;
 3845|      0|                        }
 3846|    884|                     }
 3847|  6.27k|                     ++non_const_idx;
 3848|  6.27k|                  }
 3849|  6.27k|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_T3_:
   49|  6.27k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  6.27k|         else {
   60|  6.27k|            using V = std::remove_cvref_t<T>;
   61|  6.27k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  6.27k|                                             end);
   63|  6.27k|         }
   64|  6.27k|      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERPKcSC_S7_TkNS_10is_contextERNS_7contextEQcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_T1_:
  892|  6.27k|      {
  893|       |         if constexpr (check_string_as_number(Opts)) {
  894|       |            auto start = it;
  895|       |            skip_number<Opts>(ctx, it, end);
  896|       |            if (bool(ctx.error)) [[unlikely]] {
  897|       |               return;
  898|       |            }
  899|       |            value.append(start, size_t(it - start));
  900|       |         }
  901|  6.27k|         else {
  902|  6.27k|            if constexpr (!check_opening_handled(Opts)) {
  903|       |               if constexpr (!check_ws_handled(Opts)) {
  904|       |                  if (skip_ws<Opts>(ctx, it, end)) {
  905|       |                     return;
  906|       |                  }
  907|       |               }
  908|       |
  909|  6.27k|               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  ------------------
  |  Branch (909:20): [True: 0, False: 6.27k]
  ------------------
  910|      0|                  return;
  911|      0|               }
  912|  6.27k|            }
  913|       |
  914|  6.27k|            if constexpr (not check_raw_string(Opts)) {
  915|  6.27k|               static constexpr auto string_padding_bytes = 8;
  916|       |
  917|  6.27k|               auto start = it;
  918|  6.27k|               uint64_t ascii_acc{};
  919|  1.27M|               while (true) {
  ------------------
  |  Branch (919:23): [True: 1.27M, Folded]
  ------------------
  920|  1.27M|                  if (it >= end) [[unlikely]] {
  ------------------
  |  Branch (920:23): [True: 351, False: 1.27M]
  ------------------
  921|    351|                     ctx.error = error_code::unexpected_end;
  922|    351|                     return;
  923|    351|                  }
  924|       |
  925|  1.27M|                  uint64_t chunk;
  926|  1.27M|                  std::memcpy(&chunk, it, 8);
  927|       |                  if constexpr (std::endian::native == std::endian::big) {
  928|       |                     chunk = std::byteswap(chunk);
  929|       |                  }
  930|  1.27M|                  ascii_acc |= chunk;
  931|  1.27M|                  const uint64_t test_chars = has_quote(chunk);
  932|  1.27M|                  if (test_chars) {
  ------------------
  |  Branch (932:23): [True: 7.74k, False: 1.26M]
  ------------------
  933|  7.74k|                     it += (countr_zero(test_chars) >> 3);
  934|       |
  935|  7.74k|                     auto* prev = it - 1;
  936|  10.6k|                     while (*prev == '\\') {
  ------------------
  |  Branch (936:29): [True: 2.93k, False: 7.74k]
  ------------------
  937|  2.93k|                        --prev;
  938|  2.93k|                     }
  939|  7.74k|                     if (size_t(it - prev) % 2) {
  ------------------
  |  Branch (939:26): [True: 5.91k, False: 1.82k]
  ------------------
  940|  5.91k|                        break;
  941|  5.91k|                     }
  942|  1.82k|                     ++it; // skip the escaped quote
  943|  1.82k|                  }
  944|  1.26M|                  else {
  945|  1.26M|                     it += 8;
  946|  1.26M|                  }
  947|  1.27M|               }
  948|       |
  949|  5.91k|               if (validate_utf8_span<Opts>(ctx, start, it, ascii_acc)) [[unlikely]] {
  ------------------
  |  Branch (949:20): [True: 248, False: 5.67k]
  ------------------
  950|    248|                  return;
  951|    248|               }
  952|       |
  953|  5.67k|               auto n = size_t(it - start);
  954|  5.67k|               value.resize(n + string_padding_bytes);
  955|       |
  956|  5.67k|               auto* p = value.data();
  957|       |
  958|   104k|               while (true) {
  ------------------
  |  Branch (958:23): [True: 104k, Folded]
  ------------------
  959|   104k|                  if (start >= it) {
  ------------------
  |  Branch (959:23): [True: 4.91k, False: 99.4k]
  ------------------
  960|  4.91k|                     break;
  961|  4.91k|                  }
  962|       |
  963|  99.4k|                  std::memcpy(p, start, 8);
  964|  99.4k|                  uint64_t swar;
  965|  99.4k|                  std::memcpy(&swar, p, 8);
  966|       |                  if constexpr (std::endian::native == std::endian::big) {
  967|       |                     swar = std::byteswap(swar);
  968|       |                  }
  969|       |
  970|  99.4k|                  constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
  971|  99.4k|                  const uint64_t lo7 = swar & lo7_mask;
  972|  99.4k|                  const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
  973|  99.4k|                  const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
  974|  99.4k|                  uint64_t next = ~((backslash & less_32) | swar);
  975|       |
  976|  99.4k|                  next &= repeat_byte8(0b10000000);
  977|  99.4k|                  if (next == 0) {
  ------------------
  |  Branch (977:23): [True: 95.0k, False: 4.41k]
  ------------------
  978|  95.0k|                     start += 8;
  979|  95.0k|                     p += 8;
  980|  95.0k|                     continue;
  981|  95.0k|                  }
  982|       |
  983|  4.41k|                  next = countr_zero(next) >> 3;
  984|  4.41k|                  start += next;
  985|  4.41k|                  if (start >= it) {
  ------------------
  |  Branch (985:23): [True: 476, False: 3.94k]
  ------------------
  986|    476|                     break;
  987|    476|                  }
  988|       |
  989|  3.94k|                  if ((*start & 0b11100000) == 0) [[unlikely]] {
  ------------------
  |  Branch (989:23): [True: 85, False: 3.85k]
  ------------------
  990|     85|                     ctx.error = error_code::syntax_error;
  991|     85|                     return;
  992|     85|                  }
  993|  3.85k|                  ++start; // skip the escape
  994|  3.85k|                  if (*start == 'u') {
  ------------------
  |  Branch (994:23): [True: 2.45k, False: 1.39k]
  ------------------
  995|  2.45k|                     ++start;
  996|  2.45k|                     p += next;
  997|  2.45k|                     const auto mark = start;
  998|  2.45k|                     const auto offset = handle_unicode_code_point(start, p, end);
  999|  2.45k|                     if (offset == 0) [[unlikely]] {
  ------------------
  |  Branch (999:26): [True: 168, False: 2.29k]
  ------------------
 1000|    168|                        ctx.error = error_code::unicode_escape_conversion_failure;
 1001|    168|                        return;
 1002|    168|                     }
 1003|  2.29k|                     n += offset;
 1004|       |                     // escape + u + unicode code points
 1005|  2.29k|                     n -= 2 + uint32_t(start - mark);
 1006|  2.29k|                  }
 1007|  1.39k|                  else {
 1008|  1.39k|                     p += next;
 1009|  1.39k|                     *p = char_unescape_table[uint8_t(*start)];
 1010|  1.39k|                     if (*p == 0) [[unlikely]] {
  ------------------
  |  Branch (1010:26): [True: 32, False: 1.36k]
  ------------------
 1011|     32|                        ctx.error = error_code::invalid_escape;
 1012|     32|                        return;
 1013|     32|                     }
 1014|  1.36k|                     ++p;
 1015|  1.36k|                     ++start;
 1016|  1.36k|                     --n;
 1017|  1.36k|                  }
 1018|  3.85k|               }
 1019|       |
 1020|  5.38k|               value.resize(n);
 1021|  5.38k|               ++it;
 1022|       |            }
 1023|       |            else {
 1024|       |               // raw_string
 1025|       |               auto start = it;
 1026|       |               skip_string_view(ctx, it, end);
 1027|       |               if (bool(ctx.error)) [[unlikely]]
 1028|       |                  return;
 1029|       |
 1030|       |               if (validate_utf8_span<Opts>(ctx, start, it)) [[unlikely]] {
 1031|       |                  return;
 1032|       |               }
 1033|       |
 1034|       |               value.assign(start, size_t(it - start));
 1035|       |               ++it;
 1036|       |            }
 1037|  6.27k|         }
 1038|  6.27k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 5.38k, False: 884]
  |  Branch (3795:38): [True: 0, False: 884]
  |  Branch (3795:51): [True: 0, False: 884]
  ------------------
 3796|  5.38k|                     return;
 3797|  5.38k|                  }
 3798|    884|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    884|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 5.38k, False: 884]
  |  Branch (3795:38): [True: 0, False: 884]
  |  Branch (3795:51): [True: 0, False: 884]
  ------------------
 3796|  5.38k|                     return;
 3797|  5.38k|                  }
 3798|    884|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    884|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|  6.27k|               for_each<N>([&]<size_t I>() {
 3795|  6.27k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 5.38k, False: 884]
  |  Branch (3795:38): [True: 0, False: 884]
  |  Branch (3795:51): [True: 0, False: 884]
  ------------------
 3796|  5.38k|                     return;
 3797|  5.38k|                  }
 3798|    884|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    884|               });
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|  1.38k|      {
 3726|  1.38k|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|  1.38k|         else {
 3732|  1.38k|            constexpr auto N = std::variant_size_v<Variant>;
 3733|  1.38k|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|  1.38k|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|  1.38k|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|  1.38k|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|  1.38k|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|  1.38k|               size_t non_const_idx = 0;
 3793|       |
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|  1.38k|                     return;
 3797|  1.38k|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  1.38k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  1.38k|                     auto copy_it{it};
 3801|  1.38k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  1.38k|                     if (!std::holds_alternative<V>(value)) {
 3803|  1.38k|                        value = V{};
 3804|  1.38k|                     }
 3805|  1.38k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  1.38k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|  1.38k|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|  1.38k|                     }
 3809|  1.38k|                     if (!bool(ctx.error)) {
 3810|  1.38k|                        found_match = true;
 3811|  1.38k|                     }
 3812|  1.38k|                     else if constexpr (not Options.null_terminated) {
 3813|  1.38k|                        constexpr bool is_complete_type =
 3814|  1.38k|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|  1.38k|                        if constexpr (is_complete_type) {
 3817|  1.38k|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|  1.38k|                              found_match = true;
 3819|  1.38k|                              ctx.error = error_code::none;
 3820|  1.38k|                           }
 3821|  1.38k|                           else {
 3822|  1.38k|                              it = copy_it;
 3823|  1.38k|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  1.38k|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|  1.38k|                                  not variant_alternative_exhausted(ctx)) {
 3826|  1.38k|                                 ctx.error = error_code::none;
 3827|  1.38k|                              }
 3828|  1.38k|                           }
 3829|  1.38k|                        }
 3830|  1.38k|                        else {
 3831|  1.38k|                           it = copy_it;
 3832|  1.38k|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  1.38k|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|  1.38k|                               not variant_alternative_exhausted(ctx)) {
 3835|  1.38k|                              ctx.error = error_code::none;
 3836|  1.38k|                           }
 3837|  1.38k|                        }
 3838|  1.38k|                     }
 3839|  1.38k|                     else {
 3840|  1.38k|                        it = copy_it;
 3841|  1.38k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  1.38k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|  1.38k|                            not variant_alternative_exhausted(ctx)) {
 3844|  1.38k|                           ctx.error = error_code::none;
 3845|  1.38k|                        }
 3846|  1.38k|                     }
 3847|  1.38k|                     ++non_const_idx;
 3848|  1.38k|                  }
 3849|  1.38k|               });
 3850|  1.38k|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 250, False: 1.13k]
  ------------------
 3851|    250|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|    250|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|  1.38k|         }
 3864|  1.38k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.38k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.38k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.38k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 1.38k]
  |  Branch (3795:38): [True: 0, False: 1.38k]
  |  Branch (3795:51): [True: 0, False: 1.38k]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  1.38k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  1.38k|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  1.38k|                     auto copy_it{it};
 3801|  1.38k|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  1.38k|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 1.18k, False: 194]
  ------------------
 3803|  1.18k|                        value = V{};
 3804|  1.18k|                     }
 3805|  1.38k|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  1.38k|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 250, False: 1.13k]
  |  Branch (3806:45): [True: 0, False: 250]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|  1.38k|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 1.13k, False: 250]
  ------------------
 3810|  1.13k|                        found_match = true;
 3811|  1.13k|                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|    250|                     else {
 3840|    250|                        it = copy_it;
 3841|    250|                        rewind_depth<Options>(ctx, copy_depth);
 3842|    250|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3842:29): [True: 0, False: 250]
  |  Branch (3842:68): [True: 0, False: 0]
  ------------------
 3843|      0|                            not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3843:29): [True: 0, False: 0]
  ------------------
 3844|      0|                           ctx.error = error_code::none;
 3845|      0|                        }
 3846|    250|                     }
 3847|  1.38k|                     ++non_const_idx;
 3848|  1.38k|                  }
 3849|  1.38k|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERbTkNS_10is_contextERNS_7contextERPKcS8_EEvOT0_OT1_OT2_T3_:
   49|  1.38k|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  1.38k|         else {
   60|  1.38k|            using V = std::remove_cvref_t<T>;
   61|  1.38k|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  1.38k|                                             end);
   63|  1.38k|         }
   64|  1.38k|      }
_ZN3glz4fromILj10EbE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEETkNS_6bool_tERbTkNS_10is_contextERNS_7contextERPKcS8_EEvOT0_OT1_OT2_T3_:
  669|  1.38k|      {
  670|       |         if constexpr (check_quoted_num(Opts)) {
  671|       |            if (skip_ws<Opts>(ctx, it, end)) {
  672|       |               return;
  673|       |            }
  674|       |            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  675|       |               return;
  676|       |            }
  677|       |         }
  678|       |
  679|       |         if constexpr (!check_ws_handled(Opts)) {
  680|       |            if (skip_ws<Opts>(ctx, it, end)) {
  681|       |               return;
  682|       |            }
  683|       |         }
  684|       |
  685|       |         if constexpr (check_bools_as_numbers(Opts)) {
  686|       |            if (*it == '1') {
  687|       |               value = true;
  688|       |               ++it;
  689|       |            }
  690|       |            else if (*it == '0') {
  691|       |               value = false;
  692|       |               ++it;
  693|       |            }
  694|       |            else {
  695|       |               ctx.error = error_code::syntax_error;
  696|       |               return;
  697|       |            }
  698|       |         }
  699|  1.38k|         else {
  700|       |            if constexpr (not check_is_padded(Opts)) {
  701|       |               if (size_t(end - it) < 4) [[unlikely]] {
  702|       |                  ctx.error = error_code::expected_true_or_false;
  703|       |                  return;
  704|       |               }
  705|       |            }
  706|       |
  707|  1.38k|            uint32_t c;
  708|  1.38k|            static constexpr uint32_t u_true = 0b01100101'01110101'01110010'01110100;
  709|  1.38k|            static constexpr uint32_t u_fals = 0b01110011'01101100'01100001'01100110;
  710|  1.38k|            std::memcpy(&c, it, 4);
  711|       |            if constexpr (std::endian::native == std::endian::big) {
  712|       |               c = std::byteswap(c);
  713|       |            }
  714|  1.38k|            it += 4;
  715|  1.38k|            if (c == u_true) {
  ------------------
  |  Branch (715:17): [True: 862, False: 521]
  ------------------
  716|    862|               value = true;
  717|    862|            }
  718|    521|            else if (it == end) [[unlikely]] {
  ------------------
  |  Branch (718:22): [True: 25, False: 496]
  ------------------
  719|     25|               ctx.error = error_code::unexpected_end;
  720|     25|               return;
  721|     25|            }
  722|    496|            else {
  723|    496|               if (c == u_fals && (*it == 'e')) [[likely]] {
  ------------------
  |  Branch (723:20): [True: 286, False: 210]
  |  Branch (723:35): [True: 271, False: 15]
  ------------------
  724|    271|                  value = false;
  725|    271|                  ++it;
  726|    271|               }
  727|    225|               else [[unlikely]] {
  728|    225|                  ctx.error = error_code::expected_true_or_false;
  729|    225|                  return;
  730|    225|               }
  731|    496|            }
  732|  1.38k|         }
  733|       |
  734|       |         if constexpr (check_quoted_num(Opts)) {
  735|       |            if constexpr (not Opts.null_terminated) {
  736|       |               if (it == end) [[unlikely]] {
  737|       |                  ctx.error = error_code::unexpected_end;
  738|       |                  return;
  739|       |               }
  740|       |            }
  741|       |            if (match<'"'>(ctx, it)) {
  742|       |               return;
  743|       |            }
  744|       |            if constexpr (not Opts.null_terminated) {
  745|       |               if (it == end) {
  746|       |                  ctx.error = error_code::end_reached;
  747|       |                  return;
  748|       |               }
  749|       |            }
  750|       |         }
  751|  1.38k|         else {
  752|       |            if constexpr (not Opts.null_terminated) {
  753|       |               if (it == end) {
  754|       |                  ctx.error = error_code::end_reached;
  755|       |                  return;
  756|       |               }
  757|       |            }
  758|  1.38k|         }
  759|  1.38k|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 1.13k, False: 250]
  |  Branch (3795:38): [True: 0, False: 250]
  |  Branch (3795:51): [True: 0, False: 250]
  ------------------
 3796|  1.13k|                     return;
 3797|  1.13k|                  }
 3798|    250|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    250|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|  1.38k|               for_each<N>([&]<size_t I>() {
 3795|  1.38k|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 1.13k, False: 250]
  |  Branch (3795:38): [True: 0, False: 250]
  |  Branch (3795:51): [True: 0, False: 250]
  ------------------
 3796|  1.13k|                     return;
 3797|  1.13k|                  }
 3798|    250|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|    250|               });
_ZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_:
 3725|  2.19M|      {
 3726|  2.19M|         constexpr auto category_count = variant_count_v<Variant, Trait>;
 3727|       |
 3728|       |         if constexpr (category_count == 0) {
 3729|       |            ctx.error = error_code::no_matching_variant_type;
 3730|       |         }
 3731|  2.19M|         else {
 3732|  2.19M|            constexpr auto N = std::variant_size_v<Variant>;
 3733|  2.19M|            constexpr auto const_count = variant_filtered_count_v<Variant, Trait, true>;
 3734|  2.19M|            constexpr auto non_const_count = variant_filtered_count_v<Variant, Trait, false>;
 3735|       |
 3736|  2.19M|            bool found_match{};
 3737|       |            // Set when the speculative parsing budget runs out; see charge_speculation. An ambiguous
 3738|       |            // nest re-parses the same subtree per alternative at every level, which is exponential,
 3739|       |            // so the budget stops it and the failure already in hand is reported.
 3740|  2.19M|            bool exhausted{};
 3741|       |
 3742|       |            // First pass: const glaze types in this category
 3743|       |            if constexpr (const_count > 0) {
 3744|       |               for_each<N>([&]<size_t I>() {
 3745|       |                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3746|       |                     return;
 3747|       |                  }
 3748|       |                  using V = std::variant_alternative_t<I, Variant>;
 3749|       |                  if constexpr (Trait<V>::value && glaze_const_value_t<V>) {
 3750|       |                     // run time substitute to compare to const value
 3751|       |                     std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
 3752|       |                     auto copy_it{it};
 3753|       |                     // A rejected alternative may have bailed out inside a container, which leaves its
 3754|       |                     // nesting level counted (see enter_depth). Rewind the depth with the iterator so
 3755|       |                     // trying N alternatives cannot spend N levels of the recursion budget.
 3756|       |                     const auto copy_depth{ctx.depth};
 3757|       |                     parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
 3758|       |                     static constexpr auto const_value{*meta_wrapper_v<V>};
 3759|       |                     if (substitute == const_value) {
 3760|       |                        found_match = true;
 3761|       |                        if (!std::holds_alternative<V>(value)) {
 3762|       |                           value = V{};
 3763|       |                        }
 3764|       |                     }
 3765|       |                     else {
 3766|       |                        // Rejected: charge the bytes it parsed before we rewind. See charge_speculation.
 3767|       |                        if (!charge_speculation(ctx, size_t(it - copy_it))) {
 3768|       |                           exhausted = true;
 3769|       |                        }
 3770|       |                        if constexpr (not Options.null_terminated) {
 3771|       |                           if (ctx.error == error_code::end_reached && not exhausted) {
 3772|       |                              ctx.error = error_code::none;
 3773|       |                           }
 3774|       |                        }
 3775|       |                        it = copy_it;
 3776|       |                        rewind_depth<Options>(ctx, copy_depth);
 3777|       |                     }
 3778|       |                  }
 3779|       |               });
 3780|       |               if (found_match) {
 3781|       |                  return;
 3782|       |               }
 3783|       |            }
 3784|       |
 3785|       |            // Second pass: non-const types in this category
 3786|  2.19M|            if constexpr (non_const_count > 0) {
 3787|       |               // Track position within matching types for "is last" check.
 3788|       |               // We iterate over all variant indices but only process matching types,
 3789|       |               // so we need runtime tracking (vs the old tuple-based approach where
 3790|       |               // the loop index directly corresponded to position in filtered set).
 3791|       |               // This has negligible cost: one increment per matching type.
 3792|  2.19M|               size_t non_const_idx = 0;
 3793|       |
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
 3796|  2.19M|                     return;
 3797|  2.19M|                  }
 3798|  2.19M|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  2.19M|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  2.19M|                     auto copy_it{it};
 3801|  2.19M|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  2.19M|                     if (!std::holds_alternative<V>(value)) {
 3803|  2.19M|                        value = V{};
 3804|  2.19M|                     }
 3805|  2.19M|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  2.19M|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|  2.19M|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|  2.19M|                     }
 3809|  2.19M|                     if (!bool(ctx.error)) {
 3810|  2.19M|                        found_match = true;
 3811|  2.19M|                     }
 3812|  2.19M|                     else if constexpr (not Options.null_terminated) {
 3813|  2.19M|                        constexpr bool is_complete_type =
 3814|  2.19M|                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|  2.19M|                        if constexpr (is_complete_type) {
 3817|  2.19M|                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|  2.19M|                              found_match = true;
 3819|  2.19M|                              ctx.error = error_code::none;
 3820|  2.19M|                           }
 3821|  2.19M|                           else {
 3822|  2.19M|                              it = copy_it;
 3823|  2.19M|                              rewind_depth<Options>(ctx, copy_depth);
 3824|  2.19M|                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|  2.19M|                                  not variant_alternative_exhausted(ctx)) {
 3826|  2.19M|                                 ctx.error = error_code::none;
 3827|  2.19M|                              }
 3828|  2.19M|                           }
 3829|  2.19M|                        }
 3830|  2.19M|                        else {
 3831|  2.19M|                           it = copy_it;
 3832|  2.19M|                           rewind_depth<Options>(ctx, copy_depth);
 3833|  2.19M|                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|  2.19M|                               not variant_alternative_exhausted(ctx)) {
 3835|  2.19M|                              ctx.error = error_code::none;
 3836|  2.19M|                           }
 3837|  2.19M|                        }
 3838|  2.19M|                     }
 3839|  2.19M|                     else {
 3840|  2.19M|                        it = copy_it;
 3841|  2.19M|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  2.19M|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|  2.19M|                            not variant_alternative_exhausted(ctx)) {
 3844|  2.19M|                           ctx.error = error_code::none;
 3845|  2.19M|                        }
 3846|  2.19M|                     }
 3847|  2.19M|                     ++non_const_idx;
 3848|  2.19M|                  }
 3849|  2.19M|               });
 3850|  2.19M|               if (!found_match) {
  ------------------
  |  Branch (3850:20): [True: 1.70k, False: 2.18M]
  ------------------
 3851|  1.70k|                  if constexpr (non_const_count == 1) {
 3852|       |                     // Keep the specific error from the single type we tried
 3853|       |                  }
 3854|       |                  else if (not exhausted && not variant_alternative_exhausted(ctx)) {
 3855|       |                     // Over-nested input is not a failure of the alternative set; keep saying so.
 3856|       |                     ctx.error = error_code::no_matching_variant_type;
 3857|       |                  }
 3858|  1.70k|               }
 3859|       |            }
 3860|       |            else {
 3861|       |               ctx.error = error_code::no_matching_variant_type;
 3862|       |            }
 3863|  2.19M|         }
 3864|  2.19M|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm0EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 2.19M]
  |  Branch (3795:38): [True: 0, False: 2.19M]
  |  Branch (3795:51): [True: 0, False: 2.19M]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  2.19M|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  2.19M|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm1EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 0, False: 2.19M]
  |  Branch (3795:38): [True: 0, False: 2.19M]
  |  Branch (3795:51): [True: 0, False: 2.19M]
  ------------------
 3796|      0|                     return;
 3797|      0|                  }
 3798|  2.19M|                  using V = std::variant_alternative_t<I, Variant>;
 3799|  2.19M|                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|  2.19M|                     auto copy_it{it};
 3801|  2.19M|                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|  2.19M|                     if (!std::holds_alternative<V>(value)) {
  ------------------
  |  Branch (3802:26): [True: 1.92M, False: 270k]
  ------------------
 3803|  1.92M|                        value = V{};
 3804|  1.92M|                     }
 3805|  2.19M|                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|  2.19M|                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
  ------------------
  |  Branch (3806:26): [True: 1.70k, False: 2.18M]
  |  Branch (3806:45): [True: 0, False: 1.70k]
  ------------------
 3807|      0|                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|      0|                     }
 3809|  2.19M|                     if (!bool(ctx.error)) {
  ------------------
  |  Branch (3809:26): [True: 2.18M, False: 1.70k]
  ------------------
 3810|  2.18M|                        found_match = true;
 3811|  2.18M|                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|  1.70k|                     else {
 3840|  1.70k|                        it = copy_it;
 3841|  1.70k|                        rewind_depth<Options>(ctx, copy_depth);
 3842|  1.70k|                        if (non_const_idx + 1 < non_const_count && not exhausted &&
  ------------------
  |  Branch (3842:29): [True: 0, False: 1.70k]
  |  Branch (3842:68): [True: 0, False: 0]
  ------------------
 3843|      0|                            not variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3843:29): [True: 0, False: 0]
  ------------------
 3844|      0|                           ctx.error = error_code::none;
 3845|      0|                        }
 3846|  1.70k|                     }
 3847|  2.19M|                     ++non_const_idx;
 3848|  2.19M|                  }
 3849|  2.19M|               });
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERdTkNS_10is_contextERNS_7contextERPKcS8_EEvOT0_OT1_OT2_T3_:
   49|  2.19M|      {
   50|       |         if constexpr (const_value_v<T>) {
   51|       |            if constexpr (check_error_on_const_read(Opts)) {
   52|       |               ctx.error = error_code::attempt_const_read;
   53|       |            }
   54|       |            else {
   55|       |               // do not read anything into the const value
   56|       |               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), end);
   57|       |            }
   58|       |         }
   59|  2.19M|         else {
   60|  2.19M|            using V = std::remove_cvref_t<T>;
   61|  2.19M|            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
   62|  2.19M|                                             end);
   63|  2.19M|         }
   64|  2.19M|      }
_ZN3glz4fromILj10EdE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEERPKcRdTkNS_10is_contextERNS_7contextES5_EEvOT1_OT2_OT0_T3_:
  767|  2.19M|      {
  768|       |         if constexpr (check_quoted_num(Opts)) {
  769|       |            if (skip_ws<Opts>(ctx, it, end)) {
  770|       |               return;
  771|       |            }
  772|       |            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
  773|       |               return;
  774|       |            }
  775|       |         }
  776|       |
  777|       |         if constexpr (!check_ws_handled(Opts)) {
  778|       |            if (skip_ws<Opts>(ctx, it, end)) {
  779|       |               return;
  780|       |            }
  781|       |         }
  782|       |
  783|  2.19M|         using V = std::decay_t<decltype(value)>;
  784|       |         if constexpr (int_t<V>) {
  785|       |            static_assert(sizeof(*it) == sizeof(char));
  786|       |
  787|       |            if constexpr (Opts.null_terminated) {
  788|       |               if (not glz::atoi(value, it)) [[unlikely]] {
  789|       |                  ctx.error = error_code::parse_number_failure;
  790|       |                  return;
  791|       |               }
  792|       |            }
  793|       |            else {
  794|       |               if (not glz::atoi(value, it, end)) [[unlikely]] {
  795|       |                  ctx.error = error_code::parse_number_failure;
  796|       |                  return;
  797|       |               }
  798|       |            }
  799|       |         }
  800|  2.19M|         else {
  801|       |// float128_t requires std::from_chars for floating-point, unavailable on older Apple platforms (iOS < 16.3)
  802|  2.19M|#if !defined(_LIBCPP_VERSION) || defined(_LIBCPP_AVAILABILITY_HAS_TO_CHARS_FLOATING_POINT)
  803|       |            if constexpr (is_float128<V>) {
  804|       |               auto [ptr, ec] = std::from_chars(it, end, value);
  805|       |               if (ec != std::errc()) {
  806|       |                  ctx.error = error_code::parse_number_failure;
  807|       |                  return;
  808|       |               }
  809|       |               it = ptr;
  810|       |            }
  811|       |            else
  812|       |#endif
  813|  2.19M|            {
  814|       |               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
  815|       |                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
  816|       |                  // place
  817|       |                  V temp;
  818|       |                  if constexpr (is_size_optimized(Opts)) {
  819|       |                     auto [ptr, ec] = simple_float::from_chars<Opts.null_terminated>(it, end, temp);
  820|       |                     if (ec != std::errc{}) [[unlikely]] {
  821|       |                        ctx.error = error_code::parse_number_failure;
  822|       |                        return;
  823|       |                     }
  824|       |                     it = ptr;
  825|       |                  }
  826|       |                  else {
  827|       |                     auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
  828|       |                     if (ec != std::errc()) [[unlikely]] {
  829|       |                        ctx.error = error_code::parse_number_failure;
  830|       |                        return;
  831|       |                     }
  832|       |                     it = ptr;
  833|       |                  }
  834|       |                  value = temp;
  835|       |               }
  836|  2.19M|               else {
  837|       |                  if constexpr (is_size_optimized(Opts)) {
  838|       |                     auto [ptr, ec] = simple_float::from_chars<Opts.null_terminated>(it, end, value);
  839|       |                     if (ec != std::errc{}) [[unlikely]] {
  840|       |                        ctx.error = error_code::parse_number_failure;
  841|       |                        return;
  842|       |                     }
  843|       |                     it = ptr;
  844|       |                  }
  845|  2.19M|                  else {
  846|  2.19M|                     auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
  847|  2.19M|                     if (ec != std::errc()) [[unlikely]] {
  ------------------
  |  Branch (847:26): [True: 1.70k, False: 2.18M]
  ------------------
  848|  1.70k|                        ctx.error = error_code::parse_number_failure;
  849|  1.70k|                        return;
  850|  1.70k|                     }
  851|  2.18M|                     it = ptr;
  852|  2.18M|                  }
  853|  2.19M|               }
  854|  2.19M|            }
  855|  2.19M|         }
  856|       |
  857|       |         if constexpr (check_quoted_num(Opts)) {
  858|       |            if constexpr (not Opts.null_terminated) {
  859|       |               if (it == end) [[unlikely]] {
  860|       |                  ctx.error = error_code::unexpected_end;
  861|       |                  return;
  862|       |               }
  863|       |            }
  864|       |            if (match<'"'>(ctx, it)) {
  865|       |               return;
  866|       |            }
  867|       |            if constexpr (not Opts.null_terminated) {
  868|       |               if (it == end) {
  869|       |                  ctx.error = error_code::end_reached;
  870|       |                  return;
  871|       |               }
  872|       |            }
  873|       |         }
  874|  2.19M|         else {
  875|       |            if constexpr (not Opts.null_terminated) {
  876|       |               if (it == end) {
  877|       |                  ctx.error = error_code::end_reached;
  878|       |                  return;
  879|       |               }
  880|       |            }
  881|  2.19M|         }
  882|  2.19M|      }
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm2EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm3EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm4EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });
_ZZN3glz28process_variant_alternativesINSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS6_ISD_EEEENSC_ISD_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSH_TkNS_10is_contextERNS_7contextERPKcSQ_EEvOT0_OT1_OT2_T3_ENKUlTnmvE_clILm5EEEDav:
 3794|  2.19M|               for_each<N>([&]<size_t I>() {
 3795|  2.19M|                  if (found_match || exhausted || variant_alternative_exhausted(ctx)) {
  ------------------
  |  Branch (3795:23): [True: 2.18M, False: 1.70k]
  |  Branch (3795:38): [True: 0, False: 1.70k]
  |  Branch (3795:51): [True: 0, False: 1.70k]
  ------------------
 3796|  2.18M|                     return;
 3797|  2.18M|                  }
 3798|  1.70k|                  using V = std::variant_alternative_t<I, Variant>;
 3799|       |                  if constexpr (Trait<V>::value && !glaze_const_value_t<V>) {
 3800|       |                     auto copy_it{it};
 3801|       |                     const auto copy_depth{ctx.depth}; // rewound with `it`; see the note above
 3802|       |                     if (!std::holds_alternative<V>(value)) {
 3803|       |                        value = V{};
 3804|       |                     }
 3805|       |                     parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
 3806|       |                     if (bool(ctx.error) && !charge_speculation(ctx, size_t(it - copy_it))) {
 3807|       |                        exhausted = true; // only rejected attempts are charged; see charge_speculation
 3808|       |                     }
 3809|       |                     if (!bool(ctx.error)) {
 3810|       |                        found_match = true;
 3811|       |                     }
 3812|       |                     else if constexpr (not Options.null_terminated) {
 3813|       |                        constexpr bool is_complete_type =
 3814|       |                           num_t<V> || bool_t<V> || string_t<V> || std::is_enum_v<V> || tuple_t<V> || is_std_tuple<V>;
 3815|       |
 3816|       |                        if constexpr (is_complete_type) {
 3817|       |                           if (ctx.error == error_code::end_reached && it > copy_it && not speculation_exhausted(ctx)) {
 3818|       |                              found_match = true;
 3819|       |                              ctx.error = error_code::none;
 3820|       |                           }
 3821|       |                           else {
 3822|       |                              it = copy_it;
 3823|       |                              rewind_depth<Options>(ctx, copy_depth);
 3824|       |                              if (non_const_idx + 1 < non_const_count && not exhausted &&
 3825|       |                                  not variant_alternative_exhausted(ctx)) {
 3826|       |                                 ctx.error = error_code::none;
 3827|       |                              }
 3828|       |                           }
 3829|       |                        }
 3830|       |                        else {
 3831|       |                           it = copy_it;
 3832|       |                           rewind_depth<Options>(ctx, copy_depth);
 3833|       |                           if (non_const_idx + 1 < non_const_count && not exhausted &&
 3834|       |                               not variant_alternative_exhausted(ctx)) {
 3835|       |                              ctx.error = error_code::none;
 3836|       |                           }
 3837|       |                        }
 3838|       |                     }
 3839|       |                     else {
 3840|       |                        it = copy_it;
 3841|       |                        rewind_depth<Options>(ctx, copy_depth);
 3842|       |                        if (non_const_idx + 1 < non_const_count && not exhausted &&
 3843|       |                            not variant_alternative_exhausted(ctx)) {
 3844|       |                           ctx.error = error_code::none;
 3845|       |                        }
 3846|       |                     }
 3847|       |                     ++non_const_idx;
 3848|       |                  }
 3849|  1.70k|               });

_ZN3glz11countr_zeroEm:
   29|  3.40M|   {
   30|       |#ifdef _MSC_VER
   31|       |      return std::countr_zero(x);
   32|       |#else
   33|  3.40M|#if __has_builtin(__builtin_ctzll)
   34|  3.40M|      return __builtin_ctzll(x);
   35|       |#else
   36|       |      return std::countr_zero(x);
   37|       |#endif
   38|  3.40M|#endif
   39|  3.40M|   }

_ZN3glz10comparitorIL_ZZNS_5matchITnNS_14string_literalEXtlNS2_ILm5EEEtlA5_cLc110ELc117ELc108ELc108EEEETnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS9_Qntcl15check_is_paddedT0_EEEvOT1_OT2_T3_E1SELm4EcEEbPKSB_:
  245|    588|   {
  246|       |      // pack() builds values in little-endian order (byte 0 in LSB position).
  247|       |      // On big-endian systems, memcpy produces native (big-endian) values,
  248|       |      // so we need to byteswap to match the packed representation.
  249|       |      if constexpr (N == 8) {
  250|       |         static constexpr auto packed = pack<Str, 8>();
  251|       |         uint64_t in;
  252|       |         std::memcpy(&in, other, 8);
  253|       |         if constexpr (std::endian::native == std::endian::big) {
  254|       |            in = std::byteswap(in);
  255|       |         }
  256|       |         return (in == packed);
  257|       |      }
  258|       |      else if constexpr (N == 7) {
  259|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  260|       |         uint64_t in{};
  261|       |         std::memcpy(&in, other, 7);
  262|       |         if constexpr (std::endian::native == std::endian::big) {
  263|       |            in = std::byteswap(in);
  264|       |         }
  265|       |         return (in == packed);
  266|       |      }
  267|       |      else if constexpr (N == 6) {
  268|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  269|       |         uint64_t in{};
  270|       |         std::memcpy(&in, other, 6);
  271|       |         if constexpr (std::endian::native == std::endian::big) {
  272|       |            in = std::byteswap(in);
  273|       |         }
  274|       |         return (in == packed);
  275|       |      }
  276|       |      else if constexpr (N == 5) {
  277|       |         static constexpr auto packed = pack<Str, 4>();
  278|       |         uint32_t in;
  279|       |         std::memcpy(&in, other, 4);
  280|       |         if constexpr (std::endian::native == std::endian::big) {
  281|       |            in = std::byteswap(in);
  282|       |         }
  283|       |         return (in == packed) & (Str[4] == other[4]);
  284|       |      }
  285|    588|      else if constexpr (N == 4) {
  286|    588|         static constexpr auto packed = pack<Str, 4>();
  287|    588|         uint32_t in;
  288|    588|         std::memcpy(&in, other, 4);
  289|       |         if constexpr (std::endian::native == std::endian::big) {
  290|       |            in = std::byteswap(in);
  291|       |         }
  292|    588|         return (in == packed);
  293|       |      }
  294|       |      else if constexpr (N == 3) {
  295|       |         static constexpr auto packed = pack<Str, 2>();
  296|       |         uint16_t in;
  297|       |         std::memcpy(&in, other, 2);
  298|       |         if constexpr (std::endian::native == std::endian::big) {
  299|       |            in = std::byteswap(in);
  300|       |         }
  301|       |         return (in == packed) & (Str[2] == other[2]);
  302|       |      }
  303|       |      else if constexpr (N == 2) {
  304|       |         static constexpr auto packed = pack<Str, 2>();
  305|       |         uint16_t in;
  306|       |         std::memcpy(&in, other, 2);
  307|       |         if constexpr (std::endian::native == std::endian::big) {
  308|       |            in = std::byteswap(in);
  309|       |         }
  310|       |         return (in == packed);
  311|       |      }
  312|       |      else if constexpr (N == 1) {
  313|       |         return Str[0] == other[0];
  314|       |      }
  315|       |      else if constexpr (N == 0) {
  316|       |         return true;
  317|       |      }
  318|       |      else {
  319|       |         // Clang and GCC optimize this extremely well for constexpr std::string_view
  320|       |         // Packing data can create more binary on GCC
  321|       |         // The other cases probably aren't needed as compiler explorer shows them optimized equally well as memcmp
  322|       |         return 0 == std::memcmp(Str.data(), other, N);
  323|       |      }
  324|    588|   }
_ZN3glz10comparitorIL_ZZNS_5matchITnNS_14string_literalEXtlNS2_ILm5EEEtlA5_cLc110ELc117ELc108ELc108EEEETnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS9_Qntcl15check_is_paddedT0_EEEvOT1_OT2_T3_E1SELm4EcEEbPKSB_:
  245|    623|   {
  246|       |      // pack() builds values in little-endian order (byte 0 in LSB position).
  247|       |      // On big-endian systems, memcpy produces native (big-endian) values,
  248|       |      // so we need to byteswap to match the packed representation.
  249|       |      if constexpr (N == 8) {
  250|       |         static constexpr auto packed = pack<Str, 8>();
  251|       |         uint64_t in;
  252|       |         std::memcpy(&in, other, 8);
  253|       |         if constexpr (std::endian::native == std::endian::big) {
  254|       |            in = std::byteswap(in);
  255|       |         }
  256|       |         return (in == packed);
  257|       |      }
  258|       |      else if constexpr (N == 7) {
  259|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  260|       |         uint64_t in{};
  261|       |         std::memcpy(&in, other, 7);
  262|       |         if constexpr (std::endian::native == std::endian::big) {
  263|       |            in = std::byteswap(in);
  264|       |         }
  265|       |         return (in == packed);
  266|       |      }
  267|       |      else if constexpr (N == 6) {
  268|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  269|       |         uint64_t in{};
  270|       |         std::memcpy(&in, other, 6);
  271|       |         if constexpr (std::endian::native == std::endian::big) {
  272|       |            in = std::byteswap(in);
  273|       |         }
  274|       |         return (in == packed);
  275|       |      }
  276|       |      else if constexpr (N == 5) {
  277|       |         static constexpr auto packed = pack<Str, 4>();
  278|       |         uint32_t in;
  279|       |         std::memcpy(&in, other, 4);
  280|       |         if constexpr (std::endian::native == std::endian::big) {
  281|       |            in = std::byteswap(in);
  282|       |         }
  283|       |         return (in == packed) & (Str[4] == other[4]);
  284|       |      }
  285|    623|      else if constexpr (N == 4) {
  286|    623|         static constexpr auto packed = pack<Str, 4>();
  287|    623|         uint32_t in;
  288|    623|         std::memcpy(&in, other, 4);
  289|       |         if constexpr (std::endian::native == std::endian::big) {
  290|       |            in = std::byteswap(in);
  291|       |         }
  292|    623|         return (in == packed);
  293|       |      }
  294|       |      else if constexpr (N == 3) {
  295|       |         static constexpr auto packed = pack<Str, 2>();
  296|       |         uint16_t in;
  297|       |         std::memcpy(&in, other, 2);
  298|       |         if constexpr (std::endian::native == std::endian::big) {
  299|       |            in = std::byteswap(in);
  300|       |         }
  301|       |         return (in == packed) & (Str[2] == other[2]);
  302|       |      }
  303|       |      else if constexpr (N == 2) {
  304|       |         static constexpr auto packed = pack<Str, 2>();
  305|       |         uint16_t in;
  306|       |         std::memcpy(&in, other, 2);
  307|       |         if constexpr (std::endian::native == std::endian::big) {
  308|       |            in = std::byteswap(in);
  309|       |         }
  310|       |         return (in == packed);
  311|       |      }
  312|       |      else if constexpr (N == 1) {
  313|       |         return Str[0] == other[0];
  314|       |      }
  315|       |      else if constexpr (N == 0) {
  316|       |         return true;
  317|       |      }
  318|       |      else {
  319|       |         // Clang and GCC optimize this extremely well for constexpr std::string_view
  320|       |         // Packing data can create more binary on GCC
  321|       |         // The other cases probably aren't needed as compiler explorer shows them optimized equally well as memcmp
  322|       |         return 0 == std::memcmp(Str.data(), other, N);
  323|       |      }
  324|    623|   }
_ZN3glz10comparitorIL_ZZNS_5matchITnNS_14string_literalEXtlNS2_ILm5EEEtlA5_cLc110ELc117ELc108ELc108EEEETnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEETkNS_10is_contextERNS_7contextERPKcS9_Qaacl15check_is_paddedT0_ElecldtT_4sizeEL_ZNS_13padding_bytesEEEEvOT1_OT2_T3_E1SELm4EcEEbPKSB_:
  245|    658|   {
  246|       |      // pack() builds values in little-endian order (byte 0 in LSB position).
  247|       |      // On big-endian systems, memcpy produces native (big-endian) values,
  248|       |      // so we need to byteswap to match the packed representation.
  249|       |      if constexpr (N == 8) {
  250|       |         static constexpr auto packed = pack<Str, 8>();
  251|       |         uint64_t in;
  252|       |         std::memcpy(&in, other, 8);
  253|       |         if constexpr (std::endian::native == std::endian::big) {
  254|       |            in = std::byteswap(in);
  255|       |         }
  256|       |         return (in == packed);
  257|       |      }
  258|       |      else if constexpr (N == 7) {
  259|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  260|       |         uint64_t in{};
  261|       |         std::memcpy(&in, other, 7);
  262|       |         if constexpr (std::endian::native == std::endian::big) {
  263|       |            in = std::byteswap(in);
  264|       |         }
  265|       |         return (in == packed);
  266|       |      }
  267|       |      else if constexpr (N == 6) {
  268|       |         static constexpr auto packed = pack_buffered<Str, 8>();
  269|       |         uint64_t in{};
  270|       |         std::memcpy(&in, other, 6);
  271|       |         if constexpr (std::endian::native == std::endian::big) {
  272|       |            in = std::byteswap(in);
  273|       |         }
  274|       |         return (in == packed);
  275|       |      }
  276|       |      else if constexpr (N == 5) {
  277|       |         static constexpr auto packed = pack<Str, 4>();
  278|       |         uint32_t in;
  279|       |         std::memcpy(&in, other, 4);
  280|       |         if constexpr (std::endian::native == std::endian::big) {
  281|       |            in = std::byteswap(in);
  282|       |         }
  283|       |         return (in == packed) & (Str[4] == other[4]);
  284|       |      }
  285|    658|      else if constexpr (N == 4) {
  286|    658|         static constexpr auto packed = pack<Str, 4>();
  287|    658|         uint32_t in;
  288|    658|         std::memcpy(&in, other, 4);
  289|       |         if constexpr (std::endian::native == std::endian::big) {
  290|       |            in = std::byteswap(in);
  291|       |         }
  292|    658|         return (in == packed);
  293|       |      }
  294|       |      else if constexpr (N == 3) {
  295|       |         static constexpr auto packed = pack<Str, 2>();
  296|       |         uint16_t in;
  297|       |         std::memcpy(&in, other, 2);
  298|       |         if constexpr (std::endian::native == std::endian::big) {
  299|       |            in = std::byteswap(in);
  300|       |         }
  301|       |         return (in == packed) & (Str[2] == other[2]);
  302|       |      }
  303|       |      else if constexpr (N == 2) {
  304|       |         static constexpr auto packed = pack<Str, 2>();
  305|       |         uint16_t in;
  306|       |         std::memcpy(&in, other, 2);
  307|       |         if constexpr (std::endian::native == std::endian::big) {
  308|       |            in = std::byteswap(in);
  309|       |         }
  310|       |         return (in == packed);
  311|       |      }
  312|       |      else if constexpr (N == 1) {
  313|       |         return Str[0] == other[0];
  314|       |      }
  315|       |      else if constexpr (N == 0) {
  316|       |         return true;
  317|       |      }
  318|       |      else {
  319|       |         // Clang and GCC optimize this extremely well for constexpr std::string_view
  320|       |         // Packing data can create more binary on GCC
  321|       |         // The other cases probably aren't needed as compiler explorer shows them optimized equally well as memcmp
  322|       |         return 0 == std::memcmp(Str.data(), other, N);
  323|       |      }
  324|    658|   }

_ZN3glz10fast_float4spanIKcEC2Ev:
  438|  13.1M|  constexpr span() : ptr(nullptr), length(0) {}
_ZN3glz10fast_float10is_integerIcEEbT_:
 1481|  12.1k|fastfloat_really_inline constexpr bool is_integer(UC c) noexcept {
 1482|  12.1k|  return !(c > UC('9') || c < UC('0'));
  ------------------
  |  Branch (1482:12): [True: 3, False: 12.1k]
  |  Branch (1482:27): [True: 75, False: 12.0k]
  ------------------
 1483|  12.1k|}
_ZN3glz10fast_float11digit_valueIcEEmT_:
 1489|  36.4M|fastfloat_really_inline constexpr uint64_t digit_value(UC c) noexcept {
 1490|  36.4M|  return uint64_t(uint8_t(c) - uint8_t('0'));
 1491|  36.4M|}
_ZN3glz10fast_float4spanIKcEC2EPS2_m:
  436|  6.61M|  constexpr span(T const *_ptr, size_t _length) : ptr(_ptr), length(_length) {}
_ZN3glz10fast_float26loop_parse_if_eight_digitsERPKcS2_Rm:
 1679|  46.9k|                           uint64_t &i) {
 1680|       |  // optimizes better than parse_if_eight_digits_unrolled() for UC = char.
 1681|  3.16M|  while ((std::distance(p, pend) >= 8) &&
  ------------------
  |  Branch (1681:10): [True: 3.15M, False: 3.20k]
  ------------------
 1682|  3.15M|         is_made_of_eight_digits_fast(read8_to_u64(p))) {
  ------------------
  |  Branch (1682:10): [True: 3.11M, False: 43.7k]
  ------------------
 1683|  3.11M|    i = i * 100000000 +
 1684|  3.11M|        parse_eight_digits_unrolled(read8_to_u64(
 1685|  3.11M|            p)); // in rare cases, this will overflow, but that's ok
 1686|  3.11M|    p += 8;
 1687|  3.11M|  }
 1688|  46.9k|}
_ZN3glz10fast_float28is_made_of_eight_digits_fastEm:
 1597|  3.15M|is_made_of_eight_digits_fast(uint64_t val) noexcept {
 1598|  3.15M|  return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) &
 1599|  3.15M|            0x8080808080808080));
 1600|  3.15M|}
_ZN3glz10fast_float12read8_to_u64IcEEmPKT_:
 1503|  8.14M|read8_to_u64(UC const *chars) {
 1504|  8.14M|  if (cpp20_and_in_constexpr() || !std::is_same<UC, char>::value) {
  ------------------
  |  Branch (1504:7): [Folded, False: 0]
  |  Branch (1504:35): [Folded, False: 0]
  ------------------
 1505|      0|    uint64_t val = 0;
 1506|      0|    for (int i = 0; i < 8; ++i) {
  ------------------
  |  Branch (1506:21): [True: 0, False: 0]
  ------------------
 1507|      0|      val |= uint64_t(uint8_t(*chars)) << (i * 8);
 1508|      0|      ++chars;
 1509|      0|    }
 1510|      0|    return val;
 1511|      0|  }
 1512|  8.14M|  uint64_t val;
 1513|  8.14M|  ::memcpy(&val, chars, sizeof(uint64_t));
 1514|       |#if GLZ_FASTFLOAT_IS_BIG_ENDIAN == 1
 1515|       |  // Need to read as-if the number was in little-endian order.
 1516|       |  val = byteswap(val);
 1517|       |#endif
 1518|  8.14M|  return val;
 1519|  8.14M|}
_ZN3glz10fast_float27parse_eight_digits_unrolledEm:
 1575|  4.99M|parse_eight_digits_unrolled(uint64_t val) {
 1576|  4.99M|  uint64_t const mask = 0x000000FF000000FF;
 1577|  4.99M|  uint64_t const mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
 1578|  4.99M|  uint64_t const mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
 1579|  4.99M|  val -= 0x3030303030303030;
 1580|  4.99M|  val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
 1581|  4.99M|  val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
 1582|  4.99M|  return uint32_t(val);
 1583|  4.99M|}
_ZNK3glz10fast_float4spanIKcE3lenEv:
  440|   186k|  constexpr size_t len() const noexcept { return length; }
_ZN3glz10fast_float19from_chars_advancedIdcEENS0_19from_chars_result_tIT0_EERNS0_22parsed_number_string_tIS3_EERT_:
 4249|  6.56M|from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept {
 4250|       |
 4251|  6.56M|  static_assert(is_supported_float_type<T>::value,
 4252|  6.56M|                "only some floating-point types are supported");
 4253|  6.56M|  static_assert(is_supported_char_type<UC>::value,
 4254|  6.56M|                "only char, wchar_t, char16_t and char32_t are supported");
 4255|       |
 4256|  6.56M|  from_chars_result_t<UC> answer;
 4257|       |
 4258|  6.56M|  answer.ec = std::errc(); // be optimistic
 4259|  6.56M|  answer.ptr = pns.lastmatch;
 4260|       |  // The implementation of the Clinger's fast path is convoluted because
 4261|       |  // we want round-to-nearest in all cases, irrespective of the rounding mode
 4262|       |  // selected on the thread.
 4263|       |  // We proceed optimistically, assuming that detail::rounds_to_nearest()
 4264|       |  // returns true.
 4265|  6.56M|  if (binary_format<T>::min_exponent_fast_path() <= pns.exponent &&
  ------------------
  |  Branch (4265:7): [True: 6.55M, False: 12.7k]
  ------------------
 4266|  6.55M|      pns.exponent <= binary_format<T>::max_exponent_fast_path() &&
  ------------------
  |  Branch (4266:7): [True: 6.52M, False: 31.6k]
  ------------------
 4267|  6.52M|      !pns.too_many_digits) {
  ------------------
  |  Branch (4267:7): [True: 6.48M, False: 37.8k]
  ------------------
 4268|       |    // Unfortunately, the conventional Clinger's fast path is only possible
 4269|       |    // when the system rounds to the nearest float.
 4270|       |    //
 4271|       |    // We expect the next branch to almost always be selected.
 4272|       |    // We could check it first (before the previous branch), but
 4273|       |    // there might be performance advantages at having the check
 4274|       |    // be last.
 4275|  6.48M|    if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
  ------------------
  |  Branch (4275:9): [True: 6.48M, Folded]
  |  Branch (4275:38): [True: 6.48M, False: 0]
  ------------------
 4276|       |      // We have that fegetround() == FE_TONEAREST.
 4277|       |      // Next is Clinger's fast path.
 4278|  6.48M|      if (pns.mantissa <= binary_format<T>::max_mantissa_fast_path()) {
  ------------------
  |  Branch (4278:11): [True: 6.48M, False: 3.08k]
  ------------------
 4279|  6.48M|        value = T(pns.mantissa);
 4280|  6.48M|        if (pns.exponent < 0) {
  ------------------
  |  Branch (4280:13): [True: 6.38k, False: 6.47M]
  ------------------
 4281|  6.38k|          value = value / binary_format<T>::exact_power_of_ten(-pns.exponent);
 4282|  6.47M|        } else {
 4283|  6.47M|          value = value * binary_format<T>::exact_power_of_ten(pns.exponent);
 4284|  6.47M|        }
 4285|  6.48M|        if (pns.negative) {
  ------------------
  |  Branch (4285:13): [True: 8.44k, False: 6.47M]
  ------------------
 4286|  8.44k|          value = -value;
 4287|  8.44k|        }
 4288|  6.48M|        return answer;
 4289|  6.48M|      }
 4290|  6.48M|    } else {
 4291|       |      // We do not have that fegetround() == FE_TONEAREST.
 4292|       |      // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's
 4293|       |      // proposal
 4294|      0|      if (pns.exponent >= 0 &&
  ------------------
  |  Branch (4294:11): [True: 0, False: 0]
  ------------------
 4295|      0|          pns.mantissa <=
  ------------------
  |  Branch (4295:11): [True: 0, False: 0]
  ------------------
 4296|      0|              binary_format<T>::max_mantissa_fast_path(pns.exponent)) {
 4297|      0|#if defined(__clang__) || defined(GLZ_FASTFLOAT_32BIT)
 4298|       |        // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD
 4299|      0|        if (pns.mantissa == 0) {
  ------------------
  |  Branch (4299:13): [True: 0, False: 0]
  ------------------
 4300|      0|          value = pns.negative ? T(-0.) : T(0.);
  ------------------
  |  Branch (4300:19): [True: 0, False: 0]
  ------------------
 4301|      0|          return answer;
 4302|      0|        }
 4303|      0|#endif
 4304|      0|        value = T(pns.mantissa) *
 4305|      0|                binary_format<T>::exact_power_of_ten(pns.exponent);
 4306|      0|        if (pns.negative) {
  ------------------
  |  Branch (4306:13): [True: 0, False: 0]
  ------------------
 4307|      0|          value = -value;
 4308|      0|        }
 4309|      0|        return answer;
 4310|      0|      }
 4311|      0|    }
 4312|  6.48M|  }
 4313|  85.2k|  adjusted_mantissa am =
 4314|  85.2k|      compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
 4315|  85.2k|  if (pns.too_many_digits && am.power2 >= 0) {
  ------------------
  |  Branch (4315:7): [True: 69.1k, False: 16.0k]
  |  Branch (4315:30): [True: 69.1k, False: 0]
  ------------------
 4316|  69.1k|    if (am != compute_float<binary_format<T>>(pns.exponent, pns.mantissa + 1)) {
  ------------------
  |  Branch (4316:9): [True: 58.5k, False: 10.5k]
  ------------------
 4317|  58.5k|      am = compute_error<binary_format<T>>(pns.exponent, pns.mantissa);
 4318|  58.5k|    }
 4319|  69.1k|  }
 4320|       |  // If we called compute_float<binary_format<T>>(pns.exponent, pns.mantissa)
 4321|       |  // and we have an invalid power (am.power2 < 0), then we need to go the long
 4322|       |  // way around again. This is very uncommon.
 4323|  85.2k|  if (am.power2 < 0) {
  ------------------
  |  Branch (4323:7): [True: 58.5k, False: 26.6k]
  ------------------
 4324|  58.5k|    am = digit_comp<T>(pns, am);
 4325|  58.5k|  }
 4326|  85.2k|  to_float(pns.negative, am, value);
 4327|       |  // Test for over/underflow.
 4328|  85.2k|  if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) ||
  ------------------
  |  Branch (4328:8): [True: 84.0k, False: 1.16k]
  |  Branch (4328:29): [True: 7.11k, False: 76.9k]
  |  Branch (4328:49): [True: 264, False: 6.85k]
  ------------------
 4329|  84.9k|      am.power2 == binary_format<T>::infinite_power()) {
  ------------------
  |  Branch (4329:7): [True: 387, False: 84.5k]
  ------------------
 4330|    651|    answer.ec = std::errc::result_out_of_range;
 4331|    651|  }
 4332|  85.2k|  return answer;
 4333|  6.56M|}
_ZN3glz10fast_float13binary_formatIdE22min_exponent_fast_pathEv:
  695|  6.56M|inline constexpr int binary_format<double>::min_exponent_fast_path() {
  696|       |#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
  697|       |  return 0;
  698|       |#else
  699|  6.56M|  return -22;
  700|  6.56M|#endif
  701|  6.56M|}
_ZN3glz10fast_float13binary_formatIdE22max_exponent_fast_pathEv:
  767|  6.55M|inline constexpr int binary_format<double>::max_exponent_fast_path() {
  768|  6.55M|  return 22;
  769|  6.55M|}
_ZN3glz10fast_float6detail17rounds_to_nearestEv:
 4129|  6.48M|fastfloat_really_inline bool rounds_to_nearest() noexcept {
 4130|       |  // https://lemire.me/blog/2020/06/26/gcc-not-nearest/
 4131|       |#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
 4132|       |  return false;
 4133|       |#endif
 4134|       |  // See
 4135|       |  // A fast function to check your floating-point rounding mode
 4136|       |  // https://lemire.me/blog/2022/11/16/a-fast-function-to-check-your-floating-point-rounding-mode/
 4137|       |  //
 4138|       |  // This function is meant to be equivalent to :
 4139|       |  // prior: #include <cfenv>
 4140|       |  //  return fegetround() == FE_TONEAREST;
 4141|       |  // However, it is expected to be much faster than the fegetround()
 4142|       |  // function call.
 4143|       |  //
 4144|       |  // The volatile keyword prevents the compiler from computing the function
 4145|       |  // at compile-time.
 4146|       |  // There might be other ways to prevent compile-time optimizations (e.g.,
 4147|       |  // asm). The value does not need to be std::numeric_limits<float>::min(), any
 4148|       |  // small value so that 1 + x should round to 1 would do (after accounting for
 4149|       |  // excess precision, as in 387 instructions).
 4150|  6.48M|  static float volatile fmin = (std::numeric_limits<float>::min)();
 4151|  6.48M|  float fmini = fmin; // we copy it so that it gets loaded at most once.
 4152|       |//
 4153|       |// Explanation:
 4154|       |// Only when fegetround() == FE_TONEAREST do we have that
 4155|       |// fmin + 1.0f == 1.0f - fmin.
 4156|       |//
 4157|       |// FE_UPWARD:
 4158|       |//  fmin + 1.0f > 1
 4159|       |//  1.0f - fmin == 1
 4160|       |//
 4161|       |// FE_DOWNWARD or  FE_TOWARDZERO:
 4162|       |//  fmin + 1.0f == 1
 4163|       |//  1.0f - fmin < 1
 4164|       |//
 4165|       |// Note: This may fail to be accurate if fast-math has been
 4166|       |// enabled, as rounding conventions may not apply.
 4167|       |#ifdef GLZ_FASTFLOAT_VISUAL_STUDIO
 4168|       |#pragma warning(push)
 4169|       |//  todo: is there a VS warning?
 4170|       |//  see
 4171|       |//  https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013
 4172|       |#elif defined(__clang__)
 4173|       |#pragma clang diagnostic push
 4174|  6.48M|#pragma clang diagnostic ignored "-Wfloat-equal"
 4175|       |#elif defined(__GNUC__)
 4176|       |#pragma GCC diagnostic push
 4177|       |#pragma GCC diagnostic ignored "-Wfloat-equal"
 4178|       |#endif
 4179|  6.48M|  return (fmini + 1.0f == 1.0f - fmini);
 4180|       |#ifdef GLZ_FASTFLOAT_VISUAL_STUDIO
 4181|       |#pragma warning(pop)
 4182|       |#elif defined(__clang__)
 4183|       |#pragma clang diagnostic pop
 4184|       |#elif defined(__GNUC__)
 4185|       |#pragma GCC diagnostic pop
 4186|       |#endif
 4187|  6.48M|}
_ZN3glz10fast_float13binary_formatIdE22max_mantissa_fast_pathEv:
  777|  6.48M|inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() {
  778|  6.48M|  return uint64_t(2) << mantissa_explicit_bits();
  779|  6.48M|}
_ZN3glz10fast_float13binary_formatIdE22mantissa_explicit_bitsEv:
  713|  7.51M|inline constexpr int binary_format<double>::mantissa_explicit_bits() {
  714|  7.51M|  return 52;
  715|  7.51M|}
_ZN3glz10fast_float13binary_formatIdE18exact_power_of_tenEl:
 1057|  6.48M|binary_format<double>::exact_power_of_ten(int64_t power) {
 1058|       |  // Work around clang bug https://godbolt.org/z/zedh7rrhc
 1059|  6.48M|  return (void)powers_of_ten[0], powers_of_ten[power];
 1060|  6.48M|}
_ZN3glz10fast_float13compute_floatINS0_13binary_formatIdEEEENS0_17adjusted_mantissaElm:
 2852|   154k|compute_float(int64_t q, uint64_t w) noexcept {
 2853|   154k|  adjusted_mantissa answer;
 2854|   154k|  if ((w == 0) || (q < binary::smallest_power_of_ten())) {
  ------------------
  |  Branch (2854:7): [True: 1.16k, False: 153k]
  |  Branch (2854:19): [True: 303, False: 152k]
  ------------------
 2855|  1.46k|    answer.power2 = 0;
 2856|  1.46k|    answer.mantissa = 0;
 2857|       |    // result should be zero
 2858|  1.46k|    return answer;
 2859|  1.46k|  }
 2860|   152k|  if (q > binary::largest_power_of_ten()) {
  ------------------
  |  Branch (2860:7): [True: 462, False: 152k]
  ------------------
 2861|       |    // we want to get infinity:
 2862|    462|    answer.power2 = binary::infinite_power();
 2863|    462|    answer.mantissa = 0;
 2864|    462|    return answer;
 2865|    462|  }
 2866|       |  // At this point in time q is in [powers::smallest_power_of_five,
 2867|       |  // powers::largest_power_of_five].
 2868|       |
 2869|       |  // We want the most significant bit of i to be 1. Shift if needed.
 2870|   152k|  int lz = leading_zeroes(w);
 2871|   152k|  w <<= lz;
 2872|       |
 2873|       |  // The required precision is binary::mantissa_explicit_bits() + 3 because
 2874|       |  // 1. We need the implicit bit
 2875|       |  // 2. We need an extra bit for rounding purposes
 2876|       |  // 3. We might lose a bit due to the "upperbit" routine (result too small,
 2877|       |  // requiring a shift)
 2878|       |
 2879|   152k|  value128 product =
 2880|   152k|      compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
 2881|       |  // The computed 'product' is always sufficient.
 2882|       |  // Mathematical proof:
 2883|       |  // Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to
 2884|       |  // appear) See script/mushtak_lemire.py
 2885|       |
 2886|       |  // The "compute_product_approximation" function can be slightly slower than a
 2887|       |  // branchless approach: value128 product = compute_product(q, w); but in
 2888|       |  // practice, we can win big with the compute_product_approximation if its
 2889|       |  // additional branch is easily predicted. Which is best is data specific.
 2890|   152k|  int upperbit = int(product.high >> 63);
 2891|   152k|  int shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3;
 2892|       |
 2893|   152k|  answer.mantissa = product.high >> shift;
 2894|       |
 2895|   152k|  answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz -
 2896|   152k|                          binary::minimum_exponent());
 2897|   152k|  if (answer.power2 <= 0) { // we have a subnormal?
  ------------------
  |  Branch (2897:7): [True: 11.1k, False: 141k]
  ------------------
 2898|       |    // Here have that answer.power2 <= 0 so -answer.power2 >= 0
 2899|  11.1k|    if (-answer.power2 + 1 >=
  ------------------
  |  Branch (2899:9): [True: 6, False: 11.1k]
  ------------------
 2900|  11.1k|        64) { // if we have more than 64 bits below the minimum exponent, you
 2901|       |              // have a zero for sure.
 2902|      6|      answer.power2 = 0;
 2903|      6|      answer.mantissa = 0;
 2904|       |      // result should be zero
 2905|      6|      return answer;
 2906|      6|    }
 2907|       |    // next line is safe because -answer.power2 + 1 < 64
 2908|  11.1k|    answer.mantissa >>= -answer.power2 + 1;
 2909|       |    // Thankfully, we can't have both "round-to-even" and subnormals because
 2910|       |    // "round-to-even" only occurs for powers close to 0 in the 32-bit and
 2911|       |    // and 64-bit case (with no more than 19 digits).
 2912|  11.1k|    answer.mantissa += (answer.mantissa & 1); // round up
 2913|  11.1k|    answer.mantissa >>= 1;
 2914|       |    // There is a weird scenario where we don't have a subnormal but just.
 2915|       |    // Suppose we start with 2.2250738585072013e-308, we end up
 2916|       |    // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal
 2917|       |    // whereas 0x40000000000000 x 2^-1023-53  is normal. Now, we need to round
 2918|       |    // up 0x3fffffffffffff x 2^-1023-53  and once we do, we are no longer
 2919|       |    // subnormal, but we can only know this after rounding.
 2920|       |    // So we only declare a subnormal if we are smaller than the threshold.
 2921|  11.1k|    answer.power2 =
 2922|  11.1k|        (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits()))
  ------------------
  |  Branch (2922:9): [True: 11.1k, False: 9]
  ------------------
 2923|  11.1k|            ? 0
 2924|  11.1k|            : 1;
 2925|  11.1k|    return answer;
 2926|  11.1k|  }
 2927|       |
 2928|       |  // usually, we round *up*, but if we fall right in between and and we have an
 2929|       |  // even basis, we need to round down
 2930|       |  // We are only concerned with the cases where 5**q fits in single 64-bit word.
 2931|   141k|  if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) &&
  ------------------
  |  Branch (2931:7): [True: 34.1k, False: 107k]
  |  Branch (2931:29): [True: 31.3k, False: 2.78k]
  ------------------
 2932|  31.3k|      (q <= binary::max_exponent_round_to_even()) &&
  ------------------
  |  Branch (2932:7): [True: 29.1k, False: 2.14k]
  ------------------
 2933|  29.1k|      ((answer.mantissa & 3) == 1)) { // we may fall between two floats!
  ------------------
  |  Branch (2933:7): [True: 15.2k, False: 13.9k]
  ------------------
 2934|       |    // To be in-between two floats we need that in doing
 2935|       |    //   answer.mantissa = product.high >> (upperbit + 64 -
 2936|       |    //   binary::mantissa_explicit_bits() - 3);
 2937|       |    // ... we dropped out only zeroes. But if this happened, then we can go
 2938|       |    // back!!!
 2939|  15.2k|    if ((answer.mantissa << shift) == product.high) {
  ------------------
  |  Branch (2939:9): [True: 11.1k, False: 4.08k]
  ------------------
 2940|  11.1k|      answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up
 2941|  11.1k|    }
 2942|  15.2k|  }
 2943|       |
 2944|   141k|  answer.mantissa += (answer.mantissa & 1); // round up
 2945|   141k|  answer.mantissa >>= 1;
 2946|   141k|  if (answer.mantissa >= (uint64_t(2) << binary::mantissa_explicit_bits())) {
  ------------------
  |  Branch (2946:7): [True: 6.41k, False: 134k]
  ------------------
 2947|  6.41k|    answer.mantissa = (uint64_t(1) << binary::mantissa_explicit_bits());
 2948|  6.41k|    answer.power2++; // undo previous addition
 2949|  6.41k|  }
 2950|       |
 2951|   141k|  answer.mantissa &= ~(uint64_t(1) << binary::mantissa_explicit_bits());
 2952|   141k|  if (answer.power2 >= binary::infinite_power()) { // infinity
  ------------------
  |  Branch (2952:7): [True: 39, False: 141k]
  ------------------
 2953|     39|    answer.power2 = binary::infinite_power();
 2954|     39|    answer.mantissa = 0;
 2955|     39|  }
 2956|   141k|  return answer;
 2957|   152k|}
_ZN3glz10fast_float17adjusted_mantissaC2Ev:
  568|   271k|  adjusted_mantissa() = default;
_ZN3glz10fast_float13binary_formatIdE21smallest_power_of_tenEv:
 1077|   153k|inline constexpr int binary_format<double>::smallest_power_of_ten() {
 1078|   153k|  return -342;
 1079|   153k|}
_ZN3glz10fast_float13binary_formatIdE20largest_power_of_tenEv:
 1068|   152k|template <> inline constexpr int binary_format<double>::largest_power_of_ten() {
 1069|   152k|  return 308;
 1070|   152k|}
_ZN3glz10fast_float14leading_zeroesEm:
  488|   245k|leading_zeroes(uint64_t input_num) {
  489|   245k|  assert(input_num > 0);
  ------------------
  |  Branch (489:3): [True: 245k, False: 0]
  ------------------
  490|   245k|  if (cpp20_and_in_constexpr()) {
  ------------------
  |  Branch (490:7): [Folded, False: 245k]
  ------------------
  491|      0|    return leading_zeroes_generic(input_num);
  492|      0|  }
  493|       |#ifdef GLZ_FASTFLOAT_VISUAL_STUDIO
  494|       |#if defined(_M_X64) || defined(_M_ARM64)
  495|       |  unsigned long leading_zero = 0;
  496|       |  // Search the mask data from most significant bit (MSB)
  497|       |  // to least significant bit (LSB) for a set bit (1).
  498|       |  _BitScanReverse64(&leading_zero, input_num);
  499|       |  return (int)(63 - leading_zero);
  500|       |#else
  501|       |  return leading_zeroes_generic(input_num);
  502|       |#endif
  503|       |#else
  504|   245k|  return __builtin_clzll(input_num);
  505|   245k|#endif
  506|   245k|}
_ZN3glz10fast_float29compute_product_approximationILi55EEENS0_8value128Elm:
 2771|   211k|compute_product_approximation(int64_t q, uint64_t w) {
 2772|   211k|  int const index = 2 * int(q - powers::smallest_power_of_five);
 2773|       |  // For small values of q, e.g., q in [0,27], the answer is always exact
 2774|       |  // because The line value128 firstproduct = full_multiplication(w,
 2775|       |  // power_of_five_128[index]); gives the exact answer.
 2776|   211k|  value128 firstproduct =
 2777|   211k|      full_multiplication(w, powers::power_of_five_128[index]);
 2778|   211k|  static_assert((bit_precision >= 0) && (bit_precision <= 64),
 2779|   211k|                " precision should  be in (0,64]");
 2780|   211k|  constexpr uint64_t precision_mask =
 2781|   211k|      (bit_precision < 64) ? (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision)
  ------------------
  |  Branch (2781:7): [True: 0, Folded]
  ------------------
 2782|   211k|                           : uint64_t(0xFFFFFFFFFFFFFFFF);
 2783|   211k|  if ((firstproduct.high & precision_mask) ==
  ------------------
  |  Branch (2783:7): [True: 48.2k, False: 162k]
  ------------------
 2784|   211k|      precision_mask) { // could further guard with  (lower + w < lower)
 2785|       |    // regarding the second product, we only need secondproduct.high, but our
 2786|       |    // expectation is that the compiler will optimize this extra work away if
 2787|       |    // needed.
 2788|  48.2k|    value128 secondproduct =
 2789|  48.2k|        full_multiplication(w, powers::power_of_five_128[index + 1]);
 2790|  48.2k|    firstproduct.low += secondproduct.high;
 2791|  48.2k|    if (secondproduct.high > firstproduct.low) {
  ------------------
  |  Branch (2791:9): [True: 12.3k, False: 35.9k]
  ------------------
 2792|  12.3k|      firstproduct.high++;
 2793|  12.3k|    }
 2794|  48.2k|  }
 2795|   211k|  return firstproduct;
 2796|   211k|}
_ZN3glz10fast_float19full_multiplicationEmm:
  540|   259k|full_multiplication(uint64_t a, uint64_t b) {
  541|   259k|  if (cpp20_and_in_constexpr()) {
  ------------------
  |  Branch (541:7): [Folded, False: 259k]
  ------------------
  542|      0|    value128 answer;
  543|      0|    answer.low = umul128_generic(a, b, &answer.high);
  544|      0|    return answer;
  545|      0|  }
  546|   259k|  value128 answer;
  547|       |#if defined(_M_ARM64) && !defined(__MINGW32__)
  548|       |  // ARM64 has native support for 64-bit multiplications, no need to emulate
  549|       |  // But MinGW on ARM64 doesn't have native support for 64-bit multiplications
  550|       |  answer.high = __umulh(a, b);
  551|       |  answer.low = a * b;
  552|       |#elif defined(GLZ_FASTFLOAT_32BIT) ||                                              \
  553|       |    (defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64))
  554|       |  answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64
  555|       |#elif defined(GLZ_FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__)
  556|       |  __uint128_t r = ((__uint128_t)a) * b;
  557|   259k|  answer.low = uint64_t(r);
  558|   259k|  answer.high = uint64_t(r >> 64);
  559|       |#else
  560|       |  answer.low = umul128_generic(a, b, &answer.high);
  561|       |#endif
  562|   259k|  return answer;
  563|   259k|}
_ZN3glz10fast_float8value128C2Ev:
  454|   259k|  constexpr value128() : low(0), high(0) {}
_ZN3glz10fast_float6detail5powerEi:
 2814|   211k|constexpr fastfloat_really_inline int32_t power(int32_t q) noexcept {
 2815|   211k|  return (((152170 + 65536) * q) >> 16) + 63;
 2816|   211k|}
_ZN3glz10fast_float13binary_formatIdE16minimum_exponentEv:
  742|   269k|template <> inline constexpr int binary_format<double>::minimum_exponent() {
  743|   269k|  return -1023;
  744|   269k|}
_ZN3glz10fast_float13binary_formatIdE26min_exponent_round_to_evenEv:
  733|  34.1k|inline constexpr int binary_format<double>::min_exponent_round_to_even() {
  734|  34.1k|  return -4;
  735|  34.1k|}
_ZN3glz10fast_float13binary_formatIdE26max_exponent_round_to_evenEv:
  723|  31.3k|inline constexpr int binary_format<double>::max_exponent_round_to_even() {
  724|  31.3k|  return 23;
  725|  31.3k|}
_ZNK3glz10fast_float17adjusted_mantissaneERKS1_:
  574|  69.1k|  constexpr bool operator!=(adjusted_mantissa const &o) const {
  575|  69.1k|    return mantissa != o.mantissa || power2 != o.power2;
  ------------------
  |  Branch (575:12): [True: 58.5k, False: 10.5k]
  |  Branch (575:38): [True: 0, False: 10.5k]
  ------------------
  576|  69.1k|  }
_ZN3glz10fast_float13compute_errorINS0_13binary_formatIdEEEENS0_17adjusted_mantissaElm:
 2837|  58.5k|compute_error(int64_t q, uint64_t w) noexcept {
 2838|  58.5k|  int lz = leading_zeroes(w);
 2839|  58.5k|  w <<= lz;
 2840|  58.5k|  value128 product =
 2841|  58.5k|      compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
 2842|  58.5k|  return compute_error_scaled<binary>(q, product.high, lz);
 2843|  58.5k|}
_ZN3glz10fast_float20compute_error_scaledINS0_13binary_formatIdEEEENS0_17adjusted_mantissaElmi:
 2823|  58.5k|compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept {
 2824|  58.5k|  int hilz = int(w >> 63) ^ 1;
 2825|  58.5k|  adjusted_mantissa answer;
 2826|  58.5k|  answer.mantissa = w << hilz;
 2827|  58.5k|  int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent();
 2828|  58.5k|  answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 +
 2829|  58.5k|                          invalid_am_bias);
 2830|  58.5k|  return answer;
 2831|  58.5k|}
_ZN3glz10fast_float10digit_compIdcEENS0_17adjusted_mantissaERNS0_22parsed_number_string_tIT0_EES2_:
 4034|  58.5k|digit_comp(parsed_number_string_t<UC> &num, adjusted_mantissa am) noexcept {
 4035|       |  // remove the invalid exponent bias
 4036|  58.5k|  am.power2 -= invalid_am_bias;
 4037|       |
 4038|  58.5k|  int32_t sci_exp = scientific_exponent(num);
 4039|  58.5k|  size_t max_digits = binary_format<T>::max_digits();
 4040|  58.5k|  size_t digits = 0;
 4041|  58.5k|  bigint bigmant;
 4042|  58.5k|  parse_mantissa(bigmant, num, max_digits, digits);
 4043|       |  // can't underflow, since digits is at most max_digits.
 4044|  58.5k|  int32_t exponent = sci_exp + 1 - int32_t(digits);
 4045|  58.5k|  if (exponent >= 0) {
  ------------------
  |  Branch (4045:7): [True: 17.4k, False: 41.1k]
  ------------------
 4046|  17.4k|    return positive_digit_comp<T>(bigmant, exponent);
 4047|  41.1k|  } else {
 4048|  41.1k|    return negative_digit_comp<T>(bigmant, am, exponent);
 4049|  41.1k|  }
 4050|  58.5k|}
_ZN3glz10fast_float19scientific_exponentIcEEiRNS0_22parsed_number_string_tIT_EE:
 3640|  58.5k|scientific_exponent(parsed_number_string_t<UC> &num) noexcept {
 3641|  58.5k|  uint64_t mantissa = num.mantissa;
 3642|  58.5k|  int32_t exponent = int32_t(num.exponent);
 3643|   292k|  while (mantissa >= 10000) {
  ------------------
  |  Branch (3643:10): [True: 234k, False: 58.5k]
  ------------------
 3644|   234k|    mantissa /= 10000;
 3645|   234k|    exponent += 4;
 3646|   234k|  }
 3647|   117k|  while (mantissa >= 100) {
  ------------------
  |  Branch (3647:10): [True: 58.5k, False: 58.5k]
  ------------------
 3648|  58.5k|    mantissa /= 100;
 3649|  58.5k|    exponent += 2;
 3650|  58.5k|  }
 3651|  58.5k|  while (mantissa >= 10) {
  ------------------
  |  Branch (3651:10): [True: 0, False: 58.5k]
  ------------------
 3652|      0|    mantissa /= 10;
 3653|      0|    exponent += 1;
 3654|      0|  }
 3655|  58.5k|  return exponent;
 3656|  58.5k|}
_ZN3glz10fast_float13binary_formatIdE10max_digitsEv:
 1085|  58.5k|template <> inline constexpr size_t binary_format<double>::max_digits() {
 1086|  58.5k|  return 769;
 1087|  58.5k|}
_ZN3glz10fast_float6bigintC2Ev:
 3399|  58.5k|  GLZ_FASTFLOAT_CONSTEXPR20 bigint() : vec() {}
_ZN3glz10fast_float8stackvecILt62EEC2Ev:
 3006|   580k|  stackvec() = default;
_ZN3glz10fast_float14parse_mantissaIcEEvRNS0_6bigintERNS0_22parsed_number_string_tIT_EEmRm:
 3859|  58.5k|               size_t max_digits, size_t &digits) noexcept {
 3860|       |  // try to minimize the number of big integer and scalar multiplication.
 3861|       |  // therefore, try to parse 8 digits at a time, and multiply by the largest
 3862|       |  // scalar value (9 or 19 digits) for each step.
 3863|  58.5k|  size_t counter = 0;
 3864|  58.5k|  digits = 0;
 3865|  58.5k|  limb value = 0;
 3866|  58.5k|#ifdef GLZ_FASTFLOAT_64BIT_LIMB
 3867|  58.5k|  size_t step = 19;
 3868|       |#else
 3869|       |  size_t step = 9;
 3870|       |#endif
 3871|       |
 3872|       |  // process all integer digits.
 3873|  58.5k|  UC const *p = num.integer.ptr;
 3874|  58.5k|  UC const *pend = p + num.integer.len();
 3875|  58.5k|  skip_zeros(p, pend);
 3876|       |  // process all digits, in increments of step per loop
 3877|   608k|  while (p != pend) {
  ------------------
  |  Branch (3877:10): [True: 562k, False: 46.6k]
  ------------------
 3878|  1.61M|    while ((std::distance(p, pend) >= 8) && (step - counter >= 8) &&
  ------------------
  |  Branch (3878:12): [True: 1.54M, False: 65.1k]
  |  Branch (3878:45): [True: 1.05M, False: 488k]
  ------------------
 3879|  1.05M|           (max_digits - digits >= 8)) {
  ------------------
  |  Branch (3879:12): [True: 1.04M, False: 8.24k]
  ------------------
 3880|  1.04M|      parse_eight_digits(p, value, counter, digits);
 3881|  1.04M|    }
 3882|  2.16M|    while (counter < step && p != pend && digits < max_digits) {
  ------------------
  |  Branch (3882:12): [True: 1.65M, False: 508k]
  |  Branch (3882:30): [True: 1.61M, False: 45.3k]
  |  Branch (3882:43): [True: 1.60M, False: 8.71k]
  ------------------
 3883|  1.60M|      parse_one_digit(p, value, counter, digits);
 3884|  1.60M|    }
 3885|   562k|    if (digits == max_digits) {
  ------------------
  |  Branch (3885:9): [True: 11.9k, False: 550k]
  ------------------
 3886|       |      // add the temporary value, then check if we've truncated any digits
 3887|  11.9k|      add_native(result, limb(powers_of_ten_uint64[counter]), value);
 3888|  11.9k|      bool truncated = is_truncated(p, pend);
 3889|  11.9k|      if (num.fraction.ptr != nullptr) {
  ------------------
  |  Branch (3889:11): [True: 8.91k, False: 3.04k]
  ------------------
 3890|  8.91k|        truncated |= is_truncated(num.fraction);
 3891|  8.91k|      }
 3892|  11.9k|      if (truncated) {
  ------------------
  |  Branch (3892:11): [True: 6.50k, False: 5.46k]
  ------------------
 3893|  6.50k|        round_up_bigint(result, digits);
 3894|  6.50k|      }
 3895|  11.9k|      return;
 3896|   550k|    } else {
 3897|   550k|      add_native(result, limb(powers_of_ten_uint64[counter]), value);
 3898|   550k|      counter = 0;
 3899|   550k|      value = 0;
 3900|   550k|    }
 3901|   562k|  }
 3902|       |
 3903|       |  // add our fraction digits, if they're available.
 3904|  46.6k|  if (num.fraction.ptr != nullptr) {
  ------------------
  |  Branch (3904:7): [True: 26.8k, False: 19.7k]
  ------------------
 3905|  26.8k|    p = num.fraction.ptr;
 3906|  26.8k|    pend = p + num.fraction.len();
 3907|  26.8k|    if (digits == 0) {
  ------------------
  |  Branch (3907:9): [True: 4.42k, False: 22.4k]
  ------------------
 3908|  4.42k|      skip_zeros(p, pend);
 3909|  4.42k|    }
 3910|       |    // process all digits, in increments of step per loop
 3911|   450k|    while (p != pend) {
  ------------------
  |  Branch (3911:12): [True: 433k, False: 17.0k]
  ------------------
 3912|  1.26M|      while ((std::distance(p, pend) >= 8) && (step - counter >= 8) &&
  ------------------
  |  Branch (3912:14): [True: 1.23M, False: 26.1k]
  |  Branch (3912:47): [True: 833k, False: 403k]
  ------------------
 3913|   833k|             (max_digits - digits >= 8)) {
  ------------------
  |  Branch (3913:14): [True: 828k, False: 4.12k]
  ------------------
 3914|   828k|        parse_eight_digits(p, value, counter, digits);
 3915|   828k|      }
 3916|  1.72M|      while (counter < step && p != pend && digits < max_digits) {
  ------------------
  |  Branch (3916:14): [True: 1.31M, False: 410k]
  |  Branch (3916:32): [True: 1.29M, False: 16.2k]
  |  Branch (3916:45): [True: 1.29M, False: 6.63k]
  ------------------
 3917|  1.29M|        parse_one_digit(p, value, counter, digits);
 3918|  1.29M|      }
 3919|   433k|      if (digits == max_digits) {
  ------------------
  |  Branch (3919:11): [True: 9.85k, False: 423k]
  ------------------
 3920|       |        // add the temporary value, then check if we've truncated any digits
 3921|  9.85k|        add_native(result, limb(powers_of_ten_uint64[counter]), value);
 3922|  9.85k|        bool truncated = is_truncated(p, pend);
 3923|  9.85k|        if (truncated) {
  ------------------
  |  Branch (3923:13): [True: 6.23k, False: 3.62k]
  ------------------
 3924|  6.23k|          round_up_bigint(result, digits);
 3925|  6.23k|        }
 3926|  9.85k|        return;
 3927|   423k|      } else {
 3928|   423k|        add_native(result, limb(powers_of_ten_uint64[counter]), value);
 3929|   423k|        counter = 0;
 3930|   423k|        value = 0;
 3931|   423k|      }
 3932|   433k|    }
 3933|  26.8k|  }
 3934|       |
 3935|  36.7k|  if (counter != 0) {
  ------------------
  |  Branch (3935:7): [True: 0, False: 36.7k]
  ------------------
 3936|      0|    add_native(result, limb(powers_of_ten_uint64[counter]), value);
 3937|      0|  }
 3938|  36.7k|}
_ZN3glz10fast_float10skip_zerosIcEEvRPKT_S4_:
 3773|  63.0k|skip_zeros(UC const *&first, UC const *last) noexcept {
 3774|  63.0k|  uint64_t val;
 3775|  64.2k|  while (!cpp20_and_in_constexpr() &&
  ------------------
  |  Branch (3775:10): [True: 64.2k, Folded]
  ------------------
 3776|  64.2k|         std::distance(first, last) >= int_cmp_len<UC>()) {
  ------------------
  |  Branch (3776:10): [True: 52.8k, False: 11.3k]
  ------------------
 3777|  52.8k|    ::memcpy(&val, first, sizeof(uint64_t));
 3778|  52.8k|    if (val != int_cmp_zeros<UC>()) {
  ------------------
  |  Branch (3778:9): [True: 51.6k, False: 1.19k]
  ------------------
 3779|  51.6k|      break;
 3780|  51.6k|    }
 3781|  1.19k|    first += int_cmp_len<UC>();
 3782|  1.19k|  }
 3783|  73.6k|  while (first != last) {
  ------------------
  |  Branch (3783:10): [True: 69.2k, False: 4.42k]
  ------------------
 3784|  69.2k|    if (*first != UC('0')) {
  ------------------
  |  Branch (3784:9): [True: 58.5k, False: 10.6k]
  ------------------
 3785|  58.5k|      break;
 3786|  58.5k|    }
 3787|  10.6k|    first++;
 3788|  10.6k|  }
 3789|  63.0k|}
_ZN3glz10fast_float11int_cmp_lenIcEEiv:
 1180|   246k|template <typename UC> constexpr int int_cmp_len() {
 1181|   246k|  return sizeof(uint64_t) / sizeof(UC);
 1182|   246k|}
_ZN3glz10fast_float13int_cmp_zerosIcEEmv:
 1170|   132k|template <typename UC> constexpr uint64_t int_cmp_zeros() {
 1171|   132k|  static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4),
 1172|   132k|                "Unsupported character size");
 1173|   132k|  return (sizeof(UC) == 1) ? 0x3030303030303030
  ------------------
  |  Branch (1173:10): [True: 132k, Folded]
  ------------------
 1174|   132k|         : (sizeof(UC) == 2)
  ------------------
  |  Branch (1174:12): [Folded, False: 0]
  ------------------
 1175|      0|             ? (uint64_t(UC('0')) << 48 | uint64_t(UC('0')) << 32 |
 1176|      0|                uint64_t(UC('0')) << 16 | UC('0'))
 1177|      0|             : (uint64_t(UC('0')) << 32 | UC('0'));
 1178|   132k|}
_ZN3glz10fast_float18parse_eight_digitsIcEEvRPKT_RmS6_S6_:
 3824|  1.87M|                   size_t &count) noexcept {
 3825|  1.87M|  value = value * 100000000 + parse_eight_digits_unrolled(p);
 3826|  1.87M|  p += 8;
 3827|  1.87M|  counter += 8;
 3828|  1.87M|  count += 8;
 3829|  1.87M|}
_ZN3glz10fast_float27parse_eight_digits_unrolledIcEEjPKT_:
 1588|  1.87M|parse_eight_digits_unrolled(UC const *chars) noexcept {
 1589|  1.87M|  if (cpp20_and_in_constexpr() || !has_simd_opt<UC>()) {
  ------------------
  |  Branch (1589:7): [Folded, False: 0]
  |  Branch (1589:35): [True: 0, Folded]
  ------------------
 1590|  1.87M|    return parse_eight_digits_unrolled(read8_to_u64(chars)); // truncation okay
 1591|  1.87M|  }
 1592|      0|  return parse_eight_digits_unrolled(simd_read8_to_u64(chars));
 1593|  1.87M|}
_ZN3glz10fast_float15parse_one_digitIcEEvRPKT_RmS6_S6_:
 3834|  2.89M|                size_t &count) noexcept {
 3835|  2.89M|  value = value * 10 + limb(*p - UC('0'));
 3836|  2.89M|  p++;
 3837|  2.89M|  counter++;
 3838|  2.89M|  count++;
 3839|  2.89M|}
_ZN3glz10fast_float10add_nativeERNS0_6bigintEmm:
 3842|  1.00M|add_native(bigint &big, limb power, limb value) noexcept {
 3843|  1.00M|  big.mul(power);
 3844|  1.00M|  big.add(value);
 3845|  1.00M|}
_ZN3glz10fast_float6bigint3mulEm:
 3552|  1.00M|  GLZ_FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept { return small_mul(vec, y); }
_ZN3glz10fast_float9small_mulILt62EEEbRNS0_8stackvecIXT_EEEm:
 3249|  1.72M|                                            limb y) noexcept {
 3250|  1.72M|  limb carry = 0;
 3251|  28.2M|  for (size_t index = 0; index < vec.len(); index++) {
  ------------------
  |  Branch (3251:26): [True: 26.5M, False: 1.72M]
  ------------------
 3252|  26.5M|    vec[index] = scalar_mul(vec[index], y, carry);
 3253|  26.5M|  }
 3254|  1.72M|  if (carry != 0) {
  ------------------
  |  Branch (3254:7): [True: 1.55M, False: 172k]
  ------------------
 3255|  1.55M|    GLZ_FASTFLOAT_TRY(vec.try_push(carry));
  ------------------
  |  |  354|  1.55M|  {                                                                            \
  |  |  355|  1.55M|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 1.55M]
  |  |  ------------------
  |  |  356|  1.55M|      return false;                                                            \
  |  |  357|  1.55M|  }
  ------------------
 3256|  1.55M|  }
 3257|  1.72M|  return true;
 3258|  1.72M|}
_ZNK3glz10fast_float8stackvecILt62EE3lenEv:
 3039|  35.8M|  constexpr size_t len() const noexcept { return length; }
_ZN3glz10fast_float10scalar_mulEmmRm:
 3196|  26.5M|scalar_mul(limb x, limb y, limb &carry) noexcept {
 3197|  26.5M|#ifdef GLZ_FASTFLOAT_64BIT_LIMB
 3198|  26.5M|#if defined(__SIZEOF_INT128__)
 3199|       |  // GCC and clang both define it as an extension.
 3200|  26.5M|  __uint128_t z = __uint128_t(x) * __uint128_t(y) + __uint128_t(carry);
 3201|  26.5M|  carry = limb(z >> limb_bits);
 3202|  26.5M|  return limb(z);
 3203|       |#else
 3204|       |  // fallback, no native 128-bit integer multiplication with carry.
 3205|       |  // on msvc, this optimizes identically, somehow.
 3206|       |  value128 z = full_multiplication(x, y);
 3207|       |  bool overflow;
 3208|       |  z.low = scalar_add(z.low, carry, overflow);
 3209|       |  z.high += uint64_t(overflow); // cannot overflow
 3210|       |  carry = z.high;
 3211|       |  return z.low;
 3212|       |#endif
 3213|       |#else
 3214|       |  uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry);
 3215|       |  carry = limb(z >> limb_bits);
 3216|       |  return limb(z);
 3217|       |#endif
 3218|  26.5M|}
_ZN3glz10fast_float8stackvecILt62EEixEm:
 3017|  65.4M|  GLZ_FASTFLOAT_CONSTEXPR14 limb &operator[](size_t index) noexcept {
 3018|  65.4M|    GLZ_FASTFLOAT_DEBUG_ASSERT(index < length);
  ------------------
  |  |  349|  65.4M|  { ((void)(x)); }
  ------------------
 3019|  65.4M|    return data[index];
 3020|  65.4M|  }
_ZN3glz10fast_float8stackvecILt62EE8try_pushEm:
 3052|  1.62M|  GLZ_FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept {
 3053|  1.62M|    if (len() < capacity()) {
  ------------------
  |  Branch (3053:9): [True: 1.62M, False: 0]
  ------------------
 3054|  1.62M|      push_unchecked(value);
 3055|  1.62M|      return true;
 3056|  1.62M|    } else {
 3057|      0|      return false;
 3058|      0|    }
 3059|  1.62M|  }
_ZNK3glz10fast_float8stackvecILt62EE8capacityEv:
 3043|  2.74M|  constexpr size_t capacity() const noexcept { return size; }
_ZN3glz10fast_float8stackvecILt62EE14push_uncheckedEm:
 3046|  1.67M|  GLZ_FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept {
 3047|  1.67M|    data[length] = value;
 3048|  1.67M|    length++;
 3049|  1.67M|  }
_ZN3glz10fast_float6bigint3addEm:
 3554|  1.00M|  GLZ_FASTFLOAT_CONSTEXPR20 bool add(limb y) noexcept { return small_add(vec, y); }
_ZN3glz10fast_float9small_addILt62EEEbRNS0_8stackvecIXT_EEEm:
 3242|  1.00M|small_add(stackvec<size> &vec, limb y) noexcept {
 3243|  1.00M|  return small_add_from(vec, y, 0);
 3244|  1.00M|}
_ZN3glz10fast_float14small_add_fromILt62EEEbRNS0_8stackvecIXT_EEEmm:
 3224|  1.00M|                                                 size_t start) noexcept {
 3225|  1.00M|  size_t index = start;
 3226|  1.00M|  limb carry = y;
 3227|  1.00M|  bool overflow;
 3228|  1.34M|  while (carry != 0 && index < vec.len()) {
  ------------------
  |  Branch (3228:10): [True: 403k, False: 945k]
  |  Branch (3228:24): [True: 339k, False: 63.7k]
  ------------------
 3229|   339k|    vec[index] = scalar_add(vec[index], carry, overflow);
 3230|   339k|    carry = limb(overflow);
 3231|   339k|    index += 1;
 3232|   339k|  }
 3233|  1.00M|  if (carry != 0) {
  ------------------
  |  Branch (3233:7): [True: 63.7k, False: 945k]
  ------------------
 3234|  63.7k|    GLZ_FASTFLOAT_TRY(vec.try_push(carry));
  ------------------
  |  |  354|  63.7k|  {                                                                            \
  |  |  355|  63.7k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 63.7k]
  |  |  ------------------
  |  |  356|  63.7k|      return false;                                                            \
  |  |  357|  63.7k|  }
  ------------------
 3235|  63.7k|  }
 3236|  1.00M|  return true;
 3237|  1.00M|}
_ZN3glz10fast_float10scalar_addEmmRb:
 3176|  7.63M|scalar_add(limb x, limb y, bool &overflow) noexcept {
 3177|  7.63M|  limb z;
 3178|       |// gcc and clang
 3179|  7.63M|#if defined(__has_builtin)
 3180|  7.63M|#if __has_builtin(__builtin_add_overflow)
 3181|  7.63M|  if (!cpp20_and_in_constexpr()) {
  ------------------
  |  Branch (3181:7): [True: 7.63M, Folded]
  ------------------
 3182|  7.63M|    overflow = __builtin_add_overflow(x, y, &z);
 3183|  7.63M|    return z;
 3184|  7.63M|  }
 3185|      0|#endif
 3186|      0|#endif
 3187|       |
 3188|       |  // generic, this still optimizes correctly on MSVC.
 3189|      0|  z = x + y;
 3190|      0|  overflow = z < x;
 3191|      0|  return z;
 3192|  7.63M|}
_ZN3glz10fast_float12is_truncatedIcEEbPKT_S4_:
 3795|  30.7k|is_truncated(UC const *first, UC const *last) noexcept {
 3796|       |  // do 8-bit optimizations, can just compare to 8 literal 0s.
 3797|  30.7k|  uint64_t val;
 3798|   105k|  while (!cpp20_and_in_constexpr() &&
  ------------------
  |  Branch (3798:10): [True: 105k, Folded]
  ------------------
 3799|   105k|         std::distance(first, last) >= int_cmp_len<UC>()) {
  ------------------
  |  Branch (3799:10): [True: 79.9k, False: 25.7k]
  ------------------
 3800|  79.9k|    ::memcpy(&val, first, sizeof(uint64_t));
 3801|  79.9k|    if (val != int_cmp_zeros<UC>()) {
  ------------------
  |  Branch (3801:9): [True: 5.00k, False: 74.9k]
  ------------------
 3802|  5.00k|      return true;
 3803|  5.00k|    }
 3804|  74.9k|    first += int_cmp_len<UC>();
 3805|  74.9k|  }
 3806|  65.4k|  while (first != last) {
  ------------------
  |  Branch (3806:10): [True: 50.8k, False: 14.5k]
  ------------------
 3807|  50.8k|    if (*first != UC('0')) {
  ------------------
  |  Branch (3807:9): [True: 11.2k, False: 39.6k]
  ------------------
 3808|  11.2k|      return true;
 3809|  11.2k|    }
 3810|  39.6k|    ++first;
 3811|  39.6k|  }
 3812|  14.5k|  return false;
 3813|  25.7k|}
_ZN3glz10fast_float12is_truncatedIcEEbNS0_4spanIKT_EE:
 3817|  8.91k|is_truncated(span<UC const> s) noexcept {
 3818|  8.91k|  return is_truncated(s.ptr, s.ptr + s.len());
 3819|  8.91k|}
_ZN3glz10fast_float15round_up_bigintERNS0_6bigintERm:
 3848|  12.7k|round_up_bigint(bigint &big, size_t &count) noexcept {
 3849|       |  // need to round-up the digits, but need to avoid rounding
 3850|       |  // ....9999 to ...10000, which could cause a false halfway point.
 3851|  12.7k|  add_native(big, 10, 1);
 3852|  12.7k|  count++;
 3853|  12.7k|}
_ZN3glz10fast_float19positive_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintEi:
 3942|  17.4k|positive_digit_comp(bigint &bigmant, int32_t exponent) noexcept {
 3943|  17.4k|  GLZ_FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent)));
  ------------------
  |  |  344|  17.4k|  { ((void)(x)); }
  ------------------
 3944|  17.4k|  adjusted_mantissa answer;
 3945|  17.4k|  bool truncated;
 3946|  17.4k|  answer.mantissa = bigmant.hi64(truncated);
 3947|  17.4k|  int bias = binary_format<T>::mantissa_explicit_bits() -
 3948|  17.4k|             binary_format<T>::minimum_exponent();
 3949|  17.4k|  answer.power2 = bigmant.bit_length() - 64 + bias;
 3950|       |
 3951|  17.4k|  round<T>(answer, [truncated](adjusted_mantissa &a, int32_t shift) {
 3952|  17.4k|    round_nearest_tie_even(
 3953|  17.4k|        a, shift,
 3954|  17.4k|        [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool {
 3955|  17.4k|          return is_above || (is_halfway && truncated) ||
 3956|  17.4k|                 (is_odd && is_halfway);
 3957|  17.4k|        });
 3958|  17.4k|  });
 3959|       |
 3960|  17.4k|  return answer;
 3961|  17.4k|}
_ZN3glz10fast_float6bigint5pow10Ej:
 3591|  17.4k|  GLZ_FASTFLOAT_CONSTEXPR20 bool pow10(uint32_t exp) noexcept {
 3592|  17.4k|    GLZ_FASTFLOAT_TRY(pow5(exp));
  ------------------
  |  |  354|  17.4k|  {                                                                            \
  |  |  355|  17.4k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 17.4k]
  |  |  ------------------
  |  |  356|  17.4k|      return false;                                                            \
  |  |  357|  17.4k|  }
  ------------------
 3593|  17.4k|    return pow2(exp);
 3594|  17.4k|  }
_ZN3glz10fast_float6bigint4pow5Ej:
 3560|  58.5k|  GLZ_FASTFLOAT_CONSTEXPR20 bool pow5(uint32_t exp) noexcept {
 3561|       |    // multiply by a power of 5
 3562|  58.5k|    size_t large_length = sizeof(large_power_of_5) / sizeof(limb);
 3563|  58.5k|    limb_span large = limb_span(large_power_of_5, large_length);
 3564|   178k|    while (exp >= large_step) {
  ------------------
  |  Branch (3564:12): [True: 120k, False: 58.5k]
  ------------------
 3565|   120k|      GLZ_FASTFLOAT_TRY(large_mul(vec, large));
  ------------------
  |  |  354|   120k|  {                                                                            \
  |  |  355|   120k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 120k]
  |  |  ------------------
  |  |  356|   120k|      return false;                                                            \
  |  |  357|   120k|  }
  ------------------
 3566|   120k|      exp -= large_step;
 3567|   120k|    }
 3568|  58.5k|#ifdef GLZ_FASTFLOAT_64BIT_LIMB
 3569|  58.5k|    uint32_t small_step = 27;
 3570|  58.5k|    limb max_native = 7450580596923828125UL;
 3571|       |#else
 3572|       |    uint32_t small_step = 13;
 3573|       |    limb max_native = 1220703125U;
 3574|       |#endif
 3575|   123k|    while (exp >= small_step) {
  ------------------
  |  Branch (3575:12): [True: 65.1k, False: 58.5k]
  ------------------
 3576|  65.1k|      GLZ_FASTFLOAT_TRY(small_mul(vec, max_native));
  ------------------
  |  |  354|  65.1k|  {                                                                            \
  |  |  355|  65.1k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 65.1k]
  |  |  ------------------
  |  |  356|  65.1k|      return false;                                                            \
  |  |  357|  65.1k|  }
  ------------------
 3577|  65.1k|      exp -= small_step;
 3578|  65.1k|    }
 3579|  58.5k|    if (exp != 0) {
  ------------------
  |  Branch (3579:9): [True: 50.4k, False: 8.19k]
  ------------------
 3580|       |      // Work around clang bug https://godbolt.org/z/zedh7rrhc
 3581|       |      // This is similar to https://github.com/llvm/llvm-project/issues/47746,
 3582|       |      // except the workaround described there don't work here
 3583|  50.4k|      GLZ_FASTFLOAT_TRY(small_mul(
  ------------------
  |  |  354|  50.4k|  {                                                                            \
  |  |  355|  50.4k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 50.4k]
  |  |  ------------------
  |  |  356|  50.4k|      return false;                                                            \
  |  |  357|  50.4k|  }
  ------------------
 3584|  50.4k|          vec, limb(((void)small_power_of_5[0], small_power_of_5[exp]))));
 3585|  50.4k|    }
 3586|       |
 3587|  58.5k|    return true;
 3588|  58.5k|  }
_ZN3glz10fast_float4spanImEC2EPKmm:
  436|   779k|  constexpr span(T const *_ptr, size_t _length) : ptr(_ptr), length(_length) {}
_ZN3glz10fast_float9large_mulILt62EEEbRNS0_8stackvecIXT_EEENS0_4spanImEE:
 3329|   120k|GLZ_FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec<size> &x, limb_span y) noexcept {
 3330|   120k|  if (y.len() == 1) {
  ------------------
  |  Branch (3330:7): [True: 0, False: 120k]
  ------------------
 3331|      0|    GLZ_FASTFLOAT_TRY(small_mul(x, y[0]));
  ------------------
  |  |  354|      0|  {                                                                            \
  |  |  355|      0|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  356|      0|      return false;                                                            \
  |  |  357|      0|  }
  ------------------
 3332|   120k|  } else {
 3333|   120k|    GLZ_FASTFLOAT_TRY(long_mul(x, y));
  ------------------
  |  |  354|   120k|  {                                                                            \
  |  |  355|   120k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 120k]
  |  |  ------------------
  |  |  356|   120k|      return false;                                                            \
  |  |  357|   120k|  }
  ------------------
 3334|   120k|  }
 3335|   120k|  return true;
 3336|   120k|}
_ZNK3glz10fast_float4spanImE3lenEv:
  440|  9.26M|  constexpr size_t len() const noexcept { return length; }
_ZNK3glz10fast_float4spanImEixEm:
  442|  5.78M|  GLZ_FASTFLOAT_CONSTEXPR14 const T &operator[](size_t index) const noexcept {
  443|  5.78M|    GLZ_FASTFLOAT_DEBUG_ASSERT(index < length);
  ------------------
  |  |  349|  5.78M|  { ((void)(x)); }
  ------------------
  444|  5.78M|    return ptr[index];
  445|  5.78M|  }
_ZN3glz10fast_float8long_mulILt62EEEbRNS0_8stackvecIXT_EEENS0_4spanImEE:
 3301|   120k|GLZ_FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec<size> &x, limb_span y) noexcept {
 3302|   120k|  limb_span xs = limb_span(x.data, x.len());
 3303|   120k|  stackvec<size> z(xs);
 3304|   120k|  limb_span zs = limb_span(z.data, z.len());
 3305|       |
 3306|   120k|  if (y.len() != 0) {
  ------------------
  |  Branch (3306:7): [True: 120k, False: 0]
  ------------------
 3307|   120k|    limb y0 = y[0];
 3308|   120k|    GLZ_FASTFLOAT_TRY(small_mul(x, y0));
  ------------------
  |  |  354|   120k|  {                                                                            \
  |  |  355|   120k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 120k]
  |  |  ------------------
  |  |  356|   120k|      return false;                                                            \
  |  |  357|   120k|  }
  ------------------
 3309|   601k|    for (size_t index = 1; index < y.len(); index++) {
  ------------------
  |  Branch (3309:28): [True: 480k, False: 120k]
  ------------------
 3310|   480k|      limb yi = y[index];
 3311|   480k|      stackvec<size> zi;
 3312|   480k|      if (yi != 0) {
  ------------------
  |  Branch (3312:11): [True: 480k, False: 0]
  ------------------
 3313|       |        // re-use the same buffer throughout
 3314|   480k|        zi.set_len(0);
 3315|   480k|        GLZ_FASTFLOAT_TRY(zi.try_extend(zs));
  ------------------
  |  |  354|   480k|  {                                                                            \
  |  |  355|   480k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 480k]
  |  |  ------------------
  |  |  356|   480k|      return false;                                                            \
  |  |  357|   480k|  }
  ------------------
 3316|   480k|        GLZ_FASTFLOAT_TRY(small_mul(zi, yi));
  ------------------
  |  |  354|   480k|  {                                                                            \
  |  |  355|   480k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 480k]
  |  |  ------------------
  |  |  356|   480k|      return false;                                                            \
  |  |  357|   480k|  }
  ------------------
 3317|   480k|        limb_span zis = limb_span(zi.data, zi.len());
 3318|   480k|        GLZ_FASTFLOAT_TRY(large_add_from(x, zis, index));
  ------------------
  |  |  354|   480k|  {                                                                            \
  |  |  355|   480k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 480k]
  |  |  ------------------
  |  |  356|   480k|      return false;                                                            \
  |  |  357|   480k|  }
  ------------------
 3319|   480k|      }
 3320|   480k|    }
 3321|   120k|  }
 3322|       |
 3323|   120k|  x.normalize();
 3324|   120k|  return true;
 3325|   120k|}
_ZN3glz10fast_float8stackvecILt62EEC2ENS0_4spanImEE:
 3013|   120k|  GLZ_FASTFLOAT_CONSTEXPR20 stackvec(limb_span s) {
 3014|   120k|    GLZ_FASTFLOAT_ASSERT(try_extend(s));
  ------------------
  |  |  344|   120k|  { ((void)(x)); }
  ------------------
 3015|   120k|  }
_ZN3glz10fast_float8stackvecILt62EE7set_lenEm:
 3035|  1.59M|  GLZ_FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept {
 3036|  1.59M|    length = uint16_t(len);
 3037|  1.59M|  }
_ZN3glz10fast_float8stackvecILt62EE10try_extendENS0_4spanImEE:
 3069|   601k|  GLZ_FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept {
 3070|   601k|    if (len() + s.len() <= capacity()) {
  ------------------
  |  Branch (3070:9): [True: 601k, False: 0]
  ------------------
 3071|   601k|      extend_unchecked(s);
 3072|   601k|      return true;
 3073|   601k|    } else {
 3074|      0|      return false;
 3075|      0|    }
 3076|   601k|  }
_ZN3glz10fast_float8stackvecILt62EE16extend_uncheckedENS0_4spanImEE:
 3062|   601k|  GLZ_FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept {
 3063|   601k|    limb *ptr = data + length;
 3064|   601k|    std::copy_n(s.ptr, s.len(), ptr);
 3065|   601k|    set_len(len() + s.len());
 3066|   601k|  }
_ZN3glz10fast_float14large_add_fromILt62EEEbRNS0_8stackvecIXT_EEENS0_4spanImEEm:
 3264|   480k|                                          size_t start) noexcept {
 3265|       |  // the effective x buffer is from `xstart..x.len()`, so exit early
 3266|       |  // if we can't get that current range.
 3267|   480k|  if (x.len() < start || y.len() > x.len() - start) {
  ------------------
  |  Branch (3267:7): [True: 0, False: 480k]
  |  Branch (3267:26): [True: 476k, False: 4.39k]
  ------------------
 3268|   476k|    GLZ_FASTFLOAT_TRY(x.try_resize(y.len() + start, 0));
  ------------------
  |  |  354|   476k|  {                                                                            \
  |  |  355|   476k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 476k]
  |  |  ------------------
  |  |  356|   476k|      return false;                                                            \
  |  |  357|   476k|  }
  ------------------
 3269|   476k|  }
 3270|       |
 3271|   480k|  bool carry = false;
 3272|  5.66M|  for (size_t index = 0; index < y.len(); index++) {
  ------------------
  |  Branch (3272:26): [True: 5.18M, False: 480k]
  ------------------
 3273|  5.18M|    limb xi = x[index + start];
 3274|  5.18M|    limb yi = y[index];
 3275|  5.18M|    bool c1 = false;
 3276|  5.18M|    bool c2 = false;
 3277|  5.18M|    xi = scalar_add(xi, yi, c1);
 3278|  5.18M|    if (carry) {
  ------------------
  |  Branch (3278:9): [True: 2.11M, False: 3.06M]
  ------------------
 3279|  2.11M|      xi = scalar_add(xi, 1, c2);
 3280|  2.11M|    }
 3281|  5.18M|    x[index + start] = xi;
 3282|  5.18M|    carry = c1 | c2;
 3283|  5.18M|  }
 3284|       |
 3285|       |  // handle overflow
 3286|   480k|  if (carry) {
  ------------------
  |  Branch (3286:7): [True: 0, False: 480k]
  ------------------
 3287|      0|    GLZ_FASTFLOAT_TRY(small_add_from(x, 1, y.len() + start));
  ------------------
  |  |  354|      0|  {                                                                            \
  |  |  355|      0|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 0]
  |  |  ------------------
  |  |  356|      0|      return false;                                                            \
  |  |  357|      0|  }
  ------------------
 3288|      0|  }
 3289|   480k|  return true;
 3290|   480k|}
_ZN3glz10fast_float8stackvecILt62EE10try_resizeEmm:
 3095|   476k|  GLZ_FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept {
 3096|   476k|    if (new_len > capacity()) {
  ------------------
  |  Branch (3096:9): [True: 0, False: 476k]
  ------------------
 3097|      0|      return false;
 3098|   476k|    } else {
 3099|   476k|      resize_unchecked(new_len, value);
 3100|   476k|      return true;
 3101|   476k|    }
 3102|   476k|  }
_ZN3glz10fast_float8stackvecILt62EE16resize_uncheckedEmm:
 3082|   476k|  void resize_unchecked(size_t new_len, limb value) noexcept {
 3083|   476k|    if (new_len > len()) {
  ------------------
  |  Branch (3083:9): [True: 476k, False: 0]
  ------------------
 3084|   476k|      size_t count = new_len - len();
 3085|   476k|      limb *first = data + len();
 3086|   476k|      limb *last = first + count;
 3087|   476k|      ::std::fill(first, last, value);
 3088|   476k|      set_len(new_len);
 3089|   476k|    } else {
 3090|      0|      set_len(new_len);
 3091|      0|    }
 3092|   476k|  }
_ZN3glz10fast_float8stackvecILt62EE9normalizeEv:
 3118|   161k|  GLZ_FASTFLOAT_CONSTEXPR14 void normalize() noexcept {
 3119|   161k|    while (len() > 0 && rindex(0) == 0) {
  ------------------
  |  Branch (3119:12): [True: 161k, False: 0]
  |  Branch (3119:25): [True: 0, False: 161k]
  ------------------
 3120|      0|      length--;
 3121|      0|    }
 3122|   161k|  }
_ZNK3glz10fast_float8stackvecILt62EE6rindexEm:
 3028|   219k|  GLZ_FASTFLOAT_CONSTEXPR14 const limb &rindex(size_t index) const noexcept {
 3029|   219k|    GLZ_FASTFLOAT_DEBUG_ASSERT(index < length);
  ------------------
  |  |  349|   219k|  { ((void)(x)); }
  ------------------
 3030|   219k|    size_t rindex = length - index - 1;
 3031|   219k|    return data[rindex];
 3032|   219k|  }
_ZN3glz10fast_float6bigint4pow2Ej:
 3557|  57.6k|  GLZ_FASTFLOAT_CONSTEXPR20 bool pow2(uint32_t exp) noexcept { return shl(exp); }
_ZN3glz10fast_float6bigint3shlEm:
 3519|  57.6k|  GLZ_FASTFLOAT_CONSTEXPR20 bool shl(size_t n) noexcept {
 3520|  57.6k|    size_t rem = n % limb_bits;
 3521|  57.6k|    size_t div = n / limb_bits;
 3522|  57.6k|    if (rem != 0) {
  ------------------
  |  Branch (3522:9): [True: 46.7k, False: 10.8k]
  ------------------
 3523|  46.7k|      GLZ_FASTFLOAT_TRY(shl_bits(rem));
  ------------------
  |  |  354|  46.7k|  {                                                                            \
  |  |  355|  46.7k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 46.7k]
  |  |  ------------------
  |  |  356|  46.7k|      return false;                                                            \
  |  |  357|  46.7k|  }
  ------------------
 3524|  46.7k|    }
 3525|  57.6k|    if (div != 0) {
  ------------------
  |  Branch (3525:9): [True: 34.7k, False: 22.8k]
  ------------------
 3526|  34.7k|      GLZ_FASTFLOAT_TRY(shl_limbs(div));
  ------------------
  |  |  354|  34.7k|  {                                                                            \
  |  |  355|  34.7k|    if (!(x))                                                                  \
  |  |  ------------------
  |  |  |  Branch (355:9): [True: 0, False: 34.7k]
  |  |  ------------------
  |  |  356|  34.7k|      return false;                                                            \
  |  |  357|  34.7k|  }
  ------------------
 3527|  34.7k|    }
 3528|  57.6k|    return true;
 3529|  57.6k|  }
_ZN3glz10fast_float6bigint8shl_bitsEm:
 3472|  46.7k|  GLZ_FASTFLOAT_CONSTEXPR20 bool shl_bits(size_t n) noexcept {
 3473|       |    // Internally, for each item, we shift left by n, and add the previous
 3474|       |    // right shifted limb-bits.
 3475|       |    // For example, we transform (for u8) shifted left 2, to:
 3476|       |    //      b10100100 b01000010
 3477|       |    //      b10 b10010001 b00001000
 3478|  46.7k|    GLZ_FASTFLOAT_DEBUG_ASSERT(n != 0);
  ------------------
  |  |  349|  46.7k|  { ((void)(x)); }
  ------------------
 3479|  46.7k|    GLZ_FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8);
  ------------------
  |  |  349|  46.7k|  { ((void)(x)); }
  ------------------
 3480|       |
 3481|  46.7k|    size_t shl = n;
 3482|  46.7k|    size_t shr = limb_bits - shl;
 3483|  46.7k|    limb prev = 0;
 3484|   720k|    for (size_t index = 0; index < vec.len(); index++) {
  ------------------
  |  Branch (3484:28): [True: 673k, False: 46.7k]
  ------------------
 3485|   673k|      limb xi = vec[index];
 3486|   673k|      vec[index] = (xi << shl) | (prev >> shr);
 3487|   673k|      prev = xi;
 3488|   673k|    }
 3489|       |
 3490|  46.7k|    limb carry = prev >> shr;
 3491|  46.7k|    if (carry != 0) {
  ------------------
  |  Branch (3491:9): [True: 12.0k, False: 34.6k]
  ------------------
 3492|  12.0k|      return vec.try_push(carry);
 3493|  12.0k|    }
 3494|  34.6k|    return true;
 3495|  46.7k|  }
_ZN3glz10fast_float6bigint9shl_limbsEm:
 3498|  34.7k|  GLZ_FASTFLOAT_CONSTEXPR20 bool shl_limbs(size_t n) noexcept {
 3499|  34.7k|    GLZ_FASTFLOAT_DEBUG_ASSERT(n != 0);
  ------------------
  |  |  349|  34.7k|  { ((void)(x)); }
  ------------------
 3500|  34.7k|    if (n + vec.len() > vec.capacity()) {
  ------------------
  |  Branch (3500:9): [True: 0, False: 34.7k]
  ------------------
 3501|      0|      return false;
 3502|  34.7k|    } else if (!vec.is_empty()) {
  ------------------
  |  Branch (3502:16): [True: 34.7k, False: 0]
  ------------------
 3503|       |      // move limbs
 3504|  34.7k|      limb *dst = vec.data + n;
 3505|  34.7k|      limb const *src = vec.data;
 3506|  34.7k|      std::copy_backward(src, src + vec.len(), dst + vec.len());
 3507|       |      // fill in empty limbs
 3508|  34.7k|      limb *first = vec.data;
 3509|  34.7k|      limb *last = first + n;
 3510|  34.7k|      ::std::fill(first, last, 0);
 3511|  34.7k|      vec.set_len(n + vec.len());
 3512|  34.7k|      return true;
 3513|  34.7k|    } else {
 3514|      0|      return true;
 3515|      0|    }
 3516|  34.7k|  }
_ZNK3glz10fast_float8stackvecILt62EE8is_emptyEv:
 3041|  52.2k|  constexpr bool is_empty() const noexcept { return length == 0; }
_ZNK3glz10fast_float6bigint4hi64ERb:
 3418|  17.4k|  GLZ_FASTFLOAT_CONSTEXPR20 uint64_t hi64(bool &truncated) const noexcept {
 3419|  17.4k|#ifdef GLZ_FASTFLOAT_64BIT_LIMB
 3420|  17.4k|    if (vec.len() == 0) {
  ------------------
  |  Branch (3420:9): [True: 0, False: 17.4k]
  ------------------
 3421|      0|      return empty_hi64(truncated);
 3422|  17.4k|    } else if (vec.len() == 1) {
  ------------------
  |  Branch (3422:16): [True: 4.55k, False: 12.9k]
  ------------------
 3423|  4.55k|      return uint64_hi64(vec.rindex(0), truncated);
 3424|  12.9k|    } else {
 3425|  12.9k|      uint64_t result = uint64_hi64(vec.rindex(0), vec.rindex(1), truncated);
 3426|  12.9k|      truncated |= vec.nonzero(2);
 3427|  12.9k|      return result;
 3428|  12.9k|    }
 3429|       |#else
 3430|       |    if (vec.len() == 0) {
 3431|       |      return empty_hi64(truncated);
 3432|       |    } else if (vec.len() == 1) {
 3433|       |      return uint32_hi64(vec.rindex(0), truncated);
 3434|       |    } else if (vec.len() == 2) {
 3435|       |      return uint32_hi64(vec.rindex(0), vec.rindex(1), truncated);
 3436|       |    } else {
 3437|       |      uint64_t result =
 3438|       |          uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated);
 3439|       |      truncated |= vec.nonzero(3);
 3440|       |      return result;
 3441|       |    }
 3442|       |#endif
 3443|  17.4k|  }
_ZN3glz10fast_float11uint64_hi64EmRb:
 3132|  4.55k|uint64_hi64(uint64_t r0, bool &truncated) noexcept {
 3133|  4.55k|  truncated = false;
 3134|  4.55k|  int shl = leading_zeroes(r0);
 3135|  4.55k|  return r0 << shl;
 3136|  4.55k|}
_ZN3glz10fast_float11uint64_hi64EmmRb:
 3139|  12.9k|uint64_hi64(uint64_t r0, uint64_t r1, bool &truncated) noexcept {
 3140|  12.9k|  int shl = leading_zeroes(r0);
 3141|  12.9k|  if (shl == 0) {
  ------------------
  |  Branch (3141:7): [True: 1.52k, False: 11.4k]
  ------------------
 3142|  1.52k|    truncated = r1 != 0;
 3143|  1.52k|    return r0;
 3144|  11.4k|  } else {
 3145|  11.4k|    int shr = 64 - shl;
 3146|  11.4k|    truncated = (r1 << shl) != 0;
 3147|  11.4k|    return (r0 << shl) | (r1 >> shr);
 3148|  11.4k|  }
 3149|  12.9k|}
_ZNK3glz10fast_float8stackvecILt62EE7nonzeroEm:
 3107|  12.9k|  GLZ_FASTFLOAT_CONSTEXPR14 bool nonzero(size_t index) const noexcept {
 3108|  17.4k|    while (index < len()) {
  ------------------
  |  Branch (3108:12): [True: 10.6k, False: 6.87k]
  ------------------
 3109|  10.6k|      if (rindex(index) != 0) {
  ------------------
  |  Branch (3109:11): [True: 6.04k, False: 4.55k]
  ------------------
 3110|  6.04k|        return true;
 3111|  6.04k|      }
 3112|  4.55k|      index++;
 3113|  4.55k|    }
 3114|  6.87k|    return false;
 3115|  12.9k|  }
_ZNK3glz10fast_float6bigint10bit_lengthEv:
 3547|  17.4k|  GLZ_FASTFLOAT_CONSTEXPR20 int bit_length() const noexcept {
 3548|  17.4k|    int lz = ctlz();
 3549|  17.4k|    return int(limb_bits * vec.len()) - lz;
 3550|  17.4k|  }
_ZNK3glz10fast_float6bigint4ctlzEv:
 3532|  17.4k|  GLZ_FASTFLOAT_CONSTEXPR20 int ctlz() const noexcept {
 3533|  17.4k|    if (vec.is_empty()) {
  ------------------
  |  Branch (3533:9): [True: 0, False: 17.4k]
  ------------------
 3534|      0|      return 0;
 3535|  17.4k|    } else {
 3536|  17.4k|#ifdef GLZ_FASTFLOAT_64BIT_LIMB
 3537|  17.4k|      return leading_zeroes(vec.rindex(0));
 3538|       |#else
 3539|       |      // no use defining a specialized leading_zeroes for a 32-bit type.
 3540|       |      uint64_t r0 = vec.rindex(0);
 3541|       |      return leading_zeroes(r0 << 32);
 3542|       |#endif
 3543|  17.4k|    }
 3544|  17.4k|  }
_ZN3glz10fast_float5roundIdZNS0_19positive_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintEiEUlRS3_iE_EEvS6_T0_:
 3707|  17.4k|                                                         callback cb) noexcept {
 3708|  17.4k|  int32_t mantissa_shift = 64 - binary_format<T>::mantissa_explicit_bits() - 1;
 3709|  17.4k|  if (-am.power2 >= mantissa_shift) {
  ------------------
  |  Branch (3709:7): [True: 0, False: 17.4k]
  ------------------
 3710|       |    // have a denormal float
 3711|      0|    int32_t shift = -am.power2 + 1;
 3712|      0|    cb(am, (std::min<int32_t>)(shift, 64));
 3713|       |    // check for round-up: if rounding-nearest carried us to the hidden bit.
 3714|      0|    am.power2 = (am.mantissa <
  ------------------
  |  Branch (3714:17): [True: 0, False: 0]
  ------------------
 3715|      0|                 (uint64_t(1) << binary_format<T>::mantissa_explicit_bits()))
 3716|      0|                    ? 0
 3717|      0|                    : 1;
 3718|      0|    return;
 3719|      0|  }
 3720|       |
 3721|       |  // have a normal float, use the default shift.
 3722|  17.4k|  cb(am, mantissa_shift);
 3723|       |
 3724|       |  // check for carry
 3725|  17.4k|  if (am.mantissa >=
  ------------------
  |  Branch (3725:7): [True: 2.55k, False: 14.9k]
  ------------------
 3726|  17.4k|      (uint64_t(2) << binary_format<T>::mantissa_explicit_bits())) {
 3727|  2.55k|    am.mantissa = (uint64_t(1) << binary_format<T>::mantissa_explicit_bits());
 3728|  2.55k|    am.power2++;
 3729|  2.55k|  }
 3730|       |
 3731|       |  // check for infinite: we could have carried to an infinite power
 3732|  17.4k|  am.mantissa &= ~(uint64_t(1) << binary_format<T>::mantissa_explicit_bits());
 3733|  17.4k|  if (am.power2 >= binary_format<T>::infinite_power()) {
  ------------------
  |  Branch (3733:7): [True: 0, False: 17.4k]
  ------------------
 3734|      0|    am.power2 = binary_format<T>::infinite_power();
 3735|      0|    am.mantissa = 0;
 3736|      0|  }
 3737|  17.4k|}
_ZZN3glz10fast_float19positive_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintEiENKUlRS2_iE_clES5_i:
 3951|  17.4k|  round<T>(answer, [truncated](adjusted_mantissa &a, int32_t shift) {
 3952|  17.4k|    round_nearest_tie_even(
 3953|  17.4k|        a, shift,
 3954|  17.4k|        [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool {
 3955|  17.4k|          return is_above || (is_halfway && truncated) ||
 3956|  17.4k|                 (is_odd && is_halfway);
 3957|  17.4k|        });
 3958|  17.4k|  });
_ZN3glz10fast_float22round_nearest_tie_evenIZZNS0_19positive_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintEiENKUlRS3_iE_clES6_iEUlbbbE_EEvS6_iT_:
 3742|  17.4k|                       callback cb) noexcept {
 3743|  17.4k|  uint64_t const mask = (shift == 64) ? UINT64_MAX : (uint64_t(1) << shift) - 1;
  ------------------
  |  Branch (3743:25): [True: 0, False: 17.4k]
  ------------------
 3744|  17.4k|  uint64_t const halfway = (shift == 0) ? 0 : uint64_t(1) << (shift - 1);
  ------------------
  |  Branch (3744:28): [True: 0, False: 17.4k]
  ------------------
 3745|  17.4k|  uint64_t truncated_bits = am.mantissa & mask;
 3746|  17.4k|  bool is_above = truncated_bits > halfway;
 3747|  17.4k|  bool is_halfway = truncated_bits == halfway;
 3748|       |
 3749|       |  // shift digits into position
 3750|  17.4k|  if (shift == 64) {
  ------------------
  |  Branch (3750:7): [True: 0, False: 17.4k]
  ------------------
 3751|      0|    am.mantissa = 0;
 3752|  17.4k|  } else {
 3753|  17.4k|    am.mantissa >>= shift;
 3754|  17.4k|  }
 3755|  17.4k|  am.power2 += shift;
 3756|       |
 3757|  17.4k|  bool is_odd = (am.mantissa & 1) == 1;
 3758|  17.4k|  am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above));
 3759|  17.4k|}
_ZZZN3glz10fast_float19positive_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintEiENKUlRS2_iE_clES5_iENKUlbbbE_clEbbb:
 3954|  17.4k|        [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool {
 3955|  17.4k|          return is_above || (is_halfway && truncated) ||
  ------------------
  |  Branch (3955:18): [True: 4.01k, False: 13.4k]
  |  Branch (3955:31): [True: 9.70k, False: 3.75k]
  |  Branch (3955:45): [True: 4.65k, False: 5.05k]
  ------------------
 3956|  8.81k|                 (is_odd && is_halfway);
  ------------------
  |  Branch (3956:19): [True: 2.69k, False: 6.11k]
  |  Branch (3956:29): [True: 39, False: 2.65k]
  ------------------
 3957|  17.4k|        });
_ZN3glz10fast_float19negative_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintES2_i:
 3970|  41.1k|    bigint &bigmant, adjusted_mantissa am, int32_t exponent) noexcept {
 3971|  41.1k|  bigint &real_digits = bigmant;
 3972|  41.1k|  int32_t real_exp = exponent;
 3973|       |
 3974|       |  // get the value of `b`, rounded down, and get a bigint representation of b+h
 3975|  41.1k|  adjusted_mantissa am_b = am;
 3976|       |  // gcc7 buf: use a lambda to remove the noexcept qualifier bug with
 3977|       |  // -Wnoexcept-type.
 3978|  41.1k|  round<T>(am_b,
 3979|  41.1k|           [](adjusted_mantissa &a, int32_t shift) { round_down(a, shift); });
 3980|  41.1k|  T b;
 3981|  41.1k|  to_float(false, am_b, b);
 3982|  41.1k|  adjusted_mantissa theor = to_extended_halfway(b);
 3983|  41.1k|  bigint theor_digits(theor.mantissa);
 3984|  41.1k|  int32_t theor_exp = theor.power2;
 3985|       |
 3986|       |  // scale real digits and theor digits to be same power.
 3987|  41.1k|  int32_t pow2_exp = theor_exp - real_exp;
 3988|  41.1k|  uint32_t pow5_exp = uint32_t(-real_exp);
 3989|  41.1k|  if (pow5_exp != 0) {
  ------------------
  |  Branch (3989:7): [True: 41.1k, False: 0]
  ------------------
 3990|  41.1k|    GLZ_FASTFLOAT_ASSERT(theor_digits.pow5(pow5_exp));
  ------------------
  |  |  344|  41.1k|  { ((void)(x)); }
  ------------------
 3991|  41.1k|  }
 3992|  41.1k|  if (pow2_exp > 0) {
  ------------------
  |  Branch (3992:7): [True: 28.4k, False: 12.6k]
  ------------------
 3993|  28.4k|    GLZ_FASTFLOAT_ASSERT(theor_digits.pow2(uint32_t(pow2_exp)));
  ------------------
  |  |  344|  28.4k|  { ((void)(x)); }
  ------------------
 3994|  28.4k|  } else if (pow2_exp < 0) {
  ------------------
  |  Branch (3994:14): [True: 11.6k, False: 987]
  ------------------
 3995|  11.6k|    GLZ_FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp)));
  ------------------
  |  |  344|  11.6k|  { ((void)(x)); }
  ------------------
 3996|  11.6k|  }
 3997|       |
 3998|       |  // compare digits, and use it to director rounding
 3999|  41.1k|  int ord = real_digits.compare(theor_digits);
 4000|  41.1k|  adjusted_mantissa answer = am;
 4001|  41.1k|  round<T>(answer, [ord](adjusted_mantissa &a, int32_t shift) {
 4002|  41.1k|    round_nearest_tie_even(
 4003|  41.1k|        a, shift, [ord](bool is_odd, bool _, bool __) -> bool {
 4004|  41.1k|          (void)_;  // not needed, since we've done our comparison
 4005|  41.1k|          (void)__; // not needed, since we've done our comparison
 4006|  41.1k|          if (ord > 0) {
 4007|  41.1k|            return true;
 4008|  41.1k|          } else if (ord < 0) {
 4009|  41.1k|            return false;
 4010|  41.1k|          } else {
 4011|  41.1k|            return is_odd;
 4012|  41.1k|          }
 4013|  41.1k|        });
 4014|  41.1k|  });
 4015|       |
 4016|  41.1k|  return answer;
 4017|  41.1k|}
_ZN3glz10fast_float5roundIdZNS0_19negative_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintES3_iEUlRS3_iE_EEvS6_T0_:
 3707|  41.1k|                                                         callback cb) noexcept {
 3708|  41.1k|  int32_t mantissa_shift = 64 - binary_format<T>::mantissa_explicit_bits() - 1;
 3709|  41.1k|  if (-am.power2 >= mantissa_shift) {
  ------------------
  |  Branch (3709:7): [True: 4.68k, False: 36.4k]
  ------------------
 3710|       |    // have a denormal float
 3711|  4.68k|    int32_t shift = -am.power2 + 1;
 3712|  4.68k|    cb(am, (std::min<int32_t>)(shift, 64));
 3713|       |    // check for round-up: if rounding-nearest carried us to the hidden bit.
 3714|  4.68k|    am.power2 = (am.mantissa <
  ------------------
  |  Branch (3714:17): [True: 4.68k, False: 0]
  ------------------
 3715|  4.68k|                 (uint64_t(1) << binary_format<T>::mantissa_explicit_bits()))
 3716|  4.68k|                    ? 0
 3717|  4.68k|                    : 1;
 3718|  4.68k|    return;
 3719|  4.68k|  }
 3720|       |
 3721|       |  // have a normal float, use the default shift.
 3722|  36.4k|  cb(am, mantissa_shift);
 3723|       |
 3724|       |  // check for carry
 3725|  36.4k|  if (am.mantissa >=
  ------------------
  |  Branch (3725:7): [True: 0, False: 36.4k]
  ------------------
 3726|  36.4k|      (uint64_t(2) << binary_format<T>::mantissa_explicit_bits())) {
 3727|      0|    am.mantissa = (uint64_t(1) << binary_format<T>::mantissa_explicit_bits());
 3728|      0|    am.power2++;
 3729|      0|  }
 3730|       |
 3731|       |  // check for infinite: we could have carried to an infinite power
 3732|  36.4k|  am.mantissa &= ~(uint64_t(1) << binary_format<T>::mantissa_explicit_bits());
 3733|  36.4k|  if (am.power2 >= binary_format<T>::infinite_power()) {
  ------------------
  |  Branch (3733:7): [True: 0, False: 36.4k]
  ------------------
 3734|      0|    am.power2 = binary_format<T>::infinite_power();
 3735|      0|    am.mantissa = 0;
 3736|      0|  }
 3737|  36.4k|}
_ZZN3glz10fast_float19negative_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintES2_iENKUlRS2_iE_clES5_i:
 3979|  41.1k|           [](adjusted_mantissa &a, int32_t shift) { round_down(a, shift); });
_ZN3glz10fast_float10round_downERNS0_17adjusted_mantissaEi:
 3762|  41.1k|round_down(adjusted_mantissa &am, int32_t shift) noexcept {
 3763|  41.1k|  if (shift == 64) {
  ------------------
  |  Branch (3763:7): [True: 1.07k, False: 40.0k]
  ------------------
 3764|  1.07k|    am.mantissa = 0;
 3765|  40.0k|  } else {
 3766|  40.0k|    am.mantissa >>= shift;
 3767|  40.0k|  }
 3768|  41.1k|  am.power2 += shift;
 3769|  41.1k|}
_ZN3glz10fast_float19to_extended_halfwayIdEENS0_17adjusted_mantissaET_:
 3696|  41.1k|to_extended_halfway(T value) noexcept {
 3697|  41.1k|  adjusted_mantissa am = to_extended(value);
 3698|  41.1k|  am.mantissa <<= 1;
 3699|  41.1k|  am.mantissa += 1;
 3700|  41.1k|  am.power2 -= 1;
 3701|  41.1k|  return am;
 3702|  41.1k|}
_ZN3glz10fast_float11to_extendedIdEENS0_17adjusted_mantissaET_:
 3661|  41.1k|to_extended(T value) noexcept {
 3662|  41.1k|  using equiv_uint = equiv_uint_t<T>;
 3663|  41.1k|  constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask();
 3664|  41.1k|  constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask();
 3665|  41.1k|  constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask();
 3666|       |
 3667|  41.1k|  adjusted_mantissa am;
 3668|  41.1k|  int32_t bias = binary_format<T>::mantissa_explicit_bits() -
 3669|  41.1k|                 binary_format<T>::minimum_exponent();
 3670|  41.1k|  equiv_uint bits;
 3671|  41.1k|#if GLZ_FASTFLOAT_HAS_BIT_CAST
 3672|  41.1k|  bits = std::bit_cast<equiv_uint>(value);
 3673|       |#else
 3674|       |  ::memcpy(&bits, &value, sizeof(T));
 3675|       |#endif
 3676|  41.1k|  if ((bits & exponent_mask) == 0) {
  ------------------
  |  Branch (3676:7): [True: 4.68k, False: 36.4k]
  ------------------
 3677|       |    // denormal
 3678|  4.68k|    am.power2 = 1 - bias;
 3679|  4.68k|    am.mantissa = bits & mantissa_mask;
 3680|  36.4k|  } else {
 3681|       |    // normal
 3682|  36.4k|    am.power2 = int32_t((bits & exponent_mask) >>
 3683|  36.4k|                        binary_format<T>::mantissa_explicit_bits());
 3684|  36.4k|    am.power2 -= bias;
 3685|  36.4k|    am.mantissa = (bits & mantissa_mask) | hidden_bit_mask;
 3686|  36.4k|  }
 3687|       |
 3688|  41.1k|  return am;
 3689|  41.1k|}
_ZN3glz10fast_float6bigintC2Em:
 3406|  41.1k|  GLZ_FASTFLOAT_CONSTEXPR20 bigint(uint64_t value) : vec() {
 3407|  41.1k|#ifdef GLZ_FASTFLOAT_64BIT_LIMB
 3408|  41.1k|    vec.push_unchecked(value);
 3409|       |#else
 3410|       |    vec.push_unchecked(uint32_t(value));
 3411|       |    vec.push_unchecked(uint32_t(value >> 32));
 3412|       |#endif
 3413|  41.1k|    vec.normalize();
 3414|  41.1k|  }
_ZNK3glz10fast_float6bigint7compareERKS1_:
 3451|  41.1k|  GLZ_FASTFLOAT_CONSTEXPR20 int compare(bigint const &other) const noexcept {
 3452|  41.1k|    if (vec.len() > other.vec.len()) {
  ------------------
  |  Branch (3452:9): [True: 0, False: 41.1k]
  ------------------
 3453|      0|      return 1;
 3454|  41.1k|    } else if (vec.len() < other.vec.len()) {
  ------------------
  |  Branch (3454:16): [True: 0, False: 41.1k]
  ------------------
 3455|      0|      return -1;
 3456|  41.1k|    } else {
 3457|  85.1k|      for (size_t index = vec.len(); index > 0; index--) {
  ------------------
  |  Branch (3457:38): [True: 82.0k, False: 3.12k]
  ------------------
 3458|  82.0k|        limb xi = vec[index - 1];
 3459|  82.0k|        limb yi = other.vec[index - 1];
 3460|  82.0k|        if (xi > yi) {
  ------------------
  |  Branch (3460:13): [True: 14.2k, False: 67.7k]
  ------------------
 3461|  14.2k|          return 1;
 3462|  67.7k|        } else if (xi < yi) {
  ------------------
  |  Branch (3462:20): [True: 23.7k, False: 44.0k]
  ------------------
 3463|  23.7k|          return -1;
 3464|  23.7k|        }
 3465|  82.0k|      }
 3466|  3.12k|      return 0;
 3467|  41.1k|    }
 3468|  41.1k|  }
_ZNK3glz10fast_float8stackvecILt62EEixEm:
 3022|   164k|  GLZ_FASTFLOAT_CONSTEXPR14 const limb &operator[](size_t index) const noexcept {
 3023|   164k|    GLZ_FASTFLOAT_DEBUG_ASSERT(index < length);
  ------------------
  |  |  349|   164k|  { ((void)(x)); }
  ------------------
 3024|   164k|    return data[index];
 3025|   164k|  }
_ZN3glz10fast_float5roundIdZNS0_19negative_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintES3_iEUlRS3_iE0_EEvS6_T0_:
 3707|  41.1k|                                                         callback cb) noexcept {
 3708|  41.1k|  int32_t mantissa_shift = 64 - binary_format<T>::mantissa_explicit_bits() - 1;
 3709|  41.1k|  if (-am.power2 >= mantissa_shift) {
  ------------------
  |  Branch (3709:7): [True: 4.68k, False: 36.4k]
  ------------------
 3710|       |    // have a denormal float
 3711|  4.68k|    int32_t shift = -am.power2 + 1;
 3712|  4.68k|    cb(am, (std::min<int32_t>)(shift, 64));
 3713|       |    // check for round-up: if rounding-nearest carried us to the hidden bit.
 3714|  4.68k|    am.power2 = (am.mantissa <
  ------------------
  |  Branch (3714:17): [True: 4.67k, False: 6]
  ------------------
 3715|  4.68k|                 (uint64_t(1) << binary_format<T>::mantissa_explicit_bits()))
 3716|  4.68k|                    ? 0
 3717|  4.68k|                    : 1;
 3718|  4.68k|    return;
 3719|  4.68k|  }
 3720|       |
 3721|       |  // have a normal float, use the default shift.
 3722|  36.4k|  cb(am, mantissa_shift);
 3723|       |
 3724|       |  // check for carry
 3725|  36.4k|  if (am.mantissa >=
  ------------------
  |  Branch (3725:7): [True: 1.83k, False: 34.5k]
  ------------------
 3726|  36.4k|      (uint64_t(2) << binary_format<T>::mantissa_explicit_bits())) {
 3727|  1.83k|    am.mantissa = (uint64_t(1) << binary_format<T>::mantissa_explicit_bits());
 3728|  1.83k|    am.power2++;
 3729|  1.83k|  }
 3730|       |
 3731|       |  // check for infinite: we could have carried to an infinite power
 3732|  36.4k|  am.mantissa &= ~(uint64_t(1) << binary_format<T>::mantissa_explicit_bits());
 3733|  36.4k|  if (am.power2 >= binary_format<T>::infinite_power()) {
  ------------------
  |  Branch (3733:7): [True: 0, False: 36.4k]
  ------------------
 3734|      0|    am.power2 = binary_format<T>::infinite_power();
 3735|      0|    am.mantissa = 0;
 3736|      0|  }
 3737|  36.4k|}
_ZZN3glz10fast_float19negative_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintES2_iENKUlRS2_iE0_clES5_i:
 4001|  41.1k|  round<T>(answer, [ord](adjusted_mantissa &a, int32_t shift) {
 4002|  41.1k|    round_nearest_tie_even(
 4003|  41.1k|        a, shift, [ord](bool is_odd, bool _, bool __) -> bool {
 4004|  41.1k|          (void)_;  // not needed, since we've done our comparison
 4005|  41.1k|          (void)__; // not needed, since we've done our comparison
 4006|  41.1k|          if (ord > 0) {
 4007|  41.1k|            return true;
 4008|  41.1k|          } else if (ord < 0) {
 4009|  41.1k|            return false;
 4010|  41.1k|          } else {
 4011|  41.1k|            return is_odd;
 4012|  41.1k|          }
 4013|  41.1k|        });
 4014|  41.1k|  });
_ZN3glz10fast_float22round_nearest_tie_evenIZZNS0_19negative_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintES3_iENKUlRS3_iE0_clES6_iEUlbbbE_EEvS6_iT_:
 3742|  41.1k|                       callback cb) noexcept {
 3743|  41.1k|  uint64_t const mask = (shift == 64) ? UINT64_MAX : (uint64_t(1) << shift) - 1;
  ------------------
  |  Branch (3743:25): [True: 1.07k, False: 40.0k]
  ------------------
 3744|  41.1k|  uint64_t const halfway = (shift == 0) ? 0 : uint64_t(1) << (shift - 1);
  ------------------
  |  Branch (3744:28): [True: 0, False: 41.1k]
  ------------------
 3745|  41.1k|  uint64_t truncated_bits = am.mantissa & mask;
 3746|  41.1k|  bool is_above = truncated_bits > halfway;
 3747|  41.1k|  bool is_halfway = truncated_bits == halfway;
 3748|       |
 3749|       |  // shift digits into position
 3750|  41.1k|  if (shift == 64) {
  ------------------
  |  Branch (3750:7): [True: 1.07k, False: 40.0k]
  ------------------
 3751|  1.07k|    am.mantissa = 0;
 3752|  40.0k|  } else {
 3753|  40.0k|    am.mantissa >>= shift;
 3754|  40.0k|  }
 3755|  41.1k|  am.power2 += shift;
 3756|       |
 3757|  41.1k|  bool is_odd = (am.mantissa & 1) == 1;
 3758|  41.1k|  am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above));
 3759|  41.1k|}
_ZZZN3glz10fast_float19negative_digit_compIdEENS0_17adjusted_mantissaERNS0_6bigintES2_iENKUlRS2_iE0_clES5_iENKUlbbbE_clEbbb:
 4003|  41.1k|        a, shift, [ord](bool is_odd, bool _, bool __) -> bool {
 4004|  41.1k|          (void)_;  // not needed, since we've done our comparison
 4005|  41.1k|          (void)__; // not needed, since we've done our comparison
 4006|  41.1k|          if (ord > 0) {
  ------------------
  |  Branch (4006:15): [True: 14.2k, False: 26.8k]
  ------------------
 4007|  14.2k|            return true;
 4008|  26.8k|          } else if (ord < 0) {
  ------------------
  |  Branch (4008:22): [True: 23.7k, False: 3.12k]
  ------------------
 4009|  23.7k|            return false;
 4010|  23.7k|          } else {
 4011|  3.12k|            return is_odd;
 4012|  3.12k|          }
 4013|  41.1k|        });
_ZN3glz10fast_float8to_floatIdEEvbNS0_17adjusted_mantissaERT_:
 1131|   126k|to_float(bool negative, adjusted_mantissa am, T &value) {
 1132|   126k|  using equiv_uint = equiv_uint_t<T>;
 1133|   126k|  equiv_uint word = equiv_uint(am.mantissa);
 1134|   126k|  word = equiv_uint(word | equiv_uint(am.power2)
 1135|   126k|                               << binary_format<T>::mantissa_explicit_bits());
 1136|   126k|  word =
 1137|   126k|      equiv_uint(word | equiv_uint(negative) << binary_format<T>::sign_index());
 1138|   126k|#if GLZ_FASTFLOAT_HAS_BIT_CAST
 1139|   126k|  value = std::bit_cast<T>(word);
 1140|       |#else
 1141|       |  ::memcpy(&value, &word, sizeof(T));
 1142|       |#endif
 1143|   126k|}
_ZN3glz10fast_float13binary_formatIdE10sign_indexEv:
  758|   126k|template <> inline constexpr int binary_format<double>::sign_index() {
  759|   126k|  return 63;
  760|   126k|}
_ZN3glz10fast_float13binary_formatIdE14infinite_powerEv:
  750|   317k|template <> inline constexpr int binary_format<double>::infinite_power() {
  751|   317k|  return 0x7FF;
  752|   317k|}

_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|   598k|   {
   25|   598k|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|   598k|         else {
   47|   598k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|   598k|               (void)(lambda.template operator()<I>(), ...);
   49|   598k|            }(std::make_index_sequence<N>{});
   50|   598k|         }
   51|   598k|      }
   52|   598k|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|   598k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|   598k|               (void)(lambda.template operator()<I>(), ...);
   49|   598k|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|  6.27k|   {
   25|  6.27k|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|  6.27k|         else {
   47|  6.27k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  6.27k|               (void)(lambda.template operator()<I>(), ...);
   49|  6.27k|            }(std::make_index_sequence<N>{});
   50|  6.27k|         }
   51|  6.27k|      }
   52|  6.27k|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|  6.27k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  6.27k|               (void)(lambda.template operator()<I>(), ...);
   49|  6.27k|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|  1.38k|   {
   25|  1.38k|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|  1.38k|         else {
   47|  1.38k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  1.38k|               (void)(lambda.template operator()<I>(), ...);
   49|  1.38k|            }(std::make_index_sequence<N>{});
   50|  1.38k|         }
   51|  1.38k|      }
   52|  1.38k|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|  1.38k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  1.38k|               (void)(lambda.template operator()<I>(), ...);
   49|  1.38k|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|  2.19M|   {
   25|  2.19M|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|  2.19M|         else {
   47|  2.19M|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  2.19M|               (void)(lambda.template operator()<I>(), ...);
   49|  2.19M|            }(std::make_index_sequence<N>{});
   50|  2.19M|         }
   51|  2.19M|      }
   52|  2.19M|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|  2.19M|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  2.19M|               (void)(lambda.template operator()<I>(), ...);
   49|  2.19M|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|   598k|   {
   25|   598k|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|   598k|         else {
   47|   598k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|   598k|               (void)(lambda.template operator()<I>(), ...);
   49|   598k|            }(std::make_index_sequence<N>{});
   50|   598k|         }
   51|   598k|      }
   52|   598k|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|   598k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|   598k|               (void)(lambda.template operator()<I>(), ...);
   49|   598k|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|  6.27k|   {
   25|  6.27k|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|  6.27k|         else {
   47|  6.27k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  6.27k|               (void)(lambda.template operator()<I>(), ...);
   49|  6.27k|            }(std::make_index_sequence<N>{});
   50|  6.27k|         }
   51|  6.27k|      }
   52|  6.27k|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|  6.27k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  6.27k|               (void)(lambda.template operator()<I>(), ...);
   49|  6.27k|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|  1.38k|   {
   25|  1.38k|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|  1.38k|         else {
   47|  1.38k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  1.38k|               (void)(lambda.template operator()<I>(), ...);
   49|  1.38k|            }(std::make_index_sequence<N>{});
   50|  1.38k|         }
   51|  1.38k|      }
   52|  1.38k|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|  1.38k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  1.38k|               (void)(lambda.template operator()<I>(), ...);
   49|  1.38k|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|  2.19M|   {
   25|  2.19M|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|  2.19M|         else {
   47|  2.19M|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  2.19M|               (void)(lambda.template operator()<I>(), ...);
   49|  2.19M|            }(std::make_index_sequence<N>{});
   50|  2.19M|         }
   51|  2.19M|      }
   52|  2.19M|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|  2.19M|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  2.19M|               (void)(lambda.template operator()<I>(), ...);
   49|  2.19M|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|   598k|   {
   25|   598k|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|   598k|         else {
   47|   598k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|   598k|               (void)(lambda.template operator()<I>(), ...);
   49|   598k|            }(std::make_index_sequence<N>{});
   50|   598k|         }
   51|   598k|      }
   52|   598k|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_16is_variant_arrayEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|   598k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|   598k|               (void)(lambda.template operator()<I>(), ...);
   49|   598k|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|  6.27k|   {
   25|  6.27k|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|  6.27k|         else {
   47|  6.27k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  6.27k|               (void)(lambda.template operator()<I>(), ...);
   49|  6.27k|            }(std::make_index_sequence<N>{});
   50|  6.27k|         }
   51|  6.27k|      }
   52|  6.27k|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_strEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|  6.27k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  6.27k|               (void)(lambda.template operator()<I>(), ...);
   49|  6.27k|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|  1.38k|   {
   25|  1.38k|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|  1.38k|         else {
   47|  1.38k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  1.38k|               (void)(lambda.template operator()<I>(), ...);
   49|  1.38k|            }(std::make_index_sequence<N>{});
   50|  1.38k|         }
   51|  1.38k|      }
   52|  1.38k|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_15is_variant_boolEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|  1.38k|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  1.38k|               (void)(lambda.template operator()<I>(), ...);
   49|  1.38k|            }(std::make_index_sequence<N>{});
_ZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_:
   24|  2.19M|   {
   25|  2.19M|      if constexpr (N > 0) {
   26|       |         // Explicit sizes for small N to help the compiler and make debugging easier
   27|       |         // These generate less assembly with O0, but make no difference for higher optimization
   28|       |         if constexpr (N == 1) {
   29|       |            lambda.template operator()<0>();
   30|       |         }
   31|       |         else if constexpr (N == 2) {
   32|       |            lambda.template operator()<0>();
   33|       |            lambda.template operator()<1>();
   34|       |         }
   35|       |         else if constexpr (N == 3) {
   36|       |            lambda.template operator()<0>();
   37|       |            lambda.template operator()<1>();
   38|       |            lambda.template operator()<2>();
   39|       |         }
   40|       |         else if constexpr (N == 4) {
   41|       |            lambda.template operator()<0>();
   42|       |            lambda.template operator()<1>();
   43|       |            lambda.template operator()<2>();
   44|       |            lambda.template operator()<3>();
   45|       |         }
   46|  2.19M|         else {
   47|  2.19M|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  2.19M|               (void)(lambda.template operator()<I>(), ...);
   49|  2.19M|            }(std::make_index_sequence<N>{});
   50|  2.19M|         }
   51|  2.19M|      }
   52|  2.19M|   }
_ZZN3glz8for_eachILm6EZNS_28process_variant_alternativesINSt3__17variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbNS2_6vectorINS_12generic_jsonILNS_8num_modeE0ENS_17ordered_small_mapEEENS7_ISE_EEEENSD_ISE_EEEEENS_14is_variant_numEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEERSI_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT0_OT1_OT2_T3_EUlTnmvE_EEvSU_ENKUlTpTnmNS2_16integer_sequenceImJXspT_EEEEE_clIJLm0ELm1ELm2ELm3ELm4ELm5EEEEDaS12_:
   47|  2.19M|            [&]<size_t... I>(std::index_sequence<I...>) {
   48|  2.19M|               (void)(lambda.template operator()<I>(), ...);
   49|  2.19M|            }(std::make_index_sequence<N>{});

_ZN3glz10from_charsILb0EdcEENS_10fast_float19from_chars_result_tIT1_EEPKS3_S6_RT0_:
  236|  2.19M|   {
  237|  2.19M|      using namespace glz::fast_float;
  238|  2.19M|      static_assert(is_supported_float_type<T>(), "only some floating-point types are supported");
  239|  2.19M|      static_assert(is_supported_char_type<UC>(), "only char, wchar_t, char16_t and char32_t are supported");
  240|       |
  241|  2.19M|      parsed_number_string_t<UC> pns = glz::parse_number_string<null_terminated, UC>(first, last);
  242|  2.19M|      if (!pns.valid) [[unlikely]] {
  ------------------
  |  Branch (242:11): [True: 1.48k, False: 2.18M]
  ------------------
  243|  1.48k|         return {.ptr = first, .ec = std::errc::invalid_argument};
  244|  1.48k|      }
  245|       |
  246|  2.18M|      return from_chars_advanced(pns, value);
  247|  2.19M|   }
_ZN3glz19parse_number_stringILb0EcEENS_10fast_float22parsed_number_string_tIT0_EEPKS3_S6_:
   18|  2.19M|   {
   19|  2.19M|      using namespace glz::fast_float;
   20|  2.19M|      static constexpr UC decimal_point = '.';
   21|       |
   22|  2.19M|      parsed_number_string_t<UC> answer;
   23|  2.19M|      answer.valid = false;
   24|  2.19M|      answer.too_many_digits = false;
   25|  2.19M|      answer.negative = (*p == UC('-'));
   26|  2.19M|      if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
  ------------------
  |  Branch (26:11): [True: 4.06k, False: 2.18M]
  ------------------
   27|  4.06k|         ++p;
   28|       |
   29|  4.06k|         if constexpr (not null_terminated) {
   30|  4.06k|            if (p == pend) [[unlikely]] {
  ------------------
  |  Branch (30:17): [True: 6, False: 4.05k]
  ------------------
   31|      6|               return answer;
   32|      6|            }
   33|  4.06k|         }
   34|       |
   35|  4.06k|         if (!glz::fast_float::is_integer(*p)) [[unlikely]] { // a sign must be followed by an integer
  ------------------
  |  Branch (35:14): [True: 22, False: 4.03k]
  ------------------
   36|     22|            return answer;
   37|     22|         }
   38|  4.06k|      }
   39|  2.19M|      UC const* const start_digits = p;
   40|       |
   41|  2.19M|      uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad)
   42|       |
   43|  2.19M|      uint64_t digit;
   44|       |      if constexpr (null_terminated) {
   45|       |         while ((digit = glz::fast_float::digit_value(*p)) <= 9) {
   46|       |            // a multiplication by 10 is cheaper than an arbitrary integer
   47|       |            // multiplication
   48|       |            i = 10 * i + digit; // might overflow, we will handle the overflow later
   49|       |            ++p;
   50|       |         }
   51|       |      }
   52|  2.19M|      else {
   53|  12.0M|         while ((p != pend) && (digit = glz::fast_float::digit_value(*p)) <= 9) {
  ------------------
  |  Branch (53:17): [True: 12.0M, False: 882]
  |  Branch (53:32): [True: 9.84M, False: 2.19M]
  ------------------
   54|       |            // a multiplication by 10 is cheaper than an arbitrary integer
   55|       |            // multiplication
   56|  9.84M|            i = 10 * i + digit; // might overflow, we will handle the overflow later
   57|  9.84M|            ++p;
   58|  9.84M|         }
   59|  2.19M|      }
   60|       |
   61|  2.19M|      UC const* const end_of_integer_part = p;
   62|  2.19M|      int64_t digit_count = int64_t(end_of_integer_part - start_digits);
   63|  2.19M|      answer.integer = glz::fast_float::span<const UC>(start_digits, size_t(digit_count));
   64|       |
   65|       |      // at least 1 digit in integer part, without leading zeros
   66|  2.19M|      if (digit_count == 0 || (start_digits[0] == UC('0') && digit_count > 1)) {
  ------------------
  |  Branch (66:11): [True: 1.36k, False: 2.18M]
  |  Branch (66:32): [True: 915k, False: 1.27M]
  |  Branch (66:62): [True: 72, False: 914k]
  ------------------
   67|  1.43k|         return answer;
   68|  1.43k|      }
   69|       |
   70|  2.18M|      int64_t exponent = 0;
   71|  2.18M|      const bool has_decimal_point = [&] {
   72|  2.18M|         if constexpr (null_terminated) {
   73|  2.18M|            return (*p == decimal_point);
   74|  2.18M|         }
   75|  2.18M|         else {
   76|  2.18M|            return (p != pend) && (*p == decimal_point);
   77|  2.18M|         }
   78|  2.18M|      }();
   79|  2.18M|      if (has_decimal_point) {
  ------------------
  |  Branch (79:11): [True: 15.6k, False: 2.17M]
  ------------------
   80|  15.6k|         ++p;
   81|  15.6k|         UC const* before = p;
   82|       |         // can occur at most twice without overflowing, but let it occur more, since
   83|       |         // for integers with many digits, digit parsing is the primary bottleneck.
   84|  15.6k|         loop_parse_if_eight_digits(p, pend, i);
   85|       |
   86|       |         if constexpr (null_terminated) {
   87|       |            while ((digit = glz::fast_float::digit_value(*p)) <= 9) {
   88|       |               ++p;
   89|       |               i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
   90|       |            }
   91|       |         }
   92|  15.6k|         else {
   93|  61.0k|            while ((p != pend) && (digit = glz::fast_float::digit_value(*p)) <= 9) {
  ------------------
  |  Branch (93:20): [True: 59.9k, False: 1.01k]
  |  Branch (93:35): [True: 45.3k, False: 14.6k]
  ------------------
   94|  45.3k|               ++p;
   95|  45.3k|               i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
   96|  45.3k|            }
   97|  15.6k|         }
   98|  15.6k|         exponent = before - p;
   99|  15.6k|         answer.fraction = glz::fast_float::span<const UC>(before, size_t(p - before));
  100|  15.6k|         digit_count -= exponent;
  101|  15.6k|      }
  102|       |      // at least 1 digit in fractional part
  103|  2.18M|      if (has_decimal_point && exponent == 0) {
  ------------------
  |  Branch (103:11): [True: 15.6k, False: 2.17M]
  |  Branch (103:32): [True: 31, False: 15.6k]
  ------------------
  104|     31|         return answer;
  105|     31|      }
  106|       |
  107|  2.18M|      int64_t exp_number = 0; // explicit exponential part
  108|       |
  109|       |      if constexpr (null_terminated) {
  110|       |         if ((UC('e') == *p) || (UC('E') == *p)) {
  111|       |            UC const* location_of_e = p;
  112|       |            ++p;
  113|       |            bool neg_exp = false;
  114|       |            if (UC('-') == *p) {
  115|       |               neg_exp = true;
  116|       |               ++p;
  117|       |            }
  118|       |            else if (UC('+') == *p) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
  119|       |               ++p;
  120|       |            }
  121|       |            if ((digit = glz::fast_float::digit_value(*p)) > 9) {
  122|       |               // Otherwise, we will be ignoring the 'e'.
  123|       |               p = location_of_e;
  124|       |            }
  125|       |            else {
  126|       |               do {
  127|       |                  if (exp_number < 0x10000000) {
  128|       |                     exp_number = 10 * exp_number + digit;
  129|       |                  }
  130|       |                  ++p;
  131|       |               } while ((digit = glz::fast_float::digit_value(*p)) <= 9);
  132|       |               if (neg_exp) {
  133|       |                  exp_number = -exp_number;
  134|       |               }
  135|       |               exponent += exp_number;
  136|       |            }
  137|       |         }
  138|       |      }
  139|  2.18M|      else {
  140|  2.18M|         if ((p != pend) && ((UC('e') == *p) || (UC('E') == *p))) {
  ------------------
  |  Branch (140:14): [True: 2.18M, False: 1.86k]
  |  Branch (140:30): [True: 7.55k, False: 2.18M]
  |  Branch (140:49): [True: 7.82k, False: 2.17M]
  ------------------
  141|  15.3k|            UC const* location_of_e = p;
  142|  15.3k|            ++p;
  143|  15.3k|            bool neg_exp = false;
  144|  15.3k|            if ((p != pend) && (UC('-') == *p)) {
  ------------------
  |  Branch (144:17): [True: 15.3k, False: 17]
  |  Branch (144:32): [True: 8.09k, False: 7.27k]
  ------------------
  145|  8.09k|               neg_exp = true;
  146|  8.09k|               ++p;
  147|  8.09k|            }
  148|  7.29k|            else if ((p != pend) && (UC('+') == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
  ------------------
  |  Branch (148:22): [True: 7.27k, False: 17]
  |  Branch (148:37): [True: 328, False: 6.94k]
  ------------------
  149|    328|               ++p;
  150|    328|            }
  151|  15.3k|            if ((p == pend) || (digit = glz::fast_float::digit_value(*p)) > 9) {
  ------------------
  |  Branch (151:17): [True: 31, False: 15.3k]
  |  Branch (151:32): [True: 18, False: 15.3k]
  ------------------
  152|       |               // Otherwise, we will be ignoring the 'e'.
  153|     49|               p = location_of_e;
  154|     49|            }
  155|  15.3k|            else {
  156|  40.5k|               do {
  157|  40.5k|                  if (exp_number < 0x10000000) {
  ------------------
  |  Branch (157:23): [True: 39.8k, False: 656]
  ------------------
  158|  39.8k|                     exp_number = 10 * exp_number + digit;
  159|  39.8k|                  }
  160|  40.5k|                  ++p;
  161|  40.5k|               } while ((p != pend) && (digit = glz::fast_float::digit_value(*p)) <= 9);
  ------------------
  |  Branch (161:25): [True: 39.3k, False: 1.19k]
  |  Branch (161:40): [True: 25.1k, False: 14.1k]
  ------------------
  162|  15.3k|               if (neg_exp) {
  ------------------
  |  Branch (162:20): [True: 8.08k, False: 7.24k]
  ------------------
  163|  8.08k|                  exp_number = -exp_number;
  164|  8.08k|               }
  165|  15.3k|               exponent += exp_number;
  166|  15.3k|            }
  167|  15.3k|         }
  168|  2.18M|      }
  169|       |
  170|  2.18M|      answer.lastmatch = p;
  171|  2.18M|      answer.valid = true;
  172|       |
  173|       |      // If we frequently had to deal with long strings of digits,
  174|       |      // we could extend our code by using a 128-bit integer instead
  175|       |      // of a 64-bit integer. However, this is uncommon.
  176|       |      //
  177|       |      // We can deal with up to 19 digits.
  178|  2.18M|      if (digit_count > 19) { // this is uncommon
  ------------------
  |  Branch (178:11): [True: 23.3k, False: 2.16M]
  ------------------
  179|       |         // It is possible that the integer had an overflow.
  180|       |         // We have to handle the case where we have 0.0000somenumber.
  181|       |         // We need to be mindful of the case where we only have zeroes...
  182|       |         // E.g., 0.000000000...000.
  183|  23.3k|         UC const* start = start_digits;
  184|       |         if constexpr (null_terminated) {
  185|       |            while ((*start == UC('0') || *start == decimal_point)) {
  186|       |               if (*start == UC('0')) {
  187|       |                  --digit_count;
  188|       |               }
  189|       |               ++start;
  190|       |            }
  191|       |         }
  192|  23.3k|         else {
  193|  1.34M|            while ((start != pend) && (*start == UC('0') || *start == decimal_point)) {
  ------------------
  |  Branch (193:20): [True: 1.34M, False: 28]
  |  Branch (193:40): [True: 1.31M, False: 30.3k]
  |  Branch (193:61): [True: 7.03k, False: 23.3k]
  ------------------
  194|  1.32M|               if (*start == UC('0')) {
  ------------------
  |  Branch (194:20): [True: 1.31M, False: 7.03k]
  ------------------
  195|  1.31M|                  --digit_count;
  196|  1.31M|               }
  197|  1.32M|               ++start;
  198|  1.32M|            }
  199|  23.3k|         }
  200|       |
  201|  23.3k|         if (digit_count > 19) {
  ------------------
  |  Branch (201:14): [True: 23.0k, False: 323]
  ------------------
  202|  23.0k|            answer.too_many_digits = true;
  203|       |            // Let us start again, this time, avoiding overflows.
  204|       |            // We don't need to check if is_integer, since we use the
  205|       |            // pre-tokenized spans from above.
  206|  23.0k|            i = 0;
  207|  23.0k|            p = answer.integer.ptr;
  208|  23.0k|            UC const* int_end = p + answer.integer.len();
  209|  23.0k|            const uint64_t minimal_nineteen_digit_integer{1000000000000000000};
  210|   367k|            while ((i < minimal_nineteen_digit_integer) && (p != int_end)) {
  ------------------
  |  Branch (210:20): [True: 352k, False: 15.3k]
  |  Branch (210:60): [True: 344k, False: 7.71k]
  ------------------
  211|   344k|               i = i * 10 + uint64_t(*p - UC('0'));
  212|   344k|               ++p;
  213|   344k|            }
  214|  23.0k|            if (i >= minimal_nineteen_digit_integer) { // We have a big integers
  ------------------
  |  Branch (214:17): [True: 15.3k, False: 7.71k]
  ------------------
  215|  15.3k|               exponent = end_of_integer_part - p + exp_number;
  216|  15.3k|            }
  217|  7.71k|            else { // We have a value with a fractional component.
  218|  7.71k|               p = answer.fraction.ptr;
  219|  7.71k|               UC const* frac_end = p + answer.fraction.len();
  220|   107k|               while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) {
  ------------------
  |  Branch (220:23): [True: 100k, False: 7.71k]
  |  Branch (220:63): [True: 100k, False: 0]
  ------------------
  221|   100k|                  i = i * 10 + uint64_t(*p - UC('0'));
  222|   100k|                  ++p;
  223|   100k|               }
  224|  7.71k|               exponent = answer.fraction.ptr - p + exp_number;
  225|  7.71k|            }
  226|       |            // We have now corrected both exponent and i, to a truncated value
  227|  23.0k|         }
  228|  23.3k|      }
  229|  2.18M|      answer.exponent = exponent;
  230|  2.18M|      answer.mantissa = i;
  231|  2.18M|      return answer;
  232|  2.18M|   }
_ZZN3glz19parse_number_stringILb0EcEENS_10fast_float22parsed_number_string_tIT0_EEPKS3_S6_ENKUlvE_clEv:
   71|  2.18M|      const bool has_decimal_point = [&] {
   72|       |         if constexpr (null_terminated) {
   73|       |            return (*p == decimal_point);
   74|       |         }
   75|  2.18M|         else {
   76|  2.18M|            return (p != pend) && (*p == decimal_point);
  ------------------
  |  Branch (76:20): [True: 2.18M, False: 851]
  |  Branch (76:35): [True: 15.6k, False: 2.17M]
  ------------------
   77|  2.18M|         }
   78|  2.18M|      }();
_ZN3glz10from_charsILb1EdcEENS_10fast_float19from_chars_result_tIT1_EEPKS3_S6_RT0_:
  236|  4.38M|   {
  237|  4.38M|      using namespace glz::fast_float;
  238|  4.38M|      static_assert(is_supported_float_type<T>(), "only some floating-point types are supported");
  239|  4.38M|      static_assert(is_supported_char_type<UC>(), "only char, wchar_t, char16_t and char32_t are supported");
  240|       |
  241|  4.38M|      parsed_number_string_t<UC> pns = glz::parse_number_string<null_terminated, UC>(first, last);
  242|  4.38M|      if (!pns.valid) [[unlikely]] {
  ------------------
  |  Branch (242:11): [True: 2.97k, False: 4.37M]
  ------------------
  243|  2.97k|         return {.ptr = first, .ec = std::errc::invalid_argument};
  244|  2.97k|      }
  245|       |
  246|  4.37M|      return from_chars_advanced(pns, value);
  247|  4.38M|   }
_ZN3glz19parse_number_stringILb1EcEENS_10fast_float22parsed_number_string_tIT0_EEPKS3_S6_:
   18|  4.38M|   {
   19|  4.38M|      using namespace glz::fast_float;
   20|  4.38M|      static constexpr UC decimal_point = '.';
   21|       |
   22|  4.38M|      parsed_number_string_t<UC> answer;
   23|  4.38M|      answer.valid = false;
   24|  4.38M|      answer.too_many_digits = false;
   25|  4.38M|      answer.negative = (*p == UC('-'));
   26|  4.38M|      if (*p == UC('-')) { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here
  ------------------
  |  Branch (26:11): [True: 8.12k, False: 4.37M]
  ------------------
   27|  8.12k|         ++p;
   28|       |
   29|       |         if constexpr (not null_terminated) {
   30|       |            if (p == pend) [[unlikely]] {
   31|       |               return answer;
   32|       |            }
   33|       |         }
   34|       |
   35|  8.12k|         if (!glz::fast_float::is_integer(*p)) [[unlikely]] { // a sign must be followed by an integer
  ------------------
  |  Branch (35:14): [True: 56, False: 8.06k]
  ------------------
   36|     56|            return answer;
   37|     56|         }
   38|  8.12k|      }
   39|  4.38M|      UC const* const start_digits = p;
   40|       |
   41|  4.38M|      uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad)
   42|       |
   43|  4.38M|      uint64_t digit;
   44|  4.38M|      if constexpr (null_terminated) {
   45|  24.0M|         while ((digit = glz::fast_float::digit_value(*p)) <= 9) {
  ------------------
  |  Branch (45:17): [True: 19.6M, False: 4.38M]
  ------------------
   46|       |            // a multiplication by 10 is cheaper than an arbitrary integer
   47|       |            // multiplication
   48|  19.6M|            i = 10 * i + digit; // might overflow, we will handle the overflow later
   49|  19.6M|            ++p;
   50|  19.6M|         }
   51|       |      }
   52|       |      else {
   53|       |         while ((p != pend) && (digit = glz::fast_float::digit_value(*p)) <= 9) {
   54|       |            // a multiplication by 10 is cheaper than an arbitrary integer
   55|       |            // multiplication
   56|       |            i = 10 * i + digit; // might overflow, we will handle the overflow later
   57|       |            ++p;
   58|       |         }
   59|       |      }
   60|       |
   61|  4.38M|      UC const* const end_of_integer_part = p;
   62|  4.38M|      int64_t digit_count = int64_t(end_of_integer_part - start_digits);
   63|  4.38M|      answer.integer = glz::fast_float::span<const UC>(start_digits, size_t(digit_count));
   64|       |
   65|       |      // at least 1 digit in integer part, without leading zeros
   66|  4.38M|      if (digit_count == 0 || (start_digits[0] == UC('0') && digit_count > 1)) {
  ------------------
  |  Branch (66:11): [True: 2.71k, False: 4.37M]
  |  Branch (66:32): [True: 1.83M, False: 2.54M]
  |  Branch (66:62): [True: 144, False: 1.82M]
  ------------------
   67|  2.86k|         return answer;
   68|  2.86k|      }
   69|       |
   70|  4.37M|      int64_t exponent = 0;
   71|  4.37M|      const bool has_decimal_point = [&] {
   72|  4.37M|         if constexpr (null_terminated) {
   73|  4.37M|            return (*p == decimal_point);
   74|  4.37M|         }
   75|  4.37M|         else {
   76|  4.37M|            return (p != pend) && (*p == decimal_point);
   77|  4.37M|         }
   78|  4.37M|      }();
   79|  4.37M|      if (has_decimal_point) {
  ------------------
  |  Branch (79:11): [True: 31.3k, False: 4.34M]
  ------------------
   80|  31.3k|         ++p;
   81|  31.3k|         UC const* before = p;
   82|       |         // can occur at most twice without overflowing, but let it occur more, since
   83|       |         // for integers with many digits, digit parsing is the primary bottleneck.
   84|  31.3k|         loop_parse_if_eight_digits(p, pend, i);
   85|       |
   86|  31.3k|         if constexpr (null_terminated) {
   87|   122k|            while ((digit = glz::fast_float::digit_value(*p)) <= 9) {
  ------------------
  |  Branch (87:20): [True: 90.6k, False: 31.3k]
  ------------------
   88|  90.6k|               ++p;
   89|  90.6k|               i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
   90|  90.6k|            }
   91|       |         }
   92|       |         else {
   93|       |            while ((p != pend) && (digit = glz::fast_float::digit_value(*p)) <= 9) {
   94|       |               ++p;
   95|       |               i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
   96|       |            }
   97|       |         }
   98|  31.3k|         exponent = before - p;
   99|  31.3k|         answer.fraction = glz::fast_float::span<const UC>(before, size_t(p - before));
  100|  31.3k|         digit_count -= exponent;
  101|  31.3k|      }
  102|       |      // at least 1 digit in fractional part
  103|  4.37M|      if (has_decimal_point && exponent == 0) {
  ------------------
  |  Branch (103:11): [True: 31.3k, False: 4.34M]
  |  Branch (103:32): [True: 62, False: 31.2k]
  ------------------
  104|     62|         return answer;
  105|     62|      }
  106|       |
  107|  4.37M|      int64_t exp_number = 0; // explicit exponential part
  108|       |
  109|  4.37M|      if constexpr (null_terminated) {
  110|  4.37M|         if ((UC('e') == *p) || (UC('E') == *p)) {
  ------------------
  |  Branch (110:14): [True: 15.1k, False: 4.36M]
  |  Branch (110:33): [True: 15.6k, False: 4.34M]
  ------------------
  111|  30.7k|            UC const* location_of_e = p;
  112|  30.7k|            ++p;
  113|  30.7k|            bool neg_exp = false;
  114|  30.7k|            if (UC('-') == *p) {
  ------------------
  |  Branch (114:17): [True: 16.1k, False: 14.5k]
  ------------------
  115|  16.1k|               neg_exp = true;
  116|  16.1k|               ++p;
  117|  16.1k|            }
  118|  14.5k|            else if (UC('+') == *p) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
  ------------------
  |  Branch (118:22): [True: 656, False: 13.9k]
  ------------------
  119|    656|               ++p;
  120|    656|            }
  121|  30.7k|            if ((digit = glz::fast_float::digit_value(*p)) > 9) {
  ------------------
  |  Branch (121:17): [True: 98, False: 30.6k]
  ------------------
  122|       |               // Otherwise, we will be ignoring the 'e'.
  123|     98|               p = location_of_e;
  124|     98|            }
  125|  30.6k|            else {
  126|  81.0k|               do {
  127|  81.0k|                  if (exp_number < 0x10000000) {
  ------------------
  |  Branch (127:23): [True: 79.7k, False: 1.31k]
  ------------------
  128|  79.7k|                     exp_number = 10 * exp_number + digit;
  129|  79.7k|                  }
  130|  81.0k|                  ++p;
  131|  81.0k|               } while ((digit = glz::fast_float::digit_value(*p)) <= 9);
  ------------------
  |  Branch (131:25): [True: 50.3k, False: 30.6k]
  ------------------
  132|  30.6k|               if (neg_exp) {
  ------------------
  |  Branch (132:20): [True: 16.1k, False: 14.4k]
  ------------------
  133|  16.1k|                  exp_number = -exp_number;
  134|  16.1k|               }
  135|  30.6k|               exponent += exp_number;
  136|  30.6k|            }
  137|  30.7k|         }
  138|       |      }
  139|       |      else {
  140|       |         if ((p != pend) && ((UC('e') == *p) || (UC('E') == *p))) {
  141|       |            UC const* location_of_e = p;
  142|       |            ++p;
  143|       |            bool neg_exp = false;
  144|       |            if ((p != pend) && (UC('-') == *p)) {
  145|       |               neg_exp = true;
  146|       |               ++p;
  147|       |            }
  148|       |            else if ((p != pend) && (UC('+') == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1)
  149|       |               ++p;
  150|       |            }
  151|       |            if ((p == pend) || (digit = glz::fast_float::digit_value(*p)) > 9) {
  152|       |               // Otherwise, we will be ignoring the 'e'.
  153|       |               p = location_of_e;
  154|       |            }
  155|       |            else {
  156|       |               do {
  157|       |                  if (exp_number < 0x10000000) {
  158|       |                     exp_number = 10 * exp_number + digit;
  159|       |                  }
  160|       |                  ++p;
  161|       |               } while ((p != pend) && (digit = glz::fast_float::digit_value(*p)) <= 9);
  162|       |               if (neg_exp) {
  163|       |                  exp_number = -exp_number;
  164|       |               }
  165|       |               exponent += exp_number;
  166|       |            }
  167|       |         }
  168|       |      }
  169|       |
  170|  4.37M|      answer.lastmatch = p;
  171|  4.37M|      answer.valid = true;
  172|       |
  173|       |      // If we frequently had to deal with long strings of digits,
  174|       |      // we could extend our code by using a 128-bit integer instead
  175|       |      // of a 64-bit integer. However, this is uncommon.
  176|       |      //
  177|       |      // We can deal with up to 19 digits.
  178|  4.37M|      if (digit_count > 19) { // this is uncommon
  ------------------
  |  Branch (178:11): [True: 46.7k, False: 4.33M]
  ------------------
  179|       |         // It is possible that the integer had an overflow.
  180|       |         // We have to handle the case where we have 0.0000somenumber.
  181|       |         // We need to be mindful of the case where we only have zeroes...
  182|       |         // E.g., 0.000000000...000.
  183|  46.7k|         UC const* start = start_digits;
  184|  46.7k|         if constexpr (null_terminated) {
  185|  2.68M|            while ((*start == UC('0') || *start == decimal_point)) {
  ------------------
  |  Branch (185:21): [True: 2.62M, False: 60.8k]
  |  Branch (185:42): [True: 14.0k, False: 46.7k]
  ------------------
  186|  2.64M|               if (*start == UC('0')) {
  ------------------
  |  Branch (186:20): [True: 2.62M, False: 14.0k]
  ------------------
  187|  2.62M|                  --digit_count;
  188|  2.62M|               }
  189|  2.64M|               ++start;
  190|  2.64M|            }
  191|       |         }
  192|       |         else {
  193|       |            while ((start != pend) && (*start == UC('0') || *start == decimal_point)) {
  194|       |               if (*start == UC('0')) {
  195|       |                  --digit_count;
  196|       |               }
  197|       |               ++start;
  198|       |            }
  199|       |         }
  200|       |
  201|  46.7k|         if (digit_count > 19) {
  ------------------
  |  Branch (201:14): [True: 46.0k, False: 646]
  ------------------
  202|  46.0k|            answer.too_many_digits = true;
  203|       |            // Let us start again, this time, avoiding overflows.
  204|       |            // We don't need to check if is_integer, since we use the
  205|       |            // pre-tokenized spans from above.
  206|  46.0k|            i = 0;
  207|  46.0k|            p = answer.integer.ptr;
  208|  46.0k|            UC const* int_end = p + answer.integer.len();
  209|  46.0k|            const uint64_t minimal_nineteen_digit_integer{1000000000000000000};
  210|   735k|            while ((i < minimal_nineteen_digit_integer) && (p != int_end)) {
  ------------------
  |  Branch (210:20): [True: 705k, False: 30.6k]
  |  Branch (210:60): [True: 689k, False: 15.4k]
  ------------------
  211|   689k|               i = i * 10 + uint64_t(*p - UC('0'));
  212|   689k|               ++p;
  213|   689k|            }
  214|  46.0k|            if (i >= minimal_nineteen_digit_integer) { // We have a big integers
  ------------------
  |  Branch (214:17): [True: 30.6k, False: 15.4k]
  ------------------
  215|  30.6k|               exponent = end_of_integer_part - p + exp_number;
  216|  30.6k|            }
  217|  15.4k|            else { // We have a value with a fractional component.
  218|  15.4k|               p = answer.fraction.ptr;
  219|  15.4k|               UC const* frac_end = p + answer.fraction.len();
  220|   215k|               while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) {
  ------------------
  |  Branch (220:23): [True: 200k, False: 15.4k]
  |  Branch (220:63): [True: 200k, False: 0]
  ------------------
  221|   200k|                  i = i * 10 + uint64_t(*p - UC('0'));
  222|   200k|                  ++p;
  223|   200k|               }
  224|  15.4k|               exponent = answer.fraction.ptr - p + exp_number;
  225|  15.4k|            }
  226|       |            // We have now corrected both exponent and i, to a truncated value
  227|  46.0k|         }
  228|  46.7k|      }
  229|  4.37M|      answer.exponent = exponent;
  230|  4.37M|      answer.mantissa = i;
  231|  4.37M|      return answer;
  232|  4.37M|   }
_ZZN3glz19parse_number_stringILb1EcEENS_10fast_float22parsed_number_string_tIT0_EEPKS3_S6_ENKUlvE_clEv:
   71|  4.37M|      const bool has_decimal_point = [&] {
   72|  4.37M|         if constexpr (null_terminated) {
   73|  4.37M|            return (*p == decimal_point);
   74|       |         }
   75|       |         else {
   76|       |            return (p != pend) && (*p == decimal_point);
   77|       |         }
   78|  4.37M|      }();

_ZN3glz7skip_wsIXtlNS_7ws_optsEEETkNS_10is_contextERNS_7contextERPKcS5_EEbOT0_OT1_T2_:
  622|  8.95M|   {
  623|  8.95M|      using namespace glz::detail;
  624|       |
  625|  8.95M|      if constexpr (not Opts.minified) {
  626|       |         if constexpr (Opts.null_terminated) {
  627|       |            if constexpr (Opts.comments) {
  628|       |               while (whitespace_comment_table[uint8_t(*it)]) {
  629|       |                  if (*it == '/') [[unlikely]] {
  630|       |                     skip_comment(ctx, it, end);
  631|       |                     if (bool(ctx.error)) [[unlikely]] {
  632|       |                        return true;
  633|       |                     }
  634|       |                  }
  635|       |                  else [[likely]] {
  636|       |                     ++it;
  637|       |                  }
  638|       |               }
  639|       |            }
  640|       |            else {
  641|       |               while (whitespace_table[uint8_t(*it)]) {
  642|       |                  ++it;
  643|       |               }
  644|       |            }
  645|       |         }
  646|  8.95M|         else {
  647|       |            if constexpr (Opts.comments) {
  648|       |               while (it < end && whitespace_comment_table[uint8_t(*it)]) {
  649|       |                  if (*it == '/') [[unlikely]] {
  650|       |                     skip_comment(ctx, it, end);
  651|       |                     if (bool(ctx.error)) [[unlikely]] {
  652|       |                        return true;
  653|       |                     }
  654|       |                  }
  655|       |                  else [[likely]] {
  656|       |                     ++it;
  657|       |                  }
  658|       |               }
  659|       |               if (it == end) [[unlikely]] {
  660|       |                  ctx.error = error_code::end_reached;
  661|       |                  return true;
  662|       |               }
  663|       |            }
  664|  8.95M|            else {
  665|  26.7M|               while (it < end && whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (665:23): [True: 26.7M, False: 1.53k]
  |  Branch (665:35): [True: 17.7M, False: 8.95M]
  ------------------
  666|  17.7M|                  ++it;
  667|  17.7M|               }
  668|  8.95M|               if (it == end) [[unlikely]] {
  ------------------
  |  Branch (668:20): [True: 1.53k, False: 8.95M]
  ------------------
  669|  1.53k|                  ctx.error = error_code::end_reached;
  670|  1.53k|                  return true;
  671|  1.53k|               }
  672|  8.95M|            }
  673|  8.95M|         }
  674|       |      }
  675|       |      else if constexpr (not Opts.null_terminated) {
  676|       |         // Minified input has no whitespace to skip, but a non-null-terminated buffer can still
  677|       |         // be exhausted at this point. The non-minified branch above performs the same check; a
  678|       |         // null-terminated buffer relies on the trailing sentinel and keeps this a pure no-op.
  679|       |         if (it == end) [[unlikely]] {
  680|       |            ctx.error = error_code::end_reached;
  681|       |            return true;
  682|       |         }
  683|       |      }
  684|       |
  685|  8.95M|      return false;
  686|  8.95M|   }
_ZN3glz17match_invalid_endILc44EXtlNS_22match_invalid_end_optsEEETkNS_10is_contextENS_7contextERPKcS4_EEbRT1_OT2_T3_:
  411|  1.08M|   {
  412|  1.08M|      if (*it != C) [[unlikely]] {
  ------------------
  |  Branch (412:11): [True: 303, False: 1.08M]
  ------------------
  413|       |         if constexpr (C == '"') {
  414|       |            ctx.error = error_code::expected_quote;
  415|       |         }
  416|    303|         else if constexpr (C == ',') {
  417|    303|            ctx.error = error_code::expected_comma;
  418|       |         }
  419|       |         else if constexpr (C == ':') {
  420|       |            ctx.error = error_code::expected_colon;
  421|       |         }
  422|       |         else if constexpr (C == '[' || C == ']') {
  423|       |            ctx.error = error_code::expected_bracket;
  424|       |         }
  425|       |         else if constexpr (C == '{' || C == '}') {
  426|       |            ctx.error = error_code::expected_brace;
  427|       |         }
  428|       |         else {
  429|       |            ctx.error = error_code::syntax_error;
  430|       |         }
  431|    303|         return true;
  432|    303|      }
  433|  1.08M|      else [[likely]] {
  434|  1.08M|         ++it;
  435|  1.08M|      }
  436|  1.08M|      if constexpr (not Opts.null_terminated) {
  437|  1.08M|         if (it == end) [[unlikely]] {
  ------------------
  |  Branch (437:14): [True: 46, False: 1.08M]
  ------------------
  438|     46|            ctx.error = error_code::unexpected_end;
  439|     46|            return true;
  440|     46|         }
  441|  1.08M|      }
  442|  1.08M|      return false;
  443|  1.08M|   }
_ZN3glz17match_invalid_endILc34EXtlNS_22match_invalid_end_optsEEETkNS_10is_contextENS_7contextERPKcS4_EEbRT1_OT2_T3_:
  411|  1.12M|   {
  412|  1.12M|      if (*it != C) [[unlikely]] {
  ------------------
  |  Branch (412:11): [True: 226, False: 1.12M]
  ------------------
  413|    226|         if constexpr (C == '"') {
  414|    226|            ctx.error = error_code::expected_quote;
  415|       |         }
  416|       |         else if constexpr (C == ',') {
  417|       |            ctx.error = error_code::expected_comma;
  418|       |         }
  419|       |         else if constexpr (C == ':') {
  420|       |            ctx.error = error_code::expected_colon;
  421|       |         }
  422|       |         else if constexpr (C == '[' || C == ']') {
  423|       |            ctx.error = error_code::expected_bracket;
  424|       |         }
  425|       |         else if constexpr (C == '{' || C == '}') {
  426|       |            ctx.error = error_code::expected_brace;
  427|       |         }
  428|       |         else {
  429|       |            ctx.error = error_code::syntax_error;
  430|       |         }
  431|    226|         return true;
  432|    226|      }
  433|  1.12M|      else [[likely]] {
  434|  1.12M|         ++it;
  435|  1.12M|      }
  436|  1.12M|      if constexpr (not Opts.null_terminated) {
  437|  1.12M|         if (it == end) [[unlikely]] {
  ------------------
  |  Branch (437:14): [True: 143, False: 1.12M]
  ------------------
  438|    143|            ctx.error = error_code::unexpected_end;
  439|    143|            return true;
  440|    143|         }
  441|  1.12M|      }
  442|  1.12M|      return false;
  443|  1.12M|   }
_ZN3glz9has_quoteEm:
  534|  16.2M|   {
  535|  16.2M|      return has_zero(chunk ^ repeat_byte8('"'));
  536|  16.2M|   }
_ZN3glz8has_zeroEm:
  529|  16.2M|   {
  530|  16.2M|      return (((chunk - 0x0101010101010101u) & ~chunk) & 0x8080808080808080u);
  531|  16.2M|   }
_ZN3glz18validate_utf8_spanITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextEccEEbOT0_PKT1_PKT2_m:
  832|  1.11M|   {
  833|       |      if constexpr (not check_validate_utf8(Opts)) {
  834|       |         // Everything the caller computed for us is dead, which lets its scan loop drop the
  835|       |         // accumulator entirely.
  836|       |         (void)ctx, (void)start, (void)fin, (void)ascii_acc;
  837|       |         return false;
  838|       |      }
  839|  1.11M|      else {
  840|  1.11M|         if ((ascii_acc & repeat_byte8(0b10000000)) == 0) {
  ------------------
  |  Branch (840:14): [True: 1.07M, False: 38.2k]
  ------------------
  841|  1.07M|            return false; // pure ASCII is trivially well formed UTF-8
  842|  1.07M|         }
  843|  38.2k|         if (!validate_utf8(start, size_t(fin - start))) [[unlikely]] {
  ------------------
  |  Branch (843:14): [True: 246, False: 37.9k]
  ------------------
  844|    246|            ctx.error = error_code::invalid_utf8;
  845|    246|            return true;
  846|    246|         }
  847|  37.9k|         return false;
  848|  38.2k|      }
  849|  1.11M|   }
_ZN3glz13validate_utf8IcEEbPKT_m:
  801|   118k|   {
  802|   118k|      const uint8_t* it = reinterpret_cast<const uint8_t*>(str);
  803|   118k|      const uint8_t* const end = it + size;
  804|       |#if defined(GLZ_UTF8_SIMD)
  805|       |      // 16 is a measured compromise, not a register-size coincidence. The scalar path skips ASCII 8
  806|       |      // bytes at a time, so on ASCII it stays ahead of the vector path's fixed setup cost until the
  807|       |      // input is long enough for the 64 byte ASCII step to engage; on non-ASCII the vector path
  808|       |      // wins from roughly 8 bytes. Raising the threshold buys a few percent on short ASCII and
  809|       |      // costs up to 2.3x on mid length non-ASCII strings, so it stays low.
  810|       |      if (size >= 16) {
  811|       |         return detail::utf8_simd::validate(it, end);
  812|       |      }
  813|       |#endif
  814|   118k|      return validate_utf8_scalar(it, end);
  815|   118k|   }
_ZN3glz20validate_utf8_scalarEPKhS1_:
  752|   118k|   {
  753|  1.90M|      while (it < end) {
  ------------------
  |  Branch (753:14): [True: 1.79M, False: 117k]
  ------------------
  754|       |         // Optimistic SWAR check for ASCII
  755|  1.79M|         if (it + 8 <= end) {
  ------------------
  |  Branch (755:14): [True: 1.50M, False: 289k]
  ------------------
  756|  1.50M|            uint64_t chunk;
  757|  1.50M|            std::memcpy(&chunk, it, 8);
  758|  1.50M|            if ((chunk & glz::repeat_byte8(0x80)) == 0) {
  ------------------
  |  Branch (758:17): [True: 1.39M, False: 104k]
  ------------------
  759|  1.39M|               it += 8;
  760|  1.39M|               continue;
  761|  1.39M|            }
  762|  1.50M|         }
  763|       |
  764|       |         // Byte-by-byte validation (standard conformant)
  765|   394k|         uint8_t byte = *it;
  766|       |
  767|   394k|         if (byte < 0x80) {
  ------------------
  |  Branch (767:14): [True: 290k, False: 104k]
  ------------------
  768|   290k|            it++;
  769|   290k|         }
  770|   104k|         else if ((byte & 0xE0) == 0xC0) {
  ------------------
  |  Branch (770:19): [True: 92.4k, False: 11.7k]
  ------------------
  771|       |            // 2-byte sequence
  772|  92.4k|            if (it + 2 > end || (it[1] & 0xC0) != 0x80) return false;
  ------------------
  |  Branch (772:17): [True: 51, False: 92.4k]
  |  Branch (772:33): [True: 136, False: 92.2k]
  ------------------
  773|  92.2k|            if (byte < 0xC2) return false; // Overlong
  ------------------
  |  Branch (773:17): [True: 53, False: 92.2k]
  ------------------
  774|  92.2k|            it += 2;
  775|  92.2k|         }
  776|  11.7k|         else if ((byte & 0xF0) == 0xE0) {
  ------------------
  |  Branch (776:19): [True: 5.31k, False: 6.45k]
  ------------------
  777|       |            // 3-byte sequence
  778|  5.31k|            if (it + 3 > end || (it[1] & 0xC0) != 0x80 || (it[2] & 0xC0) != 0x80) return false;
  ------------------
  |  Branch (778:17): [True: 29, False: 5.28k]
  |  Branch (778:33): [True: 73, False: 5.21k]
  |  Branch (778:59): [True: 90, False: 5.12k]
  ------------------
  779|  5.12k|            if (byte == 0xE0 && it[1] < 0xA0) return false; // Overlong
  ------------------
  |  Branch (779:17): [True: 1.81k, False: 3.30k]
  |  Branch (779:33): [True: 83, False: 1.72k]
  ------------------
  780|  5.03k|            if (byte == 0xED && it[1] >= 0xA0) return false; // Surrogate
  ------------------
  |  Branch (780:17): [True: 1.45k, False: 3.58k]
  |  Branch (780:33): [True: 54, False: 1.39k]
  ------------------
  781|  4.98k|            it += 3;
  782|  4.98k|         }
  783|  6.45k|         else if ((byte & 0xF8) == 0xF0) {
  ------------------
  |  Branch (783:19): [True: 5.97k, False: 484]
  ------------------
  784|       |            // 4-byte sequence
  785|  5.97k|            if (it + 4 > end || (it[1] & 0xC0) != 0x80 || (it[2] & 0xC0) != 0x80 || (it[3] & 0xC0) != 0x80)
  ------------------
  |  Branch (785:17): [True: 33, False: 5.93k]
  |  Branch (785:33): [True: 81, False: 5.85k]
  |  Branch (785:59): [True: 62, False: 5.79k]
  |  Branch (785:85): [True: 76, False: 5.71k]
  ------------------
  786|    252|               return false;
  787|  5.71k|            if (byte == 0xF0 && it[1] < 0x90) return false; // Overlong
  ------------------
  |  Branch (787:17): [True: 1.66k, False: 4.05k]
  |  Branch (787:33): [True: 70, False: 1.59k]
  ------------------
  788|  5.64k|            if (byte == 0xF4 && it[1] >= 0x90) return false; // > U+10FFFF
  ------------------
  |  Branch (788:17): [True: 1.67k, False: 3.97k]
  |  Branch (788:33): [True: 41, False: 1.63k]
  ------------------
  789|  5.60k|            if (byte > 0xF4) return false; // > U+10FFFF
  ------------------
  |  Branch (789:17): [True: 38, False: 5.57k]
  ------------------
  790|  5.57k|            it += 4;
  791|  5.57k|         }
  792|    484|         else {
  793|    484|            return false;
  794|    484|         }
  795|   394k|      }
  796|       |
  797|   117k|      return true;
  798|   118k|   }
_ZN3glz25handle_unicode_code_pointIccEEjRPKT_RPT0_S3_:
  288|  29.3k|   {
  289|  29.3k|      using namespace unicode;
  290|       |
  291|  29.3k|      if (it + 4 >= end) [[unlikely]] {
  ------------------
  |  Branch (291:11): [True: 114, False: 29.2k]
  ------------------
  292|    114|         return false;
  293|    114|      }
  294|  29.2k|      const uint32_t high = hex_to_u32(it);
  295|  29.2k|      if (high == 0xFFFFFFFFu) [[unlikely]] {
  ------------------
  |  Branch (295:11): [True: 202, False: 29.0k]
  ------------------
  296|    202|         return false;
  297|    202|      }
  298|  29.0k|      it += 4; // skip the code point characters
  299|       |
  300|  29.0k|      uint32_t code_point;
  301|       |
  302|  29.0k|      if ((high & generic_surrogate_mask) == generic_surrogate_value) {
  ------------------
  |  Branch (302:11): [True: 3.54k, False: 25.4k]
  ------------------
  303|       |         // surrogate pair code points
  304|  3.54k|         if ((high & surrogate_mask) != high_surrogate_value) {
  ------------------
  |  Branch (304:14): [True: 33, False: 3.50k]
  ------------------
  305|     33|            return false;
  306|     33|         }
  307|       |
  308|  3.50k|         if (it + 6 >= end) [[unlikely]] {
  ------------------
  |  Branch (308:14): [True: 79, False: 3.42k]
  ------------------
  309|     79|            return false;
  310|     79|         }
  311|       |         // The next two characters must be `\u`
  312|  3.42k|         uint16_t u;
  313|  3.42k|         std::memcpy(&u, it, 2);
  314|  3.42k|         if (u != to_uint16_t(R"(\u)")) [[unlikely]] {
  ------------------
  |  Branch (314:14): [True: 341, False: 3.08k]
  ------------------
  315|    341|            return false;
  316|    341|         }
  317|  3.08k|         it += 2;
  318|       |         // verify that second unicode escape sequence is present
  319|  3.08k|         const uint32_t low = hex_to_u32(it);
  320|  3.08k|         if (low == 0xFFFFFFFFu) [[unlikely]] {
  ------------------
  |  Branch (320:14): [True: 75, False: 3.01k]
  ------------------
  321|     75|            return false;
  322|     75|         }
  323|  3.01k|         it += 4;
  324|       |
  325|  3.01k|         if ((low & surrogate_mask) != low_surrogate_value) [[unlikely]] {
  ------------------
  |  Branch (325:14): [True: 177, False: 2.83k]
  ------------------
  326|    177|            return false;
  327|    177|         }
  328|       |
  329|  2.83k|         code_point = (high & surrogate_codepoint_mask) << surrogate_codepoint_bits;
  330|  2.83k|         code_point |= (low & surrogate_codepoint_mask);
  331|  2.83k|         code_point += surrogate_codepoint_offset;
  332|  2.83k|      }
  333|  25.4k|      else {
  334|  25.4k|         code_point = high;
  335|  25.4k|      }
  336|  28.3k|      const uint32_t offset = code_point_to_utf8(code_point, dst);
  337|  28.3k|      dst += offset;
  338|  28.3k|      return offset;
  339|  29.0k|   }
_ZN3glz10hex_to_u32EPKc:
  203|  32.3k|   {
  204|  32.3k|      constexpr auto& t = digit_hex_table;
  205|  32.3k|      const uint8_t arr[4]{t[uint8_t(c[3])], t[uint8_t(c[2])], t[uint8_t(c[1])], t[uint8_t(c[0])]};
  206|  32.3k|      auto chunk = std::bit_cast<uint32_t>(arr);
  207|       |      // On big-endian, bit_cast produces bytes in opposite order than expected
  208|       |      // byteswap to get consistent little-endian representation
  209|       |      if constexpr (std::endian::native == std::endian::big) {
  210|       |         chunk = std::byteswap(chunk);
  211|       |      }
  212|       |      // check that all hex characters are valid
  213|  32.3k|      if (chunk & repeat_byte4(0b11110000u)) [[unlikely]] {
  ------------------
  |  Branch (213:11): [True: 277, False: 32.0k]
  ------------------
  214|    277|         return 0xFFFFFFFFu;
  215|    277|      }
  216|       |
  217|       |      // now pack into first four bytes of uint32_t
  218|  32.0k|      uint32_t packed{};
  219|  32.0k|      packed |= (chunk & 0x0000000F);
  220|  32.0k|      packed |= (chunk & 0x00000F00) >> 4;
  221|  32.0k|      packed |= (chunk & 0x000F0000) >> 8;
  222|  32.0k|      packed |= (chunk & 0x0F000000) >> 12;
  223|  32.0k|      return packed;
  224|  32.3k|   }
_ZN3glz18code_point_to_utf8IcEEjjPT_:
  228|  28.3k|   {
  229|  28.3k|      if (code_point <= 0x7F) {
  ------------------
  |  Branch (229:11): [True: 10.7k, False: 17.5k]
  ------------------
  230|  10.7k|         c[0] = Char(code_point);
  231|  10.7k|         return 1;
  232|  10.7k|      }
  233|  17.5k|      if (code_point <= 0x7FF) {
  ------------------
  |  Branch (233:11): [True: 8.40k, False: 9.16k]
  ------------------
  234|  8.40k|         c[0] = Char(0xC0 | ((code_point >> 6) & 0x1F));
  235|  8.40k|         c[1] = Char(0x80 | (code_point & 0x3F));
  236|  8.40k|         return 2;
  237|  8.40k|      }
  238|  9.16k|      if (code_point <= 0xFFFF) {
  ------------------
  |  Branch (238:11): [True: 6.32k, False: 2.83k]
  ------------------
  239|  6.32k|         c[0] = Char(0xE0 | ((code_point >> 12) & 0x0F));
  240|  6.32k|         c[1] = Char(0x80 | ((code_point >> 6) & 0x3F));
  241|  6.32k|         c[2] = Char(0x80 | (code_point & 0x3F));
  242|  6.32k|         return 3;
  243|  6.32k|      }
  244|  2.83k|      if (code_point <= 0x10FFFF) {
  ------------------
  |  Branch (244:11): [True: 2.83k, False: 0]
  ------------------
  245|  2.83k|         c[0] = Char(0xF0 | ((code_point >> 18) & 0x07));
  246|  2.83k|         c[1] = Char(0x80 | ((code_point >> 12) & 0x3F));
  247|  2.83k|         c[2] = Char(0x80 | ((code_point >> 6) & 0x3F));
  248|  2.83k|         c[3] = Char(0x80 | (code_point & 0x3F));
  249|  2.83k|         return 4;
  250|  2.83k|      }
  251|      0|      return 0;
  252|  2.83k|   }
_ZN3glz17match_invalid_endILc58EXtlNS_22match_invalid_end_optsEEETkNS_10is_contextENS_7contextERPKcS4_EEbRT1_OT2_T3_:
  411|  1.11M|   {
  412|  1.11M|      if (*it != C) [[unlikely]] {
  ------------------
  |  Branch (412:11): [True: 440, False: 1.11M]
  ------------------
  413|       |         if constexpr (C == '"') {
  414|       |            ctx.error = error_code::expected_quote;
  415|       |         }
  416|       |         else if constexpr (C == ',') {
  417|       |            ctx.error = error_code::expected_comma;
  418|       |         }
  419|    440|         else if constexpr (C == ':') {
  420|    440|            ctx.error = error_code::expected_colon;
  421|       |         }
  422|       |         else if constexpr (C == '[' || C == ']') {
  423|       |            ctx.error = error_code::expected_bracket;
  424|       |         }
  425|       |         else if constexpr (C == '{' || C == '}') {
  426|       |            ctx.error = error_code::expected_brace;
  427|       |         }
  428|       |         else {
  429|       |            ctx.error = error_code::syntax_error;
  430|       |         }
  431|    440|         return true;
  432|    440|      }
  433|  1.11M|      else [[likely]] {
  434|  1.11M|         ++it;
  435|  1.11M|      }
  436|  1.11M|      if constexpr (not Opts.null_terminated) {
  437|  1.11M|         if (it == end) [[unlikely]] {
  ------------------
  |  Branch (437:14): [True: 1.11k, False: 1.11M]
  ------------------
  438|  1.11k|            ctx.error = error_code::unexpected_end;
  439|  1.11k|            return true;
  440|  1.11k|         }
  441|  1.11M|      }
  442|  1.11M|      return false;
  443|  1.11M|   }
_ZN3glz17match_invalid_endILc91EXtlNS_22match_invalid_end_optsEEETkNS_10is_contextENS_7contextERPKcS4_EEbRT1_OT2_T3_:
  411|   598k|   {
  412|   598k|      if (*it != C) [[unlikely]] {
  ------------------
  |  Branch (412:11): [True: 0, False: 598k]
  ------------------
  413|       |         if constexpr (C == '"') {
  414|       |            ctx.error = error_code::expected_quote;
  415|       |         }
  416|       |         else if constexpr (C == ',') {
  417|       |            ctx.error = error_code::expected_comma;
  418|       |         }
  419|       |         else if constexpr (C == ':') {
  420|       |            ctx.error = error_code::expected_colon;
  421|       |         }
  422|      0|         else if constexpr (C == '[' || C == ']') {
  423|      0|            ctx.error = error_code::expected_bracket;
  424|       |         }
  425|       |         else if constexpr (C == '{' || C == '}') {
  426|       |            ctx.error = error_code::expected_brace;
  427|       |         }
  428|       |         else {
  429|       |            ctx.error = error_code::syntax_error;
  430|       |         }
  431|      0|         return true;
  432|      0|      }
  433|   598k|      else [[likely]] {
  434|   598k|         ++it;
  435|   598k|      }
  436|   598k|      if constexpr (not Opts.null_terminated) {
  437|   598k|         if (it == end) [[unlikely]] {
  ------------------
  |  Branch (437:14): [True: 114, False: 598k]
  ------------------
  438|    114|            ctx.error = error_code::unexpected_end;
  439|    114|            return true;
  440|    114|         }
  441|   598k|      }
  442|   598k|      return false;
  443|   598k|   }
_ZN3glz16skip_matching_wsIcRPKcEEvPKT_OT0_m:
  689|  51.8k|   {
  690|  51.8k|      if (length > 7) {
  ------------------
  |  Branch (690:11): [True: 11.1k, False: 40.6k]
  ------------------
  691|  11.1k|         uint64_t v[2];
  692|  15.6k|         while (length > 8) {
  ------------------
  |  Branch (692:17): [True: 9.61k, False: 6.00k]
  ------------------
  693|  9.61k|            std::memcpy(v, ws, 8);
  694|  9.61k|            std::memcpy(v + 1, it, 8);
  695|  9.61k|            if (v[0] != v[1]) {
  ------------------
  |  Branch (695:17): [True: 5.17k, False: 4.44k]
  ------------------
  696|  5.17k|               return;
  697|  5.17k|            }
  698|  4.44k|            length -= 8;
  699|  4.44k|            ws += 8;
  700|  4.44k|            it += 8;
  701|  4.44k|         }
  702|       |
  703|  6.00k|         const auto shift = 8 - length;
  704|  6.00k|         ws -= shift;
  705|  6.00k|         it -= shift;
  706|       |
  707|  6.00k|         std::memcpy(v, ws, 8);
  708|  6.00k|         std::memcpy(v + 1, it, 8);
  709|  6.00k|         if (v[0] != v[1]) {
  ------------------
  |  Branch (709:14): [True: 3.91k, False: 2.08k]
  ------------------
  710|  3.91k|            return;
  711|  3.91k|         }
  712|  2.08k|         it += 8;
  713|  2.08k|         return;
  714|  6.00k|      }
  715|  40.6k|      {
  716|  40.6k|         constexpr uint64_t n{sizeof(uint32_t)};
  717|  40.6k|         if (length >= n) {
  ------------------
  |  Branch (717:14): [True: 22.3k, False: 18.3k]
  ------------------
  718|  22.3k|            uint32_t v[2];
  719|  22.3k|            std::memcpy(v, ws, n);
  720|  22.3k|            std::memcpy(v + 1, it, n);
  721|  22.3k|            if (v[0] != v[1]) {
  ------------------
  |  Branch (721:17): [True: 12.9k, False: 9.39k]
  ------------------
  722|  12.9k|               return;
  723|  12.9k|            }
  724|  9.39k|            length -= n;
  725|  9.39k|            ws += n;
  726|  9.39k|            it += n;
  727|  9.39k|         }
  728|  40.6k|      }
  729|  27.7k|      {
  730|  27.7k|         constexpr uint64_t n{sizeof(uint16_t)};
  731|  27.7k|         if (length >= n) {
  ------------------
  |  Branch (731:14): [True: 6.31k, False: 21.3k]
  ------------------
  732|  6.31k|            uint16_t v[2];
  733|  6.31k|            std::memcpy(v, ws, n);
  734|  6.31k|            std::memcpy(v + 1, it, n);
  735|  6.31k|            if (v[0] != v[1]) {
  ------------------
  |  Branch (735:17): [True: 3.83k, False: 2.48k]
  ------------------
  736|  3.83k|               return;
  737|  3.83k|            }
  738|       |            // length -= n;
  739|       |            // ws += n;
  740|  2.48k|            it += n;
  741|  2.48k|         }
  742|  27.7k|      }
  743|       |      // We have to call a whitespace check after this function
  744|       |      // in case the whitespace is mismatching.
  745|       |      // So, we forgo this check as to not duplicate.
  746|       |      /*if (length && *ws == *it) {
  747|       |         ++it;
  748|       |      }*/
  749|  27.7k|   }
_ZN3glz18validate_utf8_spanITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEETkNS_10is_contextERNS_7contextEccEEbOT0_PKT1_PKT2_m:
  832|  5.85k|   {
  833|       |      if constexpr (not check_validate_utf8(Opts)) {
  834|       |         // Everything the caller computed for us is dead, which lets its scan loop drop the
  835|       |         // accumulator entirely.
  836|       |         (void)ctx, (void)start, (void)fin, (void)ascii_acc;
  837|       |         return false;
  838|       |      }
  839|  5.85k|      else {
  840|  5.85k|         if ((ascii_acc & repeat_byte8(0b10000000)) == 0) {
  ------------------
  |  Branch (840:14): [True: 3.78k, False: 2.06k]
  ------------------
  841|  3.78k|            return false; // pure ASCII is trivially well formed UTF-8
  842|  3.78k|         }
  843|  2.06k|         if (!validate_utf8(start, size_t(fin - start))) [[unlikely]] {
  ------------------
  |  Branch (843:14): [True: 220, False: 1.84k]
  ------------------
  844|    220|            ctx.error = error_code::invalid_utf8;
  845|    220|            return true;
  846|    220|         }
  847|  1.84k|         return false;
  848|  2.06k|      }
  849|  5.85k|   }
_ZN3glz5matchITnNS_14string_literalEXtlNS1_ILm5EEEtlA5_cLc110ELc117ELc108ELc108EEEETnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS8_Qntcl15check_is_paddedT0_EEEvOT1_OT2_T3_:
  491|    658|   {
  492|    658|      const auto n = size_t(end - it);
  493|    658|      static constexpr auto S = str.sv();
  494|    658|      if ((n < str.size()) || not comparitor<S>(it)) [[unlikely]] {
  ------------------
  |  Branch (494:11): [True: 70, False: 588]
  |  Branch (494:31): [True: 114, False: 474]
  ------------------
  495|    184|         ctx.error = error_code::syntax_error;
  496|    184|      }
  497|    474|      else [[likely]] {
  498|    474|         it += str.size();
  499|    474|      }
  500|    658|   }
_ZN3glz7skip_wsIXtlNS_7ws_optsELb0ELb1EEETkNS_10is_contextERNS_7contextERPKcS5_EEbOT0_OT1_T2_:
  622|  17.9M|   {
  623|  17.9M|      using namespace glz::detail;
  624|       |
  625|  17.9M|      if constexpr (not Opts.minified) {
  626|  17.9M|         if constexpr (Opts.null_terminated) {
  627|       |            if constexpr (Opts.comments) {
  628|       |               while (whitespace_comment_table[uint8_t(*it)]) {
  629|       |                  if (*it == '/') [[unlikely]] {
  630|       |                     skip_comment(ctx, it, end);
  631|       |                     if (bool(ctx.error)) [[unlikely]] {
  632|       |                        return true;
  633|       |                     }
  634|       |                  }
  635|       |                  else [[likely]] {
  636|       |                     ++it;
  637|       |                  }
  638|       |               }
  639|       |            }
  640|  17.9M|            else {
  641|  53.5M|               while (whitespace_table[uint8_t(*it)]) {
  ------------------
  |  Branch (641:23): [True: 35.5M, False: 17.9M]
  ------------------
  642|  35.5M|                  ++it;
  643|  35.5M|               }
  644|  17.9M|            }
  645|       |         }
  646|       |         else {
  647|       |            if constexpr (Opts.comments) {
  648|       |               while (it < end && whitespace_comment_table[uint8_t(*it)]) {
  649|       |                  if (*it == '/') [[unlikely]] {
  650|       |                     skip_comment(ctx, it, end);
  651|       |                     if (bool(ctx.error)) [[unlikely]] {
  652|       |                        return true;
  653|       |                     }
  654|       |                  }
  655|       |                  else [[likely]] {
  656|       |                     ++it;
  657|       |                  }
  658|       |               }
  659|       |               if (it == end) [[unlikely]] {
  660|       |                  ctx.error = error_code::end_reached;
  661|       |                  return true;
  662|       |               }
  663|       |            }
  664|       |            else {
  665|       |               while (it < end && whitespace_table[uint8_t(*it)]) {
  666|       |                  ++it;
  667|       |               }
  668|       |               if (it == end) [[unlikely]] {
  669|       |                  ctx.error = error_code::end_reached;
  670|       |                  return true;
  671|       |               }
  672|       |            }
  673|       |         }
  674|       |      }
  675|       |      else if constexpr (not Opts.null_terminated) {
  676|       |         // Minified input has no whitespace to skip, but a non-null-terminated buffer can still
  677|       |         // be exhausted at this point. The non-minified branch above performs the same check; a
  678|       |         // null-terminated buffer relies on the trailing sentinel and keeps this a pure no-op.
  679|       |         if (it == end) [[unlikely]] {
  680|       |            ctx.error = error_code::end_reached;
  681|       |            return true;
  682|       |         }
  683|       |      }
  684|       |
  685|  17.9M|      return false;
  686|  17.9M|   }
_ZN3glz17match_invalid_endILc44EXtlNS_22match_invalid_end_optsELb1EEETkNS_10is_contextENS_7contextERPKcS4_EEbRT1_OT2_T3_:
  411|  2.17M|   {
  412|  2.17M|      if (*it != C) [[unlikely]] {
  ------------------
  |  Branch (412:11): [True: 1.02k, False: 2.17M]
  ------------------
  413|       |         if constexpr (C == '"') {
  414|       |            ctx.error = error_code::expected_quote;
  415|       |         }
  416|  1.02k|         else if constexpr (C == ',') {
  417|  1.02k|            ctx.error = error_code::expected_comma;
  418|       |         }
  419|       |         else if constexpr (C == ':') {
  420|       |            ctx.error = error_code::expected_colon;
  421|       |         }
  422|       |         else if constexpr (C == '[' || C == ']') {
  423|       |            ctx.error = error_code::expected_bracket;
  424|       |         }
  425|       |         else if constexpr (C == '{' || C == '}') {
  426|       |            ctx.error = error_code::expected_brace;
  427|       |         }
  428|       |         else {
  429|       |            ctx.error = error_code::syntax_error;
  430|       |         }
  431|  1.02k|         return true;
  432|  1.02k|      }
  433|  2.17M|      else [[likely]] {
  434|  2.17M|         ++it;
  435|  2.17M|      }
  436|       |      if constexpr (not Opts.null_terminated) {
  437|       |         if (it == end) [[unlikely]] {
  438|       |            ctx.error = error_code::unexpected_end;
  439|       |            return true;
  440|       |         }
  441|       |      }
  442|  2.17M|      return false;
  443|  2.17M|   }
_ZN3glz17match_invalid_endILc34EXtlNS_22match_invalid_end_optsELb1EEETkNS_10is_contextENS_7contextERPKcS4_EEbRT1_OT2_T3_:
  411|  2.24M|   {
  412|  2.24M|      if (*it != C) [[unlikely]] {
  ------------------
  |  Branch (412:11): [True: 726, False: 2.24M]
  ------------------
  413|    726|         if constexpr (C == '"') {
  414|    726|            ctx.error = error_code::expected_quote;
  415|       |         }
  416|       |         else if constexpr (C == ',') {
  417|       |            ctx.error = error_code::expected_comma;
  418|       |         }
  419|       |         else if constexpr (C == ':') {
  420|       |            ctx.error = error_code::expected_colon;
  421|       |         }
  422|       |         else if constexpr (C == '[' || C == ']') {
  423|       |            ctx.error = error_code::expected_bracket;
  424|       |         }
  425|       |         else if constexpr (C == '{' || C == '}') {
  426|       |            ctx.error = error_code::expected_brace;
  427|       |         }
  428|       |         else {
  429|       |            ctx.error = error_code::syntax_error;
  430|       |         }
  431|    726|         return true;
  432|    726|      }
  433|  2.24M|      else [[likely]] {
  434|  2.24M|         ++it;
  435|  2.24M|      }
  436|       |      if constexpr (not Opts.null_terminated) {
  437|       |         if (it == end) [[unlikely]] {
  438|       |            ctx.error = error_code::unexpected_end;
  439|       |            return true;
  440|       |         }
  441|       |      }
  442|  2.24M|      return false;
  443|  2.24M|   }
_ZN3glz18validate_utf8_spanITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextEccEEbOT0_PKT1_PKT2_m:
  832|  1.11M|   {
  833|       |      if constexpr (not check_validate_utf8(Opts)) {
  834|       |         // Everything the caller computed for us is dead, which lets its scan loop drop the
  835|       |         // accumulator entirely.
  836|       |         (void)ctx, (void)start, (void)fin, (void)ascii_acc;
  837|       |         return false;
  838|       |      }
  839|  1.11M|      else {
  840|  1.11M|         if ((ascii_acc & repeat_byte8(0b10000000)) == 0) {
  ------------------
  |  Branch (840:14): [True: 1.07M, False: 38.0k]
  ------------------
  841|  1.07M|            return false; // pure ASCII is trivially well formed UTF-8
  842|  1.07M|         }
  843|  38.0k|         if (!validate_utf8(start, size_t(fin - start))) [[unlikely]] {
  ------------------
  |  Branch (843:14): [True: 247, False: 37.7k]
  ------------------
  844|    247|            ctx.error = error_code::invalid_utf8;
  845|    247|            return true;
  846|    247|         }
  847|  37.7k|         return false;
  848|  38.0k|      }
  849|  1.11M|   }
_ZN3glz17match_invalid_endILc58EXtlNS_22match_invalid_end_optsELb1EEETkNS_10is_contextENS_7contextERPKcS4_EEbRT1_OT2_T3_:
  411|  2.22M|   {
  412|  2.22M|      if (*it != C) [[unlikely]] {
  ------------------
  |  Branch (412:11): [True: 1.47k, False: 2.22M]
  ------------------
  413|       |         if constexpr (C == '"') {
  414|       |            ctx.error = error_code::expected_quote;
  415|       |         }
  416|       |         else if constexpr (C == ',') {
  417|       |            ctx.error = error_code::expected_comma;
  418|       |         }
  419|  1.47k|         else if constexpr (C == ':') {
  420|  1.47k|            ctx.error = error_code::expected_colon;
  421|       |         }
  422|       |         else if constexpr (C == '[' || C == ']') {
  423|       |            ctx.error = error_code::expected_bracket;
  424|       |         }
  425|       |         else if constexpr (C == '{' || C == '}') {
  426|       |            ctx.error = error_code::expected_brace;
  427|       |         }
  428|       |         else {
  429|       |            ctx.error = error_code::syntax_error;
  430|       |         }
  431|  1.47k|         return true;
  432|  1.47k|      }
  433|  2.22M|      else [[likely]] {
  434|  2.22M|         ++it;
  435|  2.22M|      }
  436|       |      if constexpr (not Opts.null_terminated) {
  437|       |         if (it == end) [[unlikely]] {
  438|       |            ctx.error = error_code::unexpected_end;
  439|       |            return true;
  440|       |         }
  441|       |      }
  442|  2.22M|      return false;
  443|  2.22M|   }
_ZN3glz17match_invalid_endILc91EXtlNS_22match_invalid_end_optsELb1EEETkNS_10is_contextENS_7contextERPKcS4_EEbRT1_OT2_T3_:
  411|  1.19M|   {
  412|  1.19M|      if (*it != C) [[unlikely]] {
  ------------------
  |  Branch (412:11): [True: 0, False: 1.19M]
  ------------------
  413|       |         if constexpr (C == '"') {
  414|       |            ctx.error = error_code::expected_quote;
  415|       |         }
  416|       |         else if constexpr (C == ',') {
  417|       |            ctx.error = error_code::expected_comma;
  418|       |         }
  419|       |         else if constexpr (C == ':') {
  420|       |            ctx.error = error_code::expected_colon;
  421|       |         }
  422|      0|         else if constexpr (C == '[' || C == ']') {
  423|      0|            ctx.error = error_code::expected_bracket;
  424|       |         }
  425|       |         else if constexpr (C == '{' || C == '}') {
  426|       |            ctx.error = error_code::expected_brace;
  427|       |         }
  428|       |         else {
  429|       |            ctx.error = error_code::syntax_error;
  430|       |         }
  431|      0|         return true;
  432|      0|      }
  433|  1.19M|      else [[likely]] {
  434|  1.19M|         ++it;
  435|  1.19M|      }
  436|       |      if constexpr (not Opts.null_terminated) {
  437|       |         if (it == end) [[unlikely]] {
  438|       |            ctx.error = error_code::unexpected_end;
  439|       |            return true;
  440|       |         }
  441|       |      }
  442|  1.19M|      return false;
  443|  1.19M|   }
_ZN3glz18validate_utf8_spanITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj4EEETkNS_10is_contextERNS_7contextEccEEbOT0_PKT1_PKT2_m:
  832|  5.90k|   {
  833|       |      if constexpr (not check_validate_utf8(Opts)) {
  834|       |         // Everything the caller computed for us is dead, which lets its scan loop drop the
  835|       |         // accumulator entirely.
  836|       |         (void)ctx, (void)start, (void)fin, (void)ascii_acc;
  837|       |         return false;
  838|       |      }
  839|  5.90k|      else {
  840|  5.90k|         if ((ascii_acc & repeat_byte8(0b10000000)) == 0) {
  ------------------
  |  Branch (840:14): [True: 3.82k, False: 2.07k]
  ------------------
  841|  3.82k|            return false; // pure ASCII is trivially well formed UTF-8
  842|  3.82k|         }
  843|  2.07k|         if (!validate_utf8(start, size_t(fin - start))) [[unlikely]] {
  ------------------
  |  Branch (843:14): [True: 245, False: 1.82k]
  ------------------
  844|    245|            ctx.error = error_code::invalid_utf8;
  845|    245|            return true;
  846|    245|         }
  847|  1.82k|         return false;
  848|  2.07k|      }
  849|  5.90k|   }
_ZN3glz5matchITnNS_14string_literalEXtlNS1_ILm5EEEtlA5_cLc110ELc117ELc108ELc108EEEETnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1EEETkNS_10is_contextERNS_7contextERPKcS8_Qntcl15check_is_paddedT0_EEEvOT1_OT2_T3_:
  491|    658|   {
  492|    658|      const auto n = size_t(end - it);
  493|    658|      static constexpr auto S = str.sv();
  494|    658|      if ((n < str.size()) || not comparitor<S>(it)) [[unlikely]] {
  ------------------
  |  Branch (494:11): [True: 35, False: 623]
  |  Branch (494:31): [True: 149, False: 474]
  ------------------
  495|    184|         ctx.error = error_code::syntax_error;
  496|    184|      }
  497|    474|      else [[likely]] {
  498|    474|         it += str.size();
  499|    474|      }
  500|    658|   }
_ZN3glz18validate_utf8_spanITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEETkNS_10is_contextERNS_7contextEccEEbOT0_PKT1_PKT2_m:
  832|  1.11M|   {
  833|       |      if constexpr (not check_validate_utf8(Opts)) {
  834|       |         // Everything the caller computed for us is dead, which lets its scan loop drop the
  835|       |         // accumulator entirely.
  836|       |         (void)ctx, (void)start, (void)fin, (void)ascii_acc;
  837|       |         return false;
  838|       |      }
  839|  1.11M|      else {
  840|  1.11M|         if ((ascii_acc & repeat_byte8(0b10000000)) == 0) {
  ------------------
  |  Branch (840:14): [True: 1.07M, False: 36.1k]
  ------------------
  841|  1.07M|            return false; // pure ASCII is trivially well formed UTF-8
  842|  1.07M|         }
  843|  36.1k|         if (!validate_utf8(start, size_t(fin - start))) [[unlikely]] {
  ------------------
  |  Branch (843:14): [True: 248, False: 35.8k]
  ------------------
  844|    248|            ctx.error = error_code::invalid_utf8;
  845|    248|            return true;
  846|    248|         }
  847|  35.8k|         return false;
  848|  36.1k|      }
  849|  1.11M|   }
_ZN3glz18validate_utf8_spanITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj36EEETkNS_10is_contextERNS_7contextEccEEbOT0_PKT1_PKT2_m:
  832|  5.91k|   {
  833|       |      if constexpr (not check_validate_utf8(Opts)) {
  834|       |         // Everything the caller computed for us is dead, which lets its scan loop drop the
  835|       |         // accumulator entirely.
  836|       |         (void)ctx, (void)start, (void)fin, (void)ascii_acc;
  837|       |         return false;
  838|       |      }
  839|  5.91k|      else {
  840|  5.91k|         if ((ascii_acc & repeat_byte8(0b10000000)) == 0) {
  ------------------
  |  Branch (840:14): [True: 3.97k, False: 1.94k]
  ------------------
  841|  3.97k|            return false; // pure ASCII is trivially well formed UTF-8
  842|  3.97k|         }
  843|  1.94k|         if (!validate_utf8(start, size_t(fin - start))) [[unlikely]] {
  ------------------
  |  Branch (843:14): [True: 248, False: 1.69k]
  ------------------
  844|    248|            ctx.error = error_code::invalid_utf8;
  845|    248|            return true;
  846|    248|         }
  847|  1.69k|         return false;
  848|  1.94k|      }
  849|  5.91k|   }
_ZN3glz5matchITnNS_14string_literalEXtlNS1_ILm5EEEtlA5_cLc110ELc117ELc108ELc108EEEETnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELb0ELb0ELj32EEETkNS_10is_contextERNS_7contextERPKcS8_Qaacl15check_is_paddedT0_ElecldtT_4sizeEL_ZNS_13padding_bytesEEEEvOT1_OT2_T3_:
  478|    658|   {
  479|    658|      static constexpr auto S = str.sv();
  480|    658|      if (not comparitor<S>(it)) [[unlikely]] {
  ------------------
  |  Branch (480:11): [True: 184, False: 474]
  ------------------
  481|    184|         ctx.error = error_code::syntax_error;
  482|    184|      }
  483|    474|      else [[likely]] {
  484|    474|         it += str.size();
  485|    474|      }
  486|    658|   }

_ZNK3glz14string_literalILm5EE4sizeEv:
   25|  2.73k|      [[nodiscard]] constexpr size_t size() const noexcept { return length; }

