Commit ce3f25de37b for nodejs

commit ce3f25de37b25e439368df02e8c6e27efc70038a
Author: Node.js GitHub Bot <github-bot@iojs.org>
Date:   Mon Oct 19 21:15:47 2026 -0400

    deps: update simdjson to 5.0.5

    PR-URL: https://github.com/nodejs/node/pull/66817
    Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
    Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
    Reviewed-By: Colin Ihrig <cjihrig@gmail.com>

diff --git a/deps/simdjson/simdjson.cpp b/deps/simdjson/simdjson.cpp
index 980bb83cefa..e8a2a24a04b 100644
--- a/deps/simdjson/simdjson.cpp
+++ b/deps/simdjson/simdjson.cpp
@@ -1,4 +1,4 @@
-/* auto-generated on 2026-10-07 22:43:29 -0400. version 5.0.3 Do not edit! */
+/* auto-generated on 2026-10-14 15:49:28 -0400. version 5.0.5 Do not edit! */
 /* including simdjson.cpp:  */
 /* begin file simdjson.cpp */
 #define SIMDJSON_SRC_SIMDJSON_CPP
@@ -3355,6 +3355,10 @@ consteval std::string consteval_to_quoted_escaped(std::string_view input) {
   out.push_back('"');
   return out;
 }
+
+consteval std::size_t padded_key_length(std::size_t length) {
+  return (length + 15) / 16 * 16;
+}
 #endif  // SIMDJSON_CONSTEVAL


@@ -3391,10 +3395,45 @@ struct fixed_string {
 template <std::size_t N>
 fixed_string(const char (&)[N]) -> fixed_string<N>;

+template <typename T>
+inline constexpr bool is_fixed_string = false;
+template <std::size_t N>
+inline constexpr bool is_fixed_string<constevalutil::fixed_string<N>> = true;
+
 template <fixed_string str>
 struct string_constant {
     static constexpr std::string_view value = str.view();
 };
+
+#if SIMDJSON_CONSTEVAL
+template <typename Text>
+consteval std::size_t static_string_size() {
+  return Text::text().size();
+}
+template <typename Text>
+consteval std::size_t padded_static_string_size() {
+  return padded_key_length(static_string_size<Text>());
+}
+
+template <typename Text>
+consteval auto make_static_string() {
+  std::array<char, padded_static_string_size<Text>()> out{};
+  std::string text = Text::text();
+  // The tail past text.size() stays zero: it is the padding.
+  for (std::size_t i = 0; i < text.size(); ++i) {
+    out[i] = text[i];
+  }
+  return out;
+}
+
+template <typename Text>
+inline constexpr auto static_string = make_static_string<Text>();
+
+template <fixed_string str>
+struct quoted_escaped_text {
+  static consteval std::string text() { return consteval_to_quoted_escaped(str.view()); }
+};
+#endif // SIMDJSON_CONSTEVAL
 #endif // SIMDJSON_SUPPORTS_CONCEPTS

 } // namespace constevalutil
@@ -9436,10 +9475,10 @@ simdjson_fastfloat_really_inline bool rounds_to_nearest() noexcept {
 //  https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013
 #elif defined(__clang__)
 #pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wfloat-equal"
+SIMDJSON_DISABLE_GCC_WARNING(-Wfloat-equal)
 #elif defined(__GNUC__)
 #pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wfloat-equal"
+SIMDJSON_DISABLE_GCC_WARNING(-Wfloat-equal)
 #endif
   return (fmini + 1.0f == 1.0f - fmini);
 #ifdef SIMDJSON_FASTFLOAT_VISUAL_STUDIO
@@ -9680,7 +9719,7 @@ from_chars_float_advanced(UC const *first, UC const *last, T &value,
 #ifdef __clang__
 #pragma clang diagnostic push
 #if (!defined(__APPLE_CC__) && __clang_major__ >= 10) || (__clang_major__ >= 13)
-#pragma clang diagnostic ignored "-Wc++20-extensions"
+SIMDJSON_DISABLE_GCC_WARNING(-Wc++20-extensions)
 #endif
 #endif
   if simdjson_fastfloat_unlikely (pns.too_many_digits) {
diff --git a/deps/simdjson/simdjson.h b/deps/simdjson/simdjson.h
index 58041ff68a7..faf21bdc232 100644
--- a/deps/simdjson/simdjson.h
+++ b/deps/simdjson/simdjson.h
@@ -1,4 +1,4 @@
-/* auto-generated on 2026-10-07 22:43:29 -0400. version 5.0.3 Do not edit! */
+/* auto-generated on 2026-10-14 15:49:28 -0400. version 5.0.5 Do not edit! */
 /* including simdjson.h:  */
 /* begin file simdjson.h */
 #ifndef SIMDJSON_H
@@ -2715,7 +2715,7 @@ namespace std {
 #define SIMDJSON_SIMDJSON_VERSION_H

 /** The version of simdjson being used (major.minor.revision) */
-#define SIMDJSON_VERSION "5.0.3"
+#define SIMDJSON_VERSION "5.0.5"

 namespace simdjson {
 enum {
@@ -2730,7 +2730,7 @@ enum {
   /**
    * The revision (major.minor.REVISION) of simdjson being used.
    */
-  SIMDJSON_VERSION_REVISION = 3
+  SIMDJSON_VERSION_REVISION = 5
 };
 } // namespace simdjson

@@ -3418,6 +3418,10 @@ consteval std::string consteval_to_quoted_escaped(std::string_view input) {
   out.push_back('"');
   return out;
 }
+
+consteval std::size_t padded_key_length(std::size_t length) {
+  return (length + 15) / 16 * 16;
+}
 #endif  // SIMDJSON_CONSTEVAL


@@ -3454,10 +3458,45 @@ struct fixed_string {
 template <std::size_t N>
 fixed_string(const char (&)[N]) -> fixed_string<N>;

+template <typename T>
+inline constexpr bool is_fixed_string = false;
+template <std::size_t N>
+inline constexpr bool is_fixed_string<constevalutil::fixed_string<N>> = true;
+
 template <fixed_string str>
 struct string_constant {
     static constexpr std::string_view value = str.view();
 };
+
+#if SIMDJSON_CONSTEVAL
+template <typename Text>
+consteval std::size_t static_string_size() {
+  return Text::text().size();
+}
+template <typename Text>
+consteval std::size_t padded_static_string_size() {
+  return padded_key_length(static_string_size<Text>());
+}
+
+template <typename Text>
+consteval auto make_static_string() {
+  std::array<char, padded_static_string_size<Text>()> out{};
+  std::string text = Text::text();
+  // The tail past text.size() stays zero: it is the padding.
+  for (std::size_t i = 0; i < text.size(); ++i) {
+    out[i] = text[i];
+  }
+  return out;
+}
+
+template <typename Text>
+inline constexpr auto static_string = make_static_string<Text>();
+
+template <fixed_string str>
+struct quoted_escaped_text {
+  static consteval std::string text() { return consteval_to_quoted_escaped(str.view()); }
+};
+#endif // SIMDJSON_CONSTEVAL
 #endif // SIMDJSON_SUPPORTS_CONCEPTS

 } // namespace constevalutil
@@ -8621,7 +8660,7 @@ template <class T> std::string prettify(simdjson_result<T> x) {
   if (x.error()) {
     throw simdjson_error(x.error());
   }
-  return to_string(x.value());
+  return prettify(x.value());
 }
 #endif

@@ -8852,6 +8891,7 @@ inline std::string fractured_json_string(std::string_view json_str,

 #include <limits>
 #include <utility>
+#include <vector>

 namespace simdjson {
 namespace internal {
@@ -8893,6 +8933,28 @@ simdjson_inline error_code parse_json_pointer_array_index(std::string_view json_

   return SUCCESS;
 }
+
+/**
+ * Returns true if the error means that a JSONPath segment matched nothing
+ * (missing field, index out of bounds, value of the wrong type, or a scalar
+ * reached while path segments remain), as opposed to a document error.
+ * A wildcard walk skips such branches, as RFC 9535 and DOM's
+ * at_path_with_wildcard do.
+ */
+simdjson_inline bool is_matching_failure_error(error_code error) noexcept {
+  return error == NO_SUCH_FIELD || error == INDEX_OUT_OF_BOUNDS ||
+         error == INCORRECT_TYPE || error == INVALID_JSON_POINTER;
+}
+
+/**
+ * Returns true if a wildcard follows in the remaining JSONPath. A segment that
+ * matches nothing before a wildcard yields an empty result instead of an
+ * error, as in DOM's at_path_with_wildcard. Like DOM, this treats a '*' inside
+ * a quoted key as a wildcard.
+ */
+simdjson_inline bool json_path_has_wildcard(std::string_view json_path) noexcept {
+  return json_path.find('*') != std::string_view::npos;
+}
 } // namespace internal

 /**
@@ -8999,12 +9061,100 @@ inline std::pair<std::string_view, std::string_view> get_next_key_and_json_path(
   } else if ((i+2 < json_path.size()) && json_path[i] == '[' && json_path[i+1] == '*' && json_path[i+2] == ']') { // i.e [*].additional_keys or [*]["additional_keys"]
     key = "*";
     i += 3;
+  } else if (i < json_path.size() && json_path[i] == '[') { // i.e. [0] or [123]
+    size_t j = i + 1;
+    while (j < json_path.size() && json_path[j] >= '0' && json_path[j] <= '9') {
+      ++j;
+    }
+    if (j > i + 1 && j < json_path.size() && json_path[j] == ']') {
+      key = json_path.substr(i + 1, j - i - 1);
+      i = j + 1;
+    }
   }


   return std::make_pair(key, json_path.substr(i));
 }

+namespace internal {
+/**
+ * A JSONPath as the DOM at_path_with_wildcard() consumes it, parsed once.
+ *
+ * Every node visited at a given depth sees the same remaining path, so we
+ * parse it up front rather than at each node: re-scanning (and converting)
+ * the remaining path at every node costs O(nodes * path length), which
+ * made a long path after a couple of wildcards take minutes on a large
+ * document.
+ */
+struct wildcard_json_path {
+  enum class tail_type { invalid, all_values, pointer };
+  // One JSON pointer ("/key") per leading segment, "/*" being a wildcard.
+  std::vector<std::string> steps{};
+  // What to do once the steps are exhausted.
+  tail_type tail{tail_type::invalid};
+  // The rest of the path, as a JSON pointer, when tail == pointer.
+  std::string tail_pointer{};
+};
+
+/**
+ * Splits json_path the same way the recursive DOM at_path_with_wildcard()
+ * historically did, one level at a time, but in a single pass.
+ */
+inline wildcard_json_path parse_wildcard_json_path(std::string_view json_path) {
+  wildcard_json_path result;
+  // The remaining path (always a suffix of json_path) contains a '*' if and
+  // only if it starts at or before the last one.
+  const size_t last_star = json_path.rfind('*');
+  std::string_view path = json_path;
+  while (true) {
+    size_t i = 0;
+    if (!path.empty() && path.front() == '$') {
+      i = 1;
+    }
+    if (i >= path.size() || (path[i] != '.' && path[i] != '[')) {
+      result.tail = wildcard_json_path::tail_type::invalid;
+      return result;
+    }
+    const size_t offset = json_path.size() - path.size();
+    if (last_star == std::string_view::npos || last_star < offset) {
+      result.tail_pointer = json_path_to_pointer_conversion(path);
+      result.tail = (result.tail_pointer == "-1")
+                        ? wildcard_json_path::tail_type::invalid
+                        : wildcard_json_path::tail_type::pointer;
+      return result;
+    }
+    if ((path.compare(i, 3, "[*]") == 0 && path.size() == i + 3) ||
+        (path.compare(i, 2, ".*") == 0 && path.size() == i + 2)) {
+      result.tail = wildcard_json_path::tail_type::all_values;
+      return result;
+    }
+    std::pair<std::string_view, std::string_view> key_and_json_path = get_next_key_and_json_path(path);
+    if (key_and_json_path.first.empty()) {
+      result.tail = wildcard_json_path::tail_type::invalid;
+      return result;
+    }
+    std::string step;
+    step.reserve(key_and_json_path.first.size() + 1);
+    step += '/';
+    // The step is consumed by at_pointer, which unescapes ~0/~1, so '~' and
+    // '/' in the key must be escaped as json_path_to_pointer_conversion does:
+    // a raw '/' splits the step into two pointer tokens and a raw '~'
+    // invalidates it, either way addressing the wrong element.
+    for (const char c : key_and_json_path.first) {
+      if (c == '~') {
+        step += "~0";
+      } else if (c == '/') {
+        step += "~1";
+      } else {
+        step += c;
+      }
+    }
+    result.steps.push_back(std::move(step));
+    path = key_and_json_path.second;
+  }
+}
+} // namespace internal
+
 } // namespace simdjson
 #endif // SIMDJSON_JSONPATHUTIL_H
 /* end file simdjson/jsonpathutil.h */
@@ -9383,68 +9533,7 @@ inline void array::process_json_path_of_child_elements(std::vector<element>::ite

 inline simdjson_result<std::vector<element>> array::at_path_with_wildcard(std::string_view json_path) const noexcept {
   SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
-
-  size_t i = 0;
-   // json_path.starts_with('$') requires C++20.
-  if (!json_path.empty() && json_path.front() == '$') {
-    i = 1;
-  }
-
-  if (i >= json_path.size() || (json_path[i] != '.' && json_path[i] != '[')) {
-    return INVALID_JSON_POINTER;
-  }
-
-  if (json_path.find("*") != std::string::npos) {
-    std::vector<element> child_values;
-
-    if (
-      (json_path.compare(i, 3, "[*]") == 0 && json_path.size() == i + 3) ||
-      (json_path.compare(i, 2,".*") == 0 && json_path.size() == i + 2)
-    ) {
-      get_values(child_values);
-      return child_values;
-    }
-
-    std::pair<std::string_view, std::string_view> key_and_json_path = get_next_key_and_json_path(json_path);
-
-    std::string_view key = key_and_json_path.first;
-    json_path = key_and_json_path.second;
-
-    if (key.size() > 0) {
-      if (key == "*") {
-        get_values(child_values);
-      } else {
-        element pointer_result;
-        std::string json_pointer = std::string("/") + std::string(key);
-        auto error = at_pointer(json_pointer).get(pointer_result);
-
-        if (!error) {
-          child_values.emplace_back(pointer_result);
-        }
-      }
-
-      std::vector<element> result = {};
-
-      if (child_values.size() > 0) {
-        std::vector<element>::iterator child_values_begin = child_values.begin();
-        std::vector<element>::iterator child_values_end = child_values.end();
-
-        process_json_path_of_child_elements(child_values_begin, child_values_end, json_path, result);
-      }
-
-      return result;
-    } else {
-      return INVALID_JSON_POINTER;
-    }
-  } else {
-    element result;
-    auto error = at_path(json_path).get(result);
-    if (error) {
-      return error;
-    }
-
-    return std::vector<element>{std::move(result)};
-  }
+  return element(*this).at_path_with_wildcard(json_path);
 }

 inline simdjson_result<element> array::at(size_t index) const noexcept {
@@ -9723,73 +9812,7 @@ inline void object::process_json_path_of_child_elements(std::vector<element>::it

 inline simdjson_result<std::vector<element>> object::at_path_with_wildcard(std::string_view json_path) const noexcept {
   SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
-
-  size_t i = 0;
-  if (json_path.empty()) {
-    return INVALID_JSON_POINTER;
-  }
-  // if JSONPath starts with $, skip it
-  // json_path.starts_with('$') requires C++20.
-  if (json_path.front() == '$') {
-    i = 1;
-  }
-
-  if (i >= json_path.size() || (json_path[i] != '.' && json_path[i] != '[')) {
-    // expect JSONPath expressions to always start with $ but this isn't currently
-    // expected in jsonpathutil.h.
-    return INVALID_JSON_POINTER;
-  }
-
-  if (json_path.find("*") != std::string::npos) {
-
-    std::vector<element> child_values;
-
-    if (
-      (json_path.compare(i, 3, "[*]") == 0 && json_path.size() == i + 3) ||
-      (json_path.compare(i, 2,".*") == 0 && json_path.size() == i + 2)
-    ) {
-      get_values(child_values);
-      return child_values;
-    }
-
-    std::pair<std::string_view, std::string_view> key_and_json_path = get_next_key_and_json_path(json_path);
-
-    std::string_view key = key_and_json_path.first;
-    json_path = key_and_json_path.second;
-
-    if (key.size() > 0) {
-      if (key == "*") {
-        get_values(child_values);
-      } else {
-        element pointer_result;
-        auto error = at_pointer(std::string("/") + std::string(key)).get(pointer_result);
-
-        if (!error) {
-          child_values.emplace_back(pointer_result);
-        }
-      }
-
-      std::vector<element> result = {};
-      if (child_values.size() > 0) {
-
-        std::vector<element>::iterator child_values_begin = child_values.begin();
-        std::vector<element>::iterator child_values_end = child_values.end();
-
-        process_json_path_of_child_elements(child_values_begin, child_values_end, json_path, result);
-      }
-
-      return result;
-    } else {
-      return INVALID_JSON_POINTER;
-    }
-  } else {
-    element result;
-    auto error = this->at_path(json_path).get(result);
-    if (error) {
-      return error;
-    }
-    return std::vector<element>{std::move(result)};
-  }
+  return element(*this).at_path_with_wildcard(json_path);
 }

 inline simdjson_result<element> object::at_key(std::string_view key) const noexcept {
@@ -10136,6 +10159,68 @@ simdjson_inline dom::array::iterator simdjson_result<dom::element>::end() const

 #endif // SIMDJSON_EXCEPTIONS

+namespace internal {
+// Appends the children of e, which must be an array or an object.
+inline void get_container_values(const dom::element &e, std::vector<dom::element> &out) noexcept {
+  dom::array a;
+  if (!e.get_array().get(a)) {
+    a.get_values(out);
+    return;
+  }
+  dom::object o;
+  if (!e.get_object().get(o)) {
+    o.get_values(out);
+  }
+}
+
+// Walks a pre-parsed wildcard path from e, which is at depth `step` of the
+// path. Errors below the starting node are skipped, not reported.
+inline simdjson_result<std::vector<dom::element>> at_wildcard_json_path(const dom::element &e, const wildcard_json_path &path, size_t step) noexcept {
+  const dom::element_type t = e.type();
+  if (t != dom::element_type::ARRAY && t != dom::element_type::OBJECT) {
+    return std::vector<dom::element>{};
+  }
+  std::vector<dom::element> children;
+  if (step == path.steps.size()) {
+    switch (path.tail) {
+      case wildcard_json_path::tail_type::all_values:
+        get_container_values(e, children);
+        return children;
+      case wildcard_json_path::tail_type::pointer: {
+        dom::element result;
+        auto error = e.at_pointer(path.tail_pointer).get(result);
+        if (error) {
+          return error;
+        }
+        return std::vector<dom::element>{std::move(result)};
+      }
+      default:
+        return INVALID_JSON_POINTER;
+    }
+  }
+  const std::string &key_pointer = path.steps[step];
+  if (key_pointer == "/*") {
+    get_container_values(e, children);
+  } else {
+    dom::element child;
+    if (!e.at_pointer(key_pointer).get(child)) {
+      children.emplace_back(child);
+    }
+  }
+  std::vector<dom::element> result;
+  for (const dom::element &child : children) {
+    std::vector<dom::element> child_result;
+    if (at_wildcard_json_path(child, path, step + 1).get(child_result)) {
+      continue;
+    }
+    result.insert(result.end(),
+                  std::make_move_iterator(child_result.begin()),
+                  std::make_move_iterator(child_result.end()));
+  }
+  return result;
+}
+} // namespace internal
+
 namespace dom {

 //
@@ -10394,9 +10479,8 @@ inline simdjson_result<std::vector<element>> element::at_path_with_wildcard(std:

   switch (tape.tape_ref_type()) {
     case internal::tape_type::START_OBJECT:
-      return object(tape).at_path_with_wildcard(json_path);
     case internal::tape_type::START_ARRAY:
-      return array(tape).at_path_with_wildcard(json_path);
+      return internal::at_wildcard_json_path(*this, internal::parse_wildcard_json_path(json_path), 0);
     default:
       return std::vector<element>{};
   }
@@ -12711,8 +12795,18 @@ inline element_metrics structure_analyzer::analyze_object(const dom::object& obj
 inline size_t structure_analyzer::estimate_string_length(std::string_view s) const {
   size_t len = 2; // quotes
   for (char c : s) {
-    if (c == '"' || c == '\\' || static_cast<unsigned char>(c) < 32) {
-      len += 2; // escape sequence (at least)
+    unsigned char uc = static_cast<unsigned char>(c);
+    if (c == '"' || c == '\\') {
+      len += 2; // \" and \\ are two-character escapes
+    } else if (uc < 0x20) {
+      switch (c) {
+        case '\b': case '\f': case '\n': case '\r': case '\t':
+          len += 2; // two-character escapes: \b \f \n \r \t
+          break;
+        default:
+          len += 6; // \u00XX -- six-character escape for other control chars
+          break;
+      }
     } else {
       len += 1;
     }
@@ -12803,7 +12897,9 @@ inline void structure_analyzer::build_table_columns(
   table_column_type common = table_column_type::unknown;
   for (const auto& v : values) {
     table_column_type t = classify_table_value(v.first.type());
-    if (t == table_column_type::unknown) continue;
+    // Null cannot be projected into object or array columns. Keep these
+    // values intact by falling back to ordinary value formatting.
+    if (t == table_column_type::unknown) return;
     if (common == table_column_type::unknown) common = t;
     else if (t != common) { common = table_column_type::mixed; break; }
   }
@@ -46559,6 +46655,13 @@ public:
   template<constevalutil::fixed_string key, typename value_type>
   simdjson_inline void append_key_value(value_type value) noexcept;

+  template<constevalutil::fixed_string key, constevalutil::fixed_string value>
+  simdjson_inline void append_key_value() noexcept;
+
+  template<constevalutil::fixed_string key, auto value>
+  requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+  simdjson_inline void append_key_value() noexcept;
+
   // Support for optional types (std::optional, etc.)
   template <concepts::optional_type T>
   requires(!require_custom_serialization<T>)
@@ -46600,6 +46703,7 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
    */
   template <size_t N>
   simdjson_inline void append_raw_n(const char *str) noexcept;
+
 #if SIMDJSON_EXCEPTIONS
   /**
    * Creates an std::string from the written JSON buffer.
@@ -46679,6 +46783,15 @@ private:
    */
   simdjson_inline bool capacity_check(size_t upcoming_bytes);

+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+  /**
+   * Append constevalutil::static_string<Text>. The whole zero-padded array is
+   * copied in 16-byte blocks, but position only advances by the text length.
+   */
+  template <typename Text>
+  simdjson_inline void append_static_string() noexcept;
+#endif
+
   /**
    * Grow the buffer to at least desired_capacity bytes.
    * If the allocation fails, is_valid is set to false. We expect
@@ -46872,10 +46985,6 @@ using unchecked_writer = basic_writer<false>;
 // 16-byte blocks).
 inline constexpr size_t unchecked_slack = 64;

-consteval size_t padded_key_length(size_t length) {
-  return (length + 15) / 16 * 16;
-}
-
 // === Helper: invoke a string_builder member that writes variable-length
 // content (escape_and_append_with_quotes etc), syncing the writer's local
 // state before the call and reloading after. Used for string fields where
@@ -46965,16 +47074,16 @@ simdjson_really_inline void atom_fields(W &w, const T &t, bool &first) {
           constexpr size_t rest_key_len = first_key_len + 1;
           constexpr auto first_key = std::define_static_string(
               constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(first_key_len) - first_key_len, '\0'));
+              std::string(constevalutil::padded_key_length(first_key_len) - first_key_len, '\0'));
           constexpr auto rest_key = std::define_static_string(
               std::string(",") + constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(rest_key_len) - rest_key_len, '\0'));
-          if (!w.ensure(padded_key_length(rest_key_len))) { return; }
+              std::string(constevalutil::padded_key_length(rest_key_len) - rest_key_len, '\0'));
+          if (!w.ensure(constevalutil::padded_key_length(rest_key_len))) { return; }
           if (first) {
-            std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
+            std::memcpy(w.ptr + w.pos, first_key, constevalutil::padded_key_length(first_key_len));
             w.pos += first_key_len;
           } else {
-            std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
+            std::memcpy(w.ptr + w.pos, rest_key, constevalutil::padded_key_length(rest_key_len));
             w.pos += rest_key_len;
           }
           first = false;
@@ -47706,6 +47815,7 @@ simdjson_warn_unused simdjson_result<std::string> extract_fractured_json(
 /* begin file simdjson/generic/builder/json_string_builder-inl.h for arm64 */
 #include <array>
 #include <cmath>
+#include <cstddef>
 #include <cstring>
 #include <limits>
 #include <type_traits>
@@ -48746,7 +48856,11 @@ string_builder::escape_and_append_with_quotes(const char *input) noexcept {
 #if SIMDJSON_SUPPORTS_CONCEPTS
 template <constevalutil::fixed_string key>
 simdjson_inline void string_builder::escape_and_append_with_quotes() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<constevalutil::quoted_escaped_text<key>>();
+#else
   escape_and_append_with_quotes(constevalutil::string_constant<key>::value);
+#endif
 }
 #endif

@@ -48780,6 +48894,18 @@ simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
     position += N;
   }
 }
+
+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+template <typename Text>
+simdjson_inline void string_builder::append_static_string() noexcept {
+  constexpr auto& padded = constevalutil::static_string<Text>;
+  if (capacity_check(padded.size())) {
+    std::memcpy(buffer.get() + position, padded.data(), padded.size());
+    position += constevalutil::static_string_size<Text>();
+  }
+}
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS
 // Support for optional types (std::optional, etc.)
 template <concepts::optional_type T>
@@ -48946,11 +49072,24 @@ string_builder::append_key_value(key_type key, value_type value) noexcept {
 }

 #if SIMDJSON_SUPPORTS_CONCEPTS
+#if SIMDJSON_CONSTEVAL
+template <constevalutil::fixed_string key>
+struct quoted_key_text {
+  static consteval std::string text() {
+    return constevalutil::consteval_to_quoted_escaped(key.view()) + ":";
+  }
+};
+#endif
+
 template <constevalutil::fixed_string key, typename value_type>
 simdjson_inline void
 string_builder::append_key_value(value_type value) noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<quoted_key_text<key>>();
+#else
   escape_and_append_with_quotes<key>();
   append_colon();
+#endif
   SIMDJSON_IF_CONSTEXPR(std::is_same<value_type, std::nullptr_t>::value) {
     append_null();
   }
@@ -48968,6 +49107,56 @@ string_builder::append_key_value(value_type value) noexcept {
     append(value);
   }
 }
+
+#if SIMDJSON_CONSTEVAL
+template <typename T>
+concept compile_time_formattable =
+  constevalutil::is_fixed_string<std::remove_cvref_t<T>> ||
+  std::same_as<std::remove_cvref_t<T>, bool> ||
+  std::same_as<std::remove_cvref_t<T>, std::nullptr_t>;
+
+template <constevalutil::fixed_string key, auto value>
+requires compile_time_formattable<decltype(value)>
+struct key_value_text {
+  static consteval std::string text() {
+    using value_type = std::remove_cvref_t<decltype(value)>;
+    std::string out = constevalutil::consteval_to_quoted_escaped(key.view()) + ':';
+    SIMDJSON_IF_CONSTEXPR(constevalutil::is_fixed_string<value_type>)
+      out += constevalutil::consteval_to_quoted_escaped(value.view());
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, bool>)
+      out += value ? "true" : "false";
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, std::nullptr_t>)
+      out += "null";
+    return out;
+  }
+};
+#endif
+
+template <constevalutil::fixed_string key, constevalutil::fixed_string value>
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<key_value_text<key, value>>();
+#else
+  escape_and_append_with_quotes<key>();
+  append_colon();
+  escape_and_append_with_quotes<value>();
+#endif
+}
+
+template <constevalutil::fixed_string key, auto value>
+requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  SIMDJSON_IF_CONSTEXPR(compile_time_formattable<decltype(value)>) {
+    append_static_string<key_value_text<key, value>>();
+  } else
+#endif
+  {
+    append_key_value<key>(value);
+  }
+}
 #endif

 } // namespace builder
@@ -49397,6 +49586,13 @@ public:
   template<constevalutil::fixed_string key, typename value_type>
   simdjson_inline void append_key_value(value_type value) noexcept;

+  template<constevalutil::fixed_string key, constevalutil::fixed_string value>
+  simdjson_inline void append_key_value() noexcept;
+
+  template<constevalutil::fixed_string key, auto value>
+  requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+  simdjson_inline void append_key_value() noexcept;
+
   // Support for optional types (std::optional, etc.)
   template <concepts::optional_type T>
   requires(!require_custom_serialization<T>)
@@ -49438,6 +49634,7 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
    */
   template <size_t N>
   simdjson_inline void append_raw_n(const char *str) noexcept;
+
 #if SIMDJSON_EXCEPTIONS
   /**
    * Creates an std::string from the written JSON buffer.
@@ -49517,6 +49714,15 @@ private:
    */
   simdjson_inline bool capacity_check(size_t upcoming_bytes);

+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+  /**
+   * Append constevalutil::static_string<Text>. The whole zero-padded array is
+   * copied in 16-byte blocks, but position only advances by the text length.
+   */
+  template <typename Text>
+  simdjson_inline void append_static_string() noexcept;
+#endif
+
   /**
    * Grow the buffer to at least desired_capacity bytes.
    * If the allocation fails, is_valid is set to false. We expect
@@ -49710,10 +49916,6 @@ using unchecked_writer = basic_writer<false>;
 // 16-byte blocks).
 inline constexpr size_t unchecked_slack = 64;

-consteval size_t padded_key_length(size_t length) {
-  return (length + 15) / 16 * 16;
-}
-
 // === Helper: invoke a string_builder member that writes variable-length
 // content (escape_and_append_with_quotes etc), syncing the writer's local
 // state before the call and reloading after. Used for string fields where
@@ -49803,16 +50005,16 @@ simdjson_really_inline void atom_fields(W &w, const T &t, bool &first) {
           constexpr size_t rest_key_len = first_key_len + 1;
           constexpr auto first_key = std::define_static_string(
               constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(first_key_len) - first_key_len, '\0'));
+              std::string(constevalutil::padded_key_length(first_key_len) - first_key_len, '\0'));
           constexpr auto rest_key = std::define_static_string(
               std::string(",") + constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(rest_key_len) - rest_key_len, '\0'));
-          if (!w.ensure(padded_key_length(rest_key_len))) { return; }
+              std::string(constevalutil::padded_key_length(rest_key_len) - rest_key_len, '\0'));
+          if (!w.ensure(constevalutil::padded_key_length(rest_key_len))) { return; }
           if (first) {
-            std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
+            std::memcpy(w.ptr + w.pos, first_key, constevalutil::padded_key_length(first_key_len));
             w.pos += first_key_len;
           } else {
-            std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
+            std::memcpy(w.ptr + w.pos, rest_key, constevalutil::padded_key_length(rest_key_len));
             w.pos += rest_key_len;
           }
           first = false;
@@ -50544,6 +50746,7 @@ simdjson_warn_unused simdjson_result<std::string> extract_fractured_json(
 /* begin file simdjson/generic/builder/json_string_builder-inl.h for fallback */
 #include <array>
 #include <cmath>
+#include <cstddef>
 #include <cstring>
 #include <limits>
 #include <type_traits>
@@ -51584,7 +51787,11 @@ string_builder::escape_and_append_with_quotes(const char *input) noexcept {
 #if SIMDJSON_SUPPORTS_CONCEPTS
 template <constevalutil::fixed_string key>
 simdjson_inline void string_builder::escape_and_append_with_quotes() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<constevalutil::quoted_escaped_text<key>>();
+#else
   escape_and_append_with_quotes(constevalutil::string_constant<key>::value);
+#endif
 }
 #endif

@@ -51618,6 +51825,18 @@ simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
     position += N;
   }
 }
+
+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+template <typename Text>
+simdjson_inline void string_builder::append_static_string() noexcept {
+  constexpr auto& padded = constevalutil::static_string<Text>;
+  if (capacity_check(padded.size())) {
+    std::memcpy(buffer.get() + position, padded.data(), padded.size());
+    position += constevalutil::static_string_size<Text>();
+  }
+}
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS
 // Support for optional types (std::optional, etc.)
 template <concepts::optional_type T>
@@ -51784,11 +52003,24 @@ string_builder::append_key_value(key_type key, value_type value) noexcept {
 }

 #if SIMDJSON_SUPPORTS_CONCEPTS
+#if SIMDJSON_CONSTEVAL
+template <constevalutil::fixed_string key>
+struct quoted_key_text {
+  static consteval std::string text() {
+    return constevalutil::consteval_to_quoted_escaped(key.view()) + ":";
+  }
+};
+#endif
+
 template <constevalutil::fixed_string key, typename value_type>
 simdjson_inline void
 string_builder::append_key_value(value_type value) noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<quoted_key_text<key>>();
+#else
   escape_and_append_with_quotes<key>();
   append_colon();
+#endif
   SIMDJSON_IF_CONSTEXPR(std::is_same<value_type, std::nullptr_t>::value) {
     append_null();
   }
@@ -51806,6 +52038,56 @@ string_builder::append_key_value(value_type value) noexcept {
     append(value);
   }
 }
+
+#if SIMDJSON_CONSTEVAL
+template <typename T>
+concept compile_time_formattable =
+  constevalutil::is_fixed_string<std::remove_cvref_t<T>> ||
+  std::same_as<std::remove_cvref_t<T>, bool> ||
+  std::same_as<std::remove_cvref_t<T>, std::nullptr_t>;
+
+template <constevalutil::fixed_string key, auto value>
+requires compile_time_formattable<decltype(value)>
+struct key_value_text {
+  static consteval std::string text() {
+    using value_type = std::remove_cvref_t<decltype(value)>;
+    std::string out = constevalutil::consteval_to_quoted_escaped(key.view()) + ':';
+    SIMDJSON_IF_CONSTEXPR(constevalutil::is_fixed_string<value_type>)
+      out += constevalutil::consteval_to_quoted_escaped(value.view());
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, bool>)
+      out += value ? "true" : "false";
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, std::nullptr_t>)
+      out += "null";
+    return out;
+  }
+};
+#endif
+
+template <constevalutil::fixed_string key, constevalutil::fixed_string value>
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<key_value_text<key, value>>();
+#else
+  escape_and_append_with_quotes<key>();
+  append_colon();
+  escape_and_append_with_quotes<value>();
+#endif
+}
+
+template <constevalutil::fixed_string key, auto value>
+requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  SIMDJSON_IF_CONSTEXPR(compile_time_formattable<decltype(value)>) {
+    append_static_string<key_value_text<key, value>>();
+  } else
+#endif
+  {
+    append_key_value<key>(value);
+  }
+}
 #endif

 } // namespace builder
@@ -52712,6 +52994,13 @@ public:
   template<constevalutil::fixed_string key, typename value_type>
   simdjson_inline void append_key_value(value_type value) noexcept;

+  template<constevalutil::fixed_string key, constevalutil::fixed_string value>
+  simdjson_inline void append_key_value() noexcept;
+
+  template<constevalutil::fixed_string key, auto value>
+  requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+  simdjson_inline void append_key_value() noexcept;
+
   // Support for optional types (std::optional, etc.)
   template <concepts::optional_type T>
   requires(!require_custom_serialization<T>)
@@ -52753,6 +53042,7 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
    */
   template <size_t N>
   simdjson_inline void append_raw_n(const char *str) noexcept;
+
 #if SIMDJSON_EXCEPTIONS
   /**
    * Creates an std::string from the written JSON buffer.
@@ -52832,6 +53122,15 @@ private:
    */
   simdjson_inline bool capacity_check(size_t upcoming_bytes);

+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+  /**
+   * Append constevalutil::static_string<Text>. The whole zero-padded array is
+   * copied in 16-byte blocks, but position only advances by the text length.
+   */
+  template <typename Text>
+  simdjson_inline void append_static_string() noexcept;
+#endif
+
   /**
    * Grow the buffer to at least desired_capacity bytes.
    * If the allocation fails, is_valid is set to false. We expect
@@ -53025,10 +53324,6 @@ using unchecked_writer = basic_writer<false>;
 // 16-byte blocks).
 inline constexpr size_t unchecked_slack = 64;

-consteval size_t padded_key_length(size_t length) {
-  return (length + 15) / 16 * 16;
-}
-
 // === Helper: invoke a string_builder member that writes variable-length
 // content (escape_and_append_with_quotes etc), syncing the writer's local
 // state before the call and reloading after. Used for string fields where
@@ -53118,16 +53413,16 @@ simdjson_really_inline void atom_fields(W &w, const T &t, bool &first) {
           constexpr size_t rest_key_len = first_key_len + 1;
           constexpr auto first_key = std::define_static_string(
               constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(first_key_len) - first_key_len, '\0'));
+              std::string(constevalutil::padded_key_length(first_key_len) - first_key_len, '\0'));
           constexpr auto rest_key = std::define_static_string(
               std::string(",") + constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(rest_key_len) - rest_key_len, '\0'));
-          if (!w.ensure(padded_key_length(rest_key_len))) { return; }
+              std::string(constevalutil::padded_key_length(rest_key_len) - rest_key_len, '\0'));
+          if (!w.ensure(constevalutil::padded_key_length(rest_key_len))) { return; }
           if (first) {
-            std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
+            std::memcpy(w.ptr + w.pos, first_key, constevalutil::padded_key_length(first_key_len));
             w.pos += first_key_len;
           } else {
-            std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
+            std::memcpy(w.ptr + w.pos, rest_key, constevalutil::padded_key_length(rest_key_len));
             w.pos += rest_key_len;
           }
           first = false;
@@ -53859,6 +54154,7 @@ simdjson_warn_unused simdjson_result<std::string> extract_fractured_json(
 /* begin file simdjson/generic/builder/json_string_builder-inl.h for haswell */
 #include <array>
 #include <cmath>
+#include <cstddef>
 #include <cstring>
 #include <limits>
 #include <type_traits>
@@ -54899,7 +55195,11 @@ string_builder::escape_and_append_with_quotes(const char *input) noexcept {
 #if SIMDJSON_SUPPORTS_CONCEPTS
 template <constevalutil::fixed_string key>
 simdjson_inline void string_builder::escape_and_append_with_quotes() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<constevalutil::quoted_escaped_text<key>>();
+#else
   escape_and_append_with_quotes(constevalutil::string_constant<key>::value);
+#endif
 }
 #endif

@@ -54933,6 +55233,18 @@ simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
     position += N;
   }
 }
+
+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+template <typename Text>
+simdjson_inline void string_builder::append_static_string() noexcept {
+  constexpr auto& padded = constevalutil::static_string<Text>;
+  if (capacity_check(padded.size())) {
+    std::memcpy(buffer.get() + position, padded.data(), padded.size());
+    position += constevalutil::static_string_size<Text>();
+  }
+}
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS
 // Support for optional types (std::optional, etc.)
 template <concepts::optional_type T>
@@ -55099,11 +55411,24 @@ string_builder::append_key_value(key_type key, value_type value) noexcept {
 }

 #if SIMDJSON_SUPPORTS_CONCEPTS
+#if SIMDJSON_CONSTEVAL
+template <constevalutil::fixed_string key>
+struct quoted_key_text {
+  static consteval std::string text() {
+    return constevalutil::consteval_to_quoted_escaped(key.view()) + ":";
+  }
+};
+#endif
+
 template <constevalutil::fixed_string key, typename value_type>
 simdjson_inline void
 string_builder::append_key_value(value_type value) noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<quoted_key_text<key>>();
+#else
   escape_and_append_with_quotes<key>();
   append_colon();
+#endif
   SIMDJSON_IF_CONSTEXPR(std::is_same<value_type, std::nullptr_t>::value) {
     append_null();
   }
@@ -55121,6 +55446,56 @@ string_builder::append_key_value(value_type value) noexcept {
     append(value);
   }
 }
+
+#if SIMDJSON_CONSTEVAL
+template <typename T>
+concept compile_time_formattable =
+  constevalutil::is_fixed_string<std::remove_cvref_t<T>> ||
+  std::same_as<std::remove_cvref_t<T>, bool> ||
+  std::same_as<std::remove_cvref_t<T>, std::nullptr_t>;
+
+template <constevalutil::fixed_string key, auto value>
+requires compile_time_formattable<decltype(value)>
+struct key_value_text {
+  static consteval std::string text() {
+    using value_type = std::remove_cvref_t<decltype(value)>;
+    std::string out = constevalutil::consteval_to_quoted_escaped(key.view()) + ':';
+    SIMDJSON_IF_CONSTEXPR(constevalutil::is_fixed_string<value_type>)
+      out += constevalutil::consteval_to_quoted_escaped(value.view());
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, bool>)
+      out += value ? "true" : "false";
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, std::nullptr_t>)
+      out += "null";
+    return out;
+  }
+};
+#endif
+
+template <constevalutil::fixed_string key, constevalutil::fixed_string value>
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<key_value_text<key, value>>();
+#else
+  escape_and_append_with_quotes<key>();
+  append_colon();
+  escape_and_append_with_quotes<value>();
+#endif
+}
+
+template <constevalutil::fixed_string key, auto value>
+requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  SIMDJSON_IF_CONSTEXPR(compile_time_formattable<decltype(value)>) {
+    append_static_string<key_value_text<key, value>>();
+  } else
+#endif
+  {
+    append_key_value<key>(value);
+  }
+}
 #endif

 } // namespace builder
@@ -56027,6 +56402,13 @@ public:
   template<constevalutil::fixed_string key, typename value_type>
   simdjson_inline void append_key_value(value_type value) noexcept;

+  template<constevalutil::fixed_string key, constevalutil::fixed_string value>
+  simdjson_inline void append_key_value() noexcept;
+
+  template<constevalutil::fixed_string key, auto value>
+  requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+  simdjson_inline void append_key_value() noexcept;
+
   // Support for optional types (std::optional, etc.)
   template <concepts::optional_type T>
   requires(!require_custom_serialization<T>)
@@ -56068,6 +56450,7 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
    */
   template <size_t N>
   simdjson_inline void append_raw_n(const char *str) noexcept;
+
 #if SIMDJSON_EXCEPTIONS
   /**
    * Creates an std::string from the written JSON buffer.
@@ -56147,6 +56530,15 @@ private:
    */
   simdjson_inline bool capacity_check(size_t upcoming_bytes);

+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+  /**
+   * Append constevalutil::static_string<Text>. The whole zero-padded array is
+   * copied in 16-byte blocks, but position only advances by the text length.
+   */
+  template <typename Text>
+  simdjson_inline void append_static_string() noexcept;
+#endif
+
   /**
    * Grow the buffer to at least desired_capacity bytes.
    * If the allocation fails, is_valid is set to false. We expect
@@ -56340,10 +56732,6 @@ using unchecked_writer = basic_writer<false>;
 // 16-byte blocks).
 inline constexpr size_t unchecked_slack = 64;

-consteval size_t padded_key_length(size_t length) {
-  return (length + 15) / 16 * 16;
-}
-
 // === Helper: invoke a string_builder member that writes variable-length
 // content (escape_and_append_with_quotes etc), syncing the writer's local
 // state before the call and reloading after. Used for string fields where
@@ -56433,16 +56821,16 @@ simdjson_really_inline void atom_fields(W &w, const T &t, bool &first) {
           constexpr size_t rest_key_len = first_key_len + 1;
           constexpr auto first_key = std::define_static_string(
               constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(first_key_len) - first_key_len, '\0'));
+              std::string(constevalutil::padded_key_length(first_key_len) - first_key_len, '\0'));
           constexpr auto rest_key = std::define_static_string(
               std::string(",") + constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(rest_key_len) - rest_key_len, '\0'));
-          if (!w.ensure(padded_key_length(rest_key_len))) { return; }
+              std::string(constevalutil::padded_key_length(rest_key_len) - rest_key_len, '\0'));
+          if (!w.ensure(constevalutil::padded_key_length(rest_key_len))) { return; }
           if (first) {
-            std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
+            std::memcpy(w.ptr + w.pos, first_key, constevalutil::padded_key_length(first_key_len));
             w.pos += first_key_len;
           } else {
-            std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
+            std::memcpy(w.ptr + w.pos, rest_key, constevalutil::padded_key_length(rest_key_len));
             w.pos += rest_key_len;
           }
           first = false;
@@ -57174,6 +57562,7 @@ simdjson_warn_unused simdjson_result<std::string> extract_fractured_json(
 /* begin file simdjson/generic/builder/json_string_builder-inl.h for icelake */
 #include <array>
 #include <cmath>
+#include <cstddef>
 #include <cstring>
 #include <limits>
 #include <type_traits>
@@ -58214,7 +58603,11 @@ string_builder::escape_and_append_with_quotes(const char *input) noexcept {
 #if SIMDJSON_SUPPORTS_CONCEPTS
 template <constevalutil::fixed_string key>
 simdjson_inline void string_builder::escape_and_append_with_quotes() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<constevalutil::quoted_escaped_text<key>>();
+#else
   escape_and_append_with_quotes(constevalutil::string_constant<key>::value);
+#endif
 }
 #endif

@@ -58248,6 +58641,18 @@ simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
     position += N;
   }
 }
+
+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+template <typename Text>
+simdjson_inline void string_builder::append_static_string() noexcept {
+  constexpr auto& padded = constevalutil::static_string<Text>;
+  if (capacity_check(padded.size())) {
+    std::memcpy(buffer.get() + position, padded.data(), padded.size());
+    position += constevalutil::static_string_size<Text>();
+  }
+}
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS
 // Support for optional types (std::optional, etc.)
 template <concepts::optional_type T>
@@ -58414,11 +58819,24 @@ string_builder::append_key_value(key_type key, value_type value) noexcept {
 }

 #if SIMDJSON_SUPPORTS_CONCEPTS
+#if SIMDJSON_CONSTEVAL
+template <constevalutil::fixed_string key>
+struct quoted_key_text {
+  static consteval std::string text() {
+    return constevalutil::consteval_to_quoted_escaped(key.view()) + ":";
+  }
+};
+#endif
+
 template <constevalutil::fixed_string key, typename value_type>
 simdjson_inline void
 string_builder::append_key_value(value_type value) noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<quoted_key_text<key>>();
+#else
   escape_and_append_with_quotes<key>();
   append_colon();
+#endif
   SIMDJSON_IF_CONSTEXPR(std::is_same<value_type, std::nullptr_t>::value) {
     append_null();
   }
@@ -58436,6 +58854,56 @@ string_builder::append_key_value(value_type value) noexcept {
     append(value);
   }
 }
+
+#if SIMDJSON_CONSTEVAL
+template <typename T>
+concept compile_time_formattable =
+  constevalutil::is_fixed_string<std::remove_cvref_t<T>> ||
+  std::same_as<std::remove_cvref_t<T>, bool> ||
+  std::same_as<std::remove_cvref_t<T>, std::nullptr_t>;
+
+template <constevalutil::fixed_string key, auto value>
+requires compile_time_formattable<decltype(value)>
+struct key_value_text {
+  static consteval std::string text() {
+    using value_type = std::remove_cvref_t<decltype(value)>;
+    std::string out = constevalutil::consteval_to_quoted_escaped(key.view()) + ':';
+    SIMDJSON_IF_CONSTEXPR(constevalutil::is_fixed_string<value_type>)
+      out += constevalutil::consteval_to_quoted_escaped(value.view());
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, bool>)
+      out += value ? "true" : "false";
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, std::nullptr_t>)
+      out += "null";
+    return out;
+  }
+};
+#endif
+
+template <constevalutil::fixed_string key, constevalutil::fixed_string value>
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<key_value_text<key, value>>();
+#else
+  escape_and_append_with_quotes<key>();
+  append_colon();
+  escape_and_append_with_quotes<value>();
+#endif
+}
+
+template <constevalutil::fixed_string key, auto value>
+requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  SIMDJSON_IF_CONSTEXPR(compile_time_formattable<decltype(value)>) {
+    append_static_string<key_value_text<key, value>>();
+  } else
+#endif
+  {
+    append_key_value<key>(value);
+  }
+}
 #endif

 } // namespace builder
@@ -59457,6 +59925,13 @@ public:
   template<constevalutil::fixed_string key, typename value_type>
   simdjson_inline void append_key_value(value_type value) noexcept;

+  template<constevalutil::fixed_string key, constevalutil::fixed_string value>
+  simdjson_inline void append_key_value() noexcept;
+
+  template<constevalutil::fixed_string key, auto value>
+  requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+  simdjson_inline void append_key_value() noexcept;
+
   // Support for optional types (std::optional, etc.)
   template <concepts::optional_type T>
   requires(!require_custom_serialization<T>)
@@ -59498,6 +59973,7 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
    */
   template <size_t N>
   simdjson_inline void append_raw_n(const char *str) noexcept;
+
 #if SIMDJSON_EXCEPTIONS
   /**
    * Creates an std::string from the written JSON buffer.
@@ -59577,6 +60053,15 @@ private:
    */
   simdjson_inline bool capacity_check(size_t upcoming_bytes);

+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+  /**
+   * Append constevalutil::static_string<Text>. The whole zero-padded array is
+   * copied in 16-byte blocks, but position only advances by the text length.
+   */
+  template <typename Text>
+  simdjson_inline void append_static_string() noexcept;
+#endif
+
   /**
    * Grow the buffer to at least desired_capacity bytes.
    * If the allocation fails, is_valid is set to false. We expect
@@ -59770,10 +60255,6 @@ using unchecked_writer = basic_writer<false>;
 // 16-byte blocks).
 inline constexpr size_t unchecked_slack = 64;

-consteval size_t padded_key_length(size_t length) {
-  return (length + 15) / 16 * 16;
-}
-
 // === Helper: invoke a string_builder member that writes variable-length
 // content (escape_and_append_with_quotes etc), syncing the writer's local
 // state before the call and reloading after. Used for string fields where
@@ -59863,16 +60344,16 @@ simdjson_really_inline void atom_fields(W &w, const T &t, bool &first) {
           constexpr size_t rest_key_len = first_key_len + 1;
           constexpr auto first_key = std::define_static_string(
               constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(first_key_len) - first_key_len, '\0'));
+              std::string(constevalutil::padded_key_length(first_key_len) - first_key_len, '\0'));
           constexpr auto rest_key = std::define_static_string(
               std::string(",") + constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(rest_key_len) - rest_key_len, '\0'));
-          if (!w.ensure(padded_key_length(rest_key_len))) { return; }
+              std::string(constevalutil::padded_key_length(rest_key_len) - rest_key_len, '\0'));
+          if (!w.ensure(constevalutil::padded_key_length(rest_key_len))) { return; }
           if (first) {
-            std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
+            std::memcpy(w.ptr + w.pos, first_key, constevalutil::padded_key_length(first_key_len));
             w.pos += first_key_len;
           } else {
-            std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
+            std::memcpy(w.ptr + w.pos, rest_key, constevalutil::padded_key_length(rest_key_len));
             w.pos += rest_key_len;
           }
           first = false;
@@ -60604,6 +61085,7 @@ simdjson_warn_unused simdjson_result<std::string> extract_fractured_json(
 /* begin file simdjson/generic/builder/json_string_builder-inl.h for ppc64 */
 #include <array>
 #include <cmath>
+#include <cstddef>
 #include <cstring>
 #include <limits>
 #include <type_traits>
@@ -61644,7 +62126,11 @@ string_builder::escape_and_append_with_quotes(const char *input) noexcept {
 #if SIMDJSON_SUPPORTS_CONCEPTS
 template <constevalutil::fixed_string key>
 simdjson_inline void string_builder::escape_and_append_with_quotes() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<constevalutil::quoted_escaped_text<key>>();
+#else
   escape_and_append_with_quotes(constevalutil::string_constant<key>::value);
+#endif
 }
 #endif

@@ -61678,6 +62164,18 @@ simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
     position += N;
   }
 }
+
+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+template <typename Text>
+simdjson_inline void string_builder::append_static_string() noexcept {
+  constexpr auto& padded = constevalutil::static_string<Text>;
+  if (capacity_check(padded.size())) {
+    std::memcpy(buffer.get() + position, padded.data(), padded.size());
+    position += constevalutil::static_string_size<Text>();
+  }
+}
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS
 // Support for optional types (std::optional, etc.)
 template <concepts::optional_type T>
@@ -61844,11 +62342,24 @@ string_builder::append_key_value(key_type key, value_type value) noexcept {
 }

 #if SIMDJSON_SUPPORTS_CONCEPTS
+#if SIMDJSON_CONSTEVAL
+template <constevalutil::fixed_string key>
+struct quoted_key_text {
+  static consteval std::string text() {
+    return constevalutil::consteval_to_quoted_escaped(key.view()) + ":";
+  }
+};
+#endif
+
 template <constevalutil::fixed_string key, typename value_type>
 simdjson_inline void
 string_builder::append_key_value(value_type value) noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<quoted_key_text<key>>();
+#else
   escape_and_append_with_quotes<key>();
   append_colon();
+#endif
   SIMDJSON_IF_CONSTEXPR(std::is_same<value_type, std::nullptr_t>::value) {
     append_null();
   }
@@ -61866,6 +62377,56 @@ string_builder::append_key_value(value_type value) noexcept {
     append(value);
   }
 }
+
+#if SIMDJSON_CONSTEVAL
+template <typename T>
+concept compile_time_formattable =
+  constevalutil::is_fixed_string<std::remove_cvref_t<T>> ||
+  std::same_as<std::remove_cvref_t<T>, bool> ||
+  std::same_as<std::remove_cvref_t<T>, std::nullptr_t>;
+
+template <constevalutil::fixed_string key, auto value>
+requires compile_time_formattable<decltype(value)>
+struct key_value_text {
+  static consteval std::string text() {
+    using value_type = std::remove_cvref_t<decltype(value)>;
+    std::string out = constevalutil::consteval_to_quoted_escaped(key.view()) + ':';
+    SIMDJSON_IF_CONSTEXPR(constevalutil::is_fixed_string<value_type>)
+      out += constevalutil::consteval_to_quoted_escaped(value.view());
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, bool>)
+      out += value ? "true" : "false";
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, std::nullptr_t>)
+      out += "null";
+    return out;
+  }
+};
+#endif
+
+template <constevalutil::fixed_string key, constevalutil::fixed_string value>
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<key_value_text<key, value>>();
+#else
+  escape_and_append_with_quotes<key>();
+  append_colon();
+  escape_and_append_with_quotes<value>();
+#endif
+}
+
+template <constevalutil::fixed_string key, auto value>
+requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  SIMDJSON_IF_CONSTEXPR(compile_time_formattable<decltype(value)>) {
+    append_static_string<key_value_text<key, value>>();
+  } else
+#endif
+  {
+    append_key_value<key>(value);
+  }
+}
 #endif

 } // namespace builder
@@ -63194,6 +63755,13 @@ public:
   template<constevalutil::fixed_string key, typename value_type>
   simdjson_inline void append_key_value(value_type value) noexcept;

+  template<constevalutil::fixed_string key, constevalutil::fixed_string value>
+  simdjson_inline void append_key_value() noexcept;
+
+  template<constevalutil::fixed_string key, auto value>
+  requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+  simdjson_inline void append_key_value() noexcept;
+
   // Support for optional types (std::optional, etc.)
   template <concepts::optional_type T>
   requires(!require_custom_serialization<T>)
@@ -63235,6 +63803,7 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
    */
   template <size_t N>
   simdjson_inline void append_raw_n(const char *str) noexcept;
+
 #if SIMDJSON_EXCEPTIONS
   /**
    * Creates an std::string from the written JSON buffer.
@@ -63314,6 +63883,15 @@ private:
    */
   simdjson_inline bool capacity_check(size_t upcoming_bytes);

+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+  /**
+   * Append constevalutil::static_string<Text>. The whole zero-padded array is
+   * copied in 16-byte blocks, but position only advances by the text length.
+   */
+  template <typename Text>
+  simdjson_inline void append_static_string() noexcept;
+#endif
+
   /**
    * Grow the buffer to at least desired_capacity bytes.
    * If the allocation fails, is_valid is set to false. We expect
@@ -63507,10 +64085,6 @@ using unchecked_writer = basic_writer<false>;
 // 16-byte blocks).
 inline constexpr size_t unchecked_slack = 64;

-consteval size_t padded_key_length(size_t length) {
-  return (length + 15) / 16 * 16;
-}
-
 // === Helper: invoke a string_builder member that writes variable-length
 // content (escape_and_append_with_quotes etc), syncing the writer's local
 // state before the call and reloading after. Used for string fields where
@@ -63600,16 +64174,16 @@ simdjson_really_inline void atom_fields(W &w, const T &t, bool &first) {
           constexpr size_t rest_key_len = first_key_len + 1;
           constexpr auto first_key = std::define_static_string(
               constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(first_key_len) - first_key_len, '\0'));
+              std::string(constevalutil::padded_key_length(first_key_len) - first_key_len, '\0'));
           constexpr auto rest_key = std::define_static_string(
               std::string(",") + constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(rest_key_len) - rest_key_len, '\0'));
-          if (!w.ensure(padded_key_length(rest_key_len))) { return; }
+              std::string(constevalutil::padded_key_length(rest_key_len) - rest_key_len, '\0'));
+          if (!w.ensure(constevalutil::padded_key_length(rest_key_len))) { return; }
           if (first) {
-            std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
+            std::memcpy(w.ptr + w.pos, first_key, constevalutil::padded_key_length(first_key_len));
             w.pos += first_key_len;
           } else {
-            std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
+            std::memcpy(w.ptr + w.pos, rest_key, constevalutil::padded_key_length(rest_key_len));
             w.pos += rest_key_len;
           }
           first = false;
@@ -64341,6 +64915,7 @@ simdjson_warn_unused simdjson_result<std::string> extract_fractured_json(
 /* begin file simdjson/generic/builder/json_string_builder-inl.h for westmere */
 #include <array>
 #include <cmath>
+#include <cstddef>
 #include <cstring>
 #include <limits>
 #include <type_traits>
@@ -65381,7 +65956,11 @@ string_builder::escape_and_append_with_quotes(const char *input) noexcept {
 #if SIMDJSON_SUPPORTS_CONCEPTS
 template <constevalutil::fixed_string key>
 simdjson_inline void string_builder::escape_and_append_with_quotes() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<constevalutil::quoted_escaped_text<key>>();
+#else
   escape_and_append_with_quotes(constevalutil::string_constant<key>::value);
+#endif
 }
 #endif

@@ -65415,6 +65994,18 @@ simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
     position += N;
   }
 }
+
+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+template <typename Text>
+simdjson_inline void string_builder::append_static_string() noexcept {
+  constexpr auto& padded = constevalutil::static_string<Text>;
+  if (capacity_check(padded.size())) {
+    std::memcpy(buffer.get() + position, padded.data(), padded.size());
+    position += constevalutil::static_string_size<Text>();
+  }
+}
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS
 // Support for optional types (std::optional, etc.)
 template <concepts::optional_type T>
@@ -65581,11 +66172,24 @@ string_builder::append_key_value(key_type key, value_type value) noexcept {
 }

 #if SIMDJSON_SUPPORTS_CONCEPTS
+#if SIMDJSON_CONSTEVAL
+template <constevalutil::fixed_string key>
+struct quoted_key_text {
+  static consteval std::string text() {
+    return constevalutil::consteval_to_quoted_escaped(key.view()) + ":";
+  }
+};
+#endif
+
 template <constevalutil::fixed_string key, typename value_type>
 simdjson_inline void
 string_builder::append_key_value(value_type value) noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<quoted_key_text<key>>();
+#else
   escape_and_append_with_quotes<key>();
   append_colon();
+#endif
   SIMDJSON_IF_CONSTEXPR(std::is_same<value_type, std::nullptr_t>::value) {
     append_null();
   }
@@ -65603,6 +66207,56 @@ string_builder::append_key_value(value_type value) noexcept {
     append(value);
   }
 }
+
+#if SIMDJSON_CONSTEVAL
+template <typename T>
+concept compile_time_formattable =
+  constevalutil::is_fixed_string<std::remove_cvref_t<T>> ||
+  std::same_as<std::remove_cvref_t<T>, bool> ||
+  std::same_as<std::remove_cvref_t<T>, std::nullptr_t>;
+
+template <constevalutil::fixed_string key, auto value>
+requires compile_time_formattable<decltype(value)>
+struct key_value_text {
+  static consteval std::string text() {
+    using value_type = std::remove_cvref_t<decltype(value)>;
+    std::string out = constevalutil::consteval_to_quoted_escaped(key.view()) + ':';
+    SIMDJSON_IF_CONSTEXPR(constevalutil::is_fixed_string<value_type>)
+      out += constevalutil::consteval_to_quoted_escaped(value.view());
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, bool>)
+      out += value ? "true" : "false";
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, std::nullptr_t>)
+      out += "null";
+    return out;
+  }
+};
+#endif
+
+template <constevalutil::fixed_string key, constevalutil::fixed_string value>
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<key_value_text<key, value>>();
+#else
+  escape_and_append_with_quotes<key>();
+  append_colon();
+  escape_and_append_with_quotes<value>();
+#endif
+}
+
+template <constevalutil::fixed_string key, auto value>
+requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  SIMDJSON_IF_CONSTEXPR(compile_time_formattable<decltype(value)>) {
+    append_static_string<key_value_text<key, value>>();
+  } else
+#endif
+  {
+    append_key_value<key>(value);
+  }
+}
 #endif

 } // namespace builder
@@ -66421,6 +67075,13 @@ public:
   template<constevalutil::fixed_string key, typename value_type>
   simdjson_inline void append_key_value(value_type value) noexcept;

+  template<constevalutil::fixed_string key, constevalutil::fixed_string value>
+  simdjson_inline void append_key_value() noexcept;
+
+  template<constevalutil::fixed_string key, auto value>
+  requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+  simdjson_inline void append_key_value() noexcept;
+
   // Support for optional types (std::optional, etc.)
   template <concepts::optional_type T>
   requires(!require_custom_serialization<T>)
@@ -66462,6 +67123,7 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
    */
   template <size_t N>
   simdjson_inline void append_raw_n(const char *str) noexcept;
+
 #if SIMDJSON_EXCEPTIONS
   /**
    * Creates an std::string from the written JSON buffer.
@@ -66541,6 +67203,15 @@ private:
    */
   simdjson_inline bool capacity_check(size_t upcoming_bytes);

+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+  /**
+   * Append constevalutil::static_string<Text>. The whole zero-padded array is
+   * copied in 16-byte blocks, but position only advances by the text length.
+   */
+  template <typename Text>
+  simdjson_inline void append_static_string() noexcept;
+#endif
+
   /**
    * Grow the buffer to at least desired_capacity bytes.
    * If the allocation fails, is_valid is set to false. We expect
@@ -66734,10 +67405,6 @@ using unchecked_writer = basic_writer<false>;
 // 16-byte blocks).
 inline constexpr size_t unchecked_slack = 64;

-consteval size_t padded_key_length(size_t length) {
-  return (length + 15) / 16 * 16;
-}
-
 // === Helper: invoke a string_builder member that writes variable-length
 // content (escape_and_append_with_quotes etc), syncing the writer's local
 // state before the call and reloading after. Used for string fields where
@@ -66827,16 +67494,16 @@ simdjson_really_inline void atom_fields(W &w, const T &t, bool &first) {
           constexpr size_t rest_key_len = first_key_len + 1;
           constexpr auto first_key = std::define_static_string(
               constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(first_key_len) - first_key_len, '\0'));
+              std::string(constevalutil::padded_key_length(first_key_len) - first_key_len, '\0'));
           constexpr auto rest_key = std::define_static_string(
               std::string(",") + constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(rest_key_len) - rest_key_len, '\0'));
-          if (!w.ensure(padded_key_length(rest_key_len))) { return; }
+              std::string(constevalutil::padded_key_length(rest_key_len) - rest_key_len, '\0'));
+          if (!w.ensure(constevalutil::padded_key_length(rest_key_len))) { return; }
           if (first) {
-            std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
+            std::memcpy(w.ptr + w.pos, first_key, constevalutil::padded_key_length(first_key_len));
             w.pos += first_key_len;
           } else {
-            std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
+            std::memcpy(w.ptr + w.pos, rest_key, constevalutil::padded_key_length(rest_key_len));
             w.pos += rest_key_len;
           }
           first = false;
@@ -67568,6 +68235,7 @@ simdjson_warn_unused simdjson_result<std::string> extract_fractured_json(
 /* begin file simdjson/generic/builder/json_string_builder-inl.h for lsx */
 #include <array>
 #include <cmath>
+#include <cstddef>
 #include <cstring>
 #include <limits>
 #include <type_traits>
@@ -68608,7 +69276,11 @@ string_builder::escape_and_append_with_quotes(const char *input) noexcept {
 #if SIMDJSON_SUPPORTS_CONCEPTS
 template <constevalutil::fixed_string key>
 simdjson_inline void string_builder::escape_and_append_with_quotes() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<constevalutil::quoted_escaped_text<key>>();
+#else
   escape_and_append_with_quotes(constevalutil::string_constant<key>::value);
+#endif
 }
 #endif

@@ -68642,6 +69314,18 @@ simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
     position += N;
   }
 }
+
+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+template <typename Text>
+simdjson_inline void string_builder::append_static_string() noexcept {
+  constexpr auto& padded = constevalutil::static_string<Text>;
+  if (capacity_check(padded.size())) {
+    std::memcpy(buffer.get() + position, padded.data(), padded.size());
+    position += constevalutil::static_string_size<Text>();
+  }
+}
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS
 // Support for optional types (std::optional, etc.)
 template <concepts::optional_type T>
@@ -68808,11 +69492,24 @@ string_builder::append_key_value(key_type key, value_type value) noexcept {
 }

 #if SIMDJSON_SUPPORTS_CONCEPTS
+#if SIMDJSON_CONSTEVAL
+template <constevalutil::fixed_string key>
+struct quoted_key_text {
+  static consteval std::string text() {
+    return constevalutil::consteval_to_quoted_escaped(key.view()) + ":";
+  }
+};
+#endif
+
 template <constevalutil::fixed_string key, typename value_type>
 simdjson_inline void
 string_builder::append_key_value(value_type value) noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<quoted_key_text<key>>();
+#else
   escape_and_append_with_quotes<key>();
   append_colon();
+#endif
   SIMDJSON_IF_CONSTEXPR(std::is_same<value_type, std::nullptr_t>::value) {
     append_null();
   }
@@ -68830,6 +69527,56 @@ string_builder::append_key_value(value_type value) noexcept {
     append(value);
   }
 }
+
+#if SIMDJSON_CONSTEVAL
+template <typename T>
+concept compile_time_formattable =
+  constevalutil::is_fixed_string<std::remove_cvref_t<T>> ||
+  std::same_as<std::remove_cvref_t<T>, bool> ||
+  std::same_as<std::remove_cvref_t<T>, std::nullptr_t>;
+
+template <constevalutil::fixed_string key, auto value>
+requires compile_time_formattable<decltype(value)>
+struct key_value_text {
+  static consteval std::string text() {
+    using value_type = std::remove_cvref_t<decltype(value)>;
+    std::string out = constevalutil::consteval_to_quoted_escaped(key.view()) + ':';
+    SIMDJSON_IF_CONSTEXPR(constevalutil::is_fixed_string<value_type>)
+      out += constevalutil::consteval_to_quoted_escaped(value.view());
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, bool>)
+      out += value ? "true" : "false";
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, std::nullptr_t>)
+      out += "null";
+    return out;
+  }
+};
+#endif
+
+template <constevalutil::fixed_string key, constevalutil::fixed_string value>
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<key_value_text<key, value>>();
+#else
+  escape_and_append_with_quotes<key>();
+  append_colon();
+  escape_and_append_with_quotes<value>();
+#endif
+}
+
+template <constevalutil::fixed_string key, auto value>
+requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  SIMDJSON_IF_CONSTEXPR(compile_time_formattable<decltype(value)>) {
+    append_static_string<key_value_text<key, value>>();
+  } else
+#endif
+  {
+    append_key_value<key>(value);
+  }
+}
 #endif

 } // namespace builder
@@ -69671,6 +70418,13 @@ public:
   template<constevalutil::fixed_string key, typename value_type>
   simdjson_inline void append_key_value(value_type value) noexcept;

+  template<constevalutil::fixed_string key, constevalutil::fixed_string value>
+  simdjson_inline void append_key_value() noexcept;
+
+  template<constevalutil::fixed_string key, auto value>
+  requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+  simdjson_inline void append_key_value() noexcept;
+
   // Support for optional types (std::optional, etc.)
   template <concepts::optional_type T>
   requires(!require_custom_serialization<T>)
@@ -69712,6 +70466,7 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
    */
   template <size_t N>
   simdjson_inline void append_raw_n(const char *str) noexcept;
+
 #if SIMDJSON_EXCEPTIONS
   /**
    * Creates an std::string from the written JSON buffer.
@@ -69791,6 +70546,15 @@ private:
    */
   simdjson_inline bool capacity_check(size_t upcoming_bytes);

+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+  /**
+   * Append constevalutil::static_string<Text>. The whole zero-padded array is
+   * copied in 16-byte blocks, but position only advances by the text length.
+   */
+  template <typename Text>
+  simdjson_inline void append_static_string() noexcept;
+#endif
+
   /**
    * Grow the buffer to at least desired_capacity bytes.
    * If the allocation fails, is_valid is set to false. We expect
@@ -69984,10 +70748,6 @@ using unchecked_writer = basic_writer<false>;
 // 16-byte blocks).
 inline constexpr size_t unchecked_slack = 64;

-consteval size_t padded_key_length(size_t length) {
-  return (length + 15) / 16 * 16;
-}
-
 // === Helper: invoke a string_builder member that writes variable-length
 // content (escape_and_append_with_quotes etc), syncing the writer's local
 // state before the call and reloading after. Used for string fields where
@@ -70077,16 +70837,16 @@ simdjson_really_inline void atom_fields(W &w, const T &t, bool &first) {
           constexpr size_t rest_key_len = first_key_len + 1;
           constexpr auto first_key = std::define_static_string(
               constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(first_key_len) - first_key_len, '\0'));
+              std::string(constevalutil::padded_key_length(first_key_len) - first_key_len, '\0'));
           constexpr auto rest_key = std::define_static_string(
               std::string(",") + constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(rest_key_len) - rest_key_len, '\0'));
-          if (!w.ensure(padded_key_length(rest_key_len))) { return; }
+              std::string(constevalutil::padded_key_length(rest_key_len) - rest_key_len, '\0'));
+          if (!w.ensure(constevalutil::padded_key_length(rest_key_len))) { return; }
           if (first) {
-            std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
+            std::memcpy(w.ptr + w.pos, first_key, constevalutil::padded_key_length(first_key_len));
             w.pos += first_key_len;
           } else {
-            std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
+            std::memcpy(w.ptr + w.pos, rest_key, constevalutil::padded_key_length(rest_key_len));
             w.pos += rest_key_len;
           }
           first = false;
@@ -70818,6 +71578,7 @@ simdjson_warn_unused simdjson_result<std::string> extract_fractured_json(
 /* begin file simdjson/generic/builder/json_string_builder-inl.h for lasx */
 #include <array>
 #include <cmath>
+#include <cstddef>
 #include <cstring>
 #include <limits>
 #include <type_traits>
@@ -71858,7 +72619,11 @@ string_builder::escape_and_append_with_quotes(const char *input) noexcept {
 #if SIMDJSON_SUPPORTS_CONCEPTS
 template <constevalutil::fixed_string key>
 simdjson_inline void string_builder::escape_and_append_with_quotes() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<constevalutil::quoted_escaped_text<key>>();
+#else
   escape_and_append_with_quotes(constevalutil::string_constant<key>::value);
+#endif
 }
 #endif

@@ -71892,6 +72657,18 @@ simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
     position += N;
   }
 }
+
+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+template <typename Text>
+simdjson_inline void string_builder::append_static_string() noexcept {
+  constexpr auto& padded = constevalutil::static_string<Text>;
+  if (capacity_check(padded.size())) {
+    std::memcpy(buffer.get() + position, padded.data(), padded.size());
+    position += constevalutil::static_string_size<Text>();
+  }
+}
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS
 // Support for optional types (std::optional, etc.)
 template <concepts::optional_type T>
@@ -72058,11 +72835,24 @@ string_builder::append_key_value(key_type key, value_type value) noexcept {
 }

 #if SIMDJSON_SUPPORTS_CONCEPTS
+#if SIMDJSON_CONSTEVAL
+template <constevalutil::fixed_string key>
+struct quoted_key_text {
+  static consteval std::string text() {
+    return constevalutil::consteval_to_quoted_escaped(key.view()) + ":";
+  }
+};
+#endif
+
 template <constevalutil::fixed_string key, typename value_type>
 simdjson_inline void
 string_builder::append_key_value(value_type value) noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<quoted_key_text<key>>();
+#else
   escape_and_append_with_quotes<key>();
   append_colon();
+#endif
   SIMDJSON_IF_CONSTEXPR(std::is_same<value_type, std::nullptr_t>::value) {
     append_null();
   }
@@ -72080,6 +72870,56 @@ string_builder::append_key_value(value_type value) noexcept {
     append(value);
   }
 }
+
+#if SIMDJSON_CONSTEVAL
+template <typename T>
+concept compile_time_formattable =
+  constevalutil::is_fixed_string<std::remove_cvref_t<T>> ||
+  std::same_as<std::remove_cvref_t<T>, bool> ||
+  std::same_as<std::remove_cvref_t<T>, std::nullptr_t>;
+
+template <constevalutil::fixed_string key, auto value>
+requires compile_time_formattable<decltype(value)>
+struct key_value_text {
+  static consteval std::string text() {
+    using value_type = std::remove_cvref_t<decltype(value)>;
+    std::string out = constevalutil::consteval_to_quoted_escaped(key.view()) + ':';
+    SIMDJSON_IF_CONSTEXPR(constevalutil::is_fixed_string<value_type>)
+      out += constevalutil::consteval_to_quoted_escaped(value.view());
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, bool>)
+      out += value ? "true" : "false";
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, std::nullptr_t>)
+      out += "null";
+    return out;
+  }
+};
+#endif
+
+template <constevalutil::fixed_string key, constevalutil::fixed_string value>
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<key_value_text<key, value>>();
+#else
+  escape_and_append_with_quotes<key>();
+  append_colon();
+  escape_and_append_with_quotes<value>();
+#endif
+}
+
+template <constevalutil::fixed_string key, auto value>
+requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  SIMDJSON_IF_CONSTEXPR(compile_time_formattable<decltype(value)>) {
+    append_static_string<key_value_text<key, value>>();
+  } else
+#endif
+  {
+    append_key_value<key>(value);
+  }
+}
 #endif

 } // namespace builder
@@ -72924,6 +73764,13 @@ public:
   template<constevalutil::fixed_string key, typename value_type>
   simdjson_inline void append_key_value(value_type value) noexcept;

+  template<constevalutil::fixed_string key, constevalutil::fixed_string value>
+  simdjson_inline void append_key_value() noexcept;
+
+  template<constevalutil::fixed_string key, auto value>
+  requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+  simdjson_inline void append_key_value() noexcept;
+
   // Support for optional types (std::optional, etc.)
   template <concepts::optional_type T>
   requires(!require_custom_serialization<T>)
@@ -72965,6 +73812,7 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
    */
   template <size_t N>
   simdjson_inline void append_raw_n(const char *str) noexcept;
+
 #if SIMDJSON_EXCEPTIONS
   /**
    * Creates an std::string from the written JSON buffer.
@@ -73044,6 +73892,15 @@ private:
    */
   simdjson_inline bool capacity_check(size_t upcoming_bytes);

+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+  /**
+   * Append constevalutil::static_string<Text>. The whole zero-padded array is
+   * copied in 16-byte blocks, but position only advances by the text length.
+   */
+  template <typename Text>
+  simdjson_inline void append_static_string() noexcept;
+#endif
+
   /**
    * Grow the buffer to at least desired_capacity bytes.
    * If the allocation fails, is_valid is set to false. We expect
@@ -73237,10 +74094,6 @@ using unchecked_writer = basic_writer<false>;
 // 16-byte blocks).
 inline constexpr size_t unchecked_slack = 64;

-consteval size_t padded_key_length(size_t length) {
-  return (length + 15) / 16 * 16;
-}
-
 // === Helper: invoke a string_builder member that writes variable-length
 // content (escape_and_append_with_quotes etc), syncing the writer's local
 // state before the call and reloading after. Used for string fields where
@@ -73330,16 +74183,16 @@ simdjson_really_inline void atom_fields(W &w, const T &t, bool &first) {
           constexpr size_t rest_key_len = first_key_len + 1;
           constexpr auto first_key = std::define_static_string(
               constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(first_key_len) - first_key_len, '\0'));
+              std::string(constevalutil::padded_key_length(first_key_len) - first_key_len, '\0'));
           constexpr auto rest_key = std::define_static_string(
               std::string(",") + constevalutil::consteval_to_quoted_escaped(key_name) + ":" +
-              std::string(padded_key_length(rest_key_len) - rest_key_len, '\0'));
-          if (!w.ensure(padded_key_length(rest_key_len))) { return; }
+              std::string(constevalutil::padded_key_length(rest_key_len) - rest_key_len, '\0'));
+          if (!w.ensure(constevalutil::padded_key_length(rest_key_len))) { return; }
           if (first) {
-            std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
+            std::memcpy(w.ptr + w.pos, first_key, constevalutil::padded_key_length(first_key_len));
             w.pos += first_key_len;
           } else {
-            std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
+            std::memcpy(w.ptr + w.pos, rest_key, constevalutil::padded_key_length(rest_key_len));
             w.pos += rest_key_len;
           }
           first = false;
@@ -74071,6 +74924,7 @@ simdjson_warn_unused simdjson_result<std::string> extract_fractured_json(
 /* begin file simdjson/generic/builder/json_string_builder-inl.h for rvv_vls */
 #include <array>
 #include <cmath>
+#include <cstddef>
 #include <cstring>
 #include <limits>
 #include <type_traits>
@@ -75111,7 +75965,11 @@ string_builder::escape_and_append_with_quotes(const char *input) noexcept {
 #if SIMDJSON_SUPPORTS_CONCEPTS
 template <constevalutil::fixed_string key>
 simdjson_inline void string_builder::escape_and_append_with_quotes() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<constevalutil::quoted_escaped_text<key>>();
+#else
   escape_and_append_with_quotes(constevalutil::string_constant<key>::value);
+#endif
 }
 #endif

@@ -75145,6 +76003,18 @@ simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
     position += N;
   }
 }
+
+#if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_CONSTEVAL
+template <typename Text>
+simdjson_inline void string_builder::append_static_string() noexcept {
+  constexpr auto& padded = constevalutil::static_string<Text>;
+  if (capacity_check(padded.size())) {
+    std::memcpy(buffer.get() + position, padded.data(), padded.size());
+    position += constevalutil::static_string_size<Text>();
+  }
+}
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS
 // Support for optional types (std::optional, etc.)
 template <concepts::optional_type T>
@@ -75311,11 +76181,24 @@ string_builder::append_key_value(key_type key, value_type value) noexcept {
 }

 #if SIMDJSON_SUPPORTS_CONCEPTS
+#if SIMDJSON_CONSTEVAL
+template <constevalutil::fixed_string key>
+struct quoted_key_text {
+  static consteval std::string text() {
+    return constevalutil::consteval_to_quoted_escaped(key.view()) + ":";
+  }
+};
+#endif
+
 template <constevalutil::fixed_string key, typename value_type>
 simdjson_inline void
 string_builder::append_key_value(value_type value) noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<quoted_key_text<key>>();
+#else
   escape_and_append_with_quotes<key>();
   append_colon();
+#endif
   SIMDJSON_IF_CONSTEXPR(std::is_same<value_type, std::nullptr_t>::value) {
     append_null();
   }
@@ -75333,6 +76216,56 @@ string_builder::append_key_value(value_type value) noexcept {
     append(value);
   }
 }
+
+#if SIMDJSON_CONSTEVAL
+template <typename T>
+concept compile_time_formattable =
+  constevalutil::is_fixed_string<std::remove_cvref_t<T>> ||
+  std::same_as<std::remove_cvref_t<T>, bool> ||
+  std::same_as<std::remove_cvref_t<T>, std::nullptr_t>;
+
+template <constevalutil::fixed_string key, auto value>
+requires compile_time_formattable<decltype(value)>
+struct key_value_text {
+  static consteval std::string text() {
+    using value_type = std::remove_cvref_t<decltype(value)>;
+    std::string out = constevalutil::consteval_to_quoted_escaped(key.view()) + ':';
+    SIMDJSON_IF_CONSTEXPR(constevalutil::is_fixed_string<value_type>)
+      out += constevalutil::consteval_to_quoted_escaped(value.view());
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, bool>)
+      out += value ? "true" : "false";
+    else SIMDJSON_IF_CONSTEXPR(std::same_as<value_type, std::nullptr_t>)
+      out += "null";
+    return out;
+  }
+};
+#endif
+
+template <constevalutil::fixed_string key, constevalutil::fixed_string value>
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  append_static_string<key_value_text<key, value>>();
+#else
+  escape_and_append_with_quotes<key>();
+  append_colon();
+  escape_and_append_with_quotes<value>();
+#endif
+}
+
+template <constevalutil::fixed_string key, auto value>
+requires (!constevalutil::is_fixed_string<std::remove_cvref_t<decltype(value)>>)
+simdjson_inline void
+string_builder::append_key_value() noexcept {
+#if SIMDJSON_CONSTEVAL
+  SIMDJSON_IF_CONSTEXPR(compile_time_formattable<decltype(value)>) {
+    append_static_string<key_value_text<key, value>>();
+  } else
+#endif
+  {
+    append_key_value<key>(value);
+  }
+}
 #endif

 } // namespace builder
@@ -81909,6 +82842,20 @@ public:
   #define SIMDJSON_KEY_SELECTOR_HAS_LSX 0
 #endif

+// Clang 15 and earlier reject a call to a consteval function from within a
+// consteval function template when an argument refers to one of the caller's
+// reference parameters ("function parameter 'keys' with unknown value cannot
+// be used in a constant expression"). With those compilers, the helpers below
+// are merely constexpr: the perfect-hash tables are still computed at compile
+// time because they initialize static constexpr data members.
+#ifndef SIMDJSON_KEY_SELECTOR_CONSTEVAL
+#if defined(__clang__) && ((defined(__apple_build_version__) && __apple_build_version__ < 15000000) || (!defined(__apple_build_version__) && __clang_major__ < 16))
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL constexpr
+#else
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL consteval
+#endif
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS

 namespace simdjson {
@@ -81963,7 +82910,7 @@ constexpr std::size_t char_at(std::string_view key, std::size_t pos) noexcept {
 // lengths differ modulo the table size are separated by the length term in the
 // hash, so they need no position coverage.
 template <std::size_t N>
-consteval std::size_t count_undistinguished_pairs(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t count_undistinguished_pairs(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -81986,7 +82933,7 @@ consteval std::size_t count_undistinguished_pairs(
 }

 template <std::size_t N>
-consteval bool positions_distinguish(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool positions_distinguish(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -81996,7 +82943,7 @@ consteval bool positions_distinguish(

 // Number of distinct (length % modulus, char_at(key, pos)) pairs at a position.
 template <std::size_t N>
-consteval std::size_t discriminating_power(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t discriminating_power(
     const std::array<std::string_view, N>& keys,
     std::size_t pos,
     std::size_t modulus) {
@@ -82020,7 +82967,7 @@ consteval std::size_t discriminating_power(
 }

 template <std::size_t N>
-consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
     std::size_t m = 0;
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].size() > m) { m = keys[i].size(); }
@@ -82030,7 +82977,7 @@ consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys

 // Bounded backtracking DFS for a minimal set of distinguishing positions.
 template <std::size_t N>
-consteval bool backtracking_search(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool backtracking_search(
     const std::array<std::string_view, N>& keys,
     const std::size_t* candidates,
     std::size_t num_candidates,
@@ -82081,7 +83028,7 @@ consteval bool backtracking_search(

 // Phase 1: select character positions that distinguish all colliding pairs.
 template <std::size_t N>
-consteval std::size_t select_positions(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t select_positions(
     const std::array<std::string_view, N>& keys,
     std::array<std::size_t, MAX_POSITIONS>& positions,
     std::size_t modulus) {
@@ -82160,7 +83107,7 @@ struct phf_result {
 // (position, character) symbol at a time; never revisits a value. Equivalence
 // classes (keys sharing the same undetermined symbols) keep the search cheap.
 template <std::size_t N, std::size_t M>
-consteval bool try_generate_gperf(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_generate_gperf(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -82308,7 +83255,7 @@ consteval bool try_generate_gperf(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -82327,7 +83274,7 @@ consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_
 }

 template <std::size_t N, std::size_t M, std::size_t MaxM>
-consteval bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     if (try_compute_phf<N, M>(keys, result)) { return true; }
     constexpr std::size_t NextM = M * 2;
     if constexpr (NextM <= MaxM) { return try_gperf_po2<N, NextM, MaxM>(keys, result); }
@@ -82362,7 +83309,7 @@ constexpr std::size_t hd_key_hash_4(std::string_view key) noexcept {
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_hash_and_displace(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_hash_and_displace(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -82462,7 +83409,7 @@ consteval bool try_hash_and_displace(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -82481,7 +83428,7 @@ consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, p
 }

 template <std::size_t N, std::size_t M>
-consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     phf_result<N> result{};
     if (try_compute_phf_hd<N, M>(keys, result)) { return result; }
@@ -82497,7 +83444,7 @@ consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>
 // Compute a perfect hash for `keys`: try gperf at power-of-two sizes (capped so
 // the runtime tables stay within uint8 indices), then fall back to H&D.
 template <std::size_t N>
-consteval phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
     constexpr std::size_t StartM = next_power_of_2(N);
     constexpr std::size_t GPERF_MAX_TABLE =
         phf_result<N>::MAX_TABLE_SIZE < 256 ? phf_result<N>::MAX_TABLE_SIZE : 256;
@@ -82534,7 +83481,7 @@ constexpr std::size_t compute_max_key_len(const std::array<std::string_view, N>&

 // Validate keys and build the runtime tables from the computed perfect hash.
 template <std::size_t N, std::size_t TableSize, std::size_t MaxKeyLen>
-consteval phf_data<N, TableSize, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_data<N, TableSize, MaxKeyLen>
 build_phf_data(const std::array<std::string_view, N>& keys, const phf_result<N>& result) {
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].empty())            { compile_time_error("empty keys are not allowed in key_selector"); }
@@ -82843,7 +83790,7 @@ constexpr unsigned window_value(const std::array<std::string_view, N>& keys,
 }

 template <std::size_t N, std::size_t MaxKeyLen>
-consteval window_data<N, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL window_data<N, MaxKeyLen>
 compute_window(const std::array<std::string_view, N>& keys) {
     window_data<N, MaxKeyLen> out{};

@@ -82928,7 +83875,7 @@ match_window_candidate(const char* p, std::uint8_t ki,
 // --- describe() string helpers (constexpr; no std::to_string, which is not) ---

 // Append the decimal form of v to s.
-SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
+inline SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
     if (v == 0) { s.push_back('0'); return; }
     char buf[20];
     std::size_t n = 0;
@@ -82938,7 +83885,7 @@ SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {

 // Append a byte as its decimal value, plus the printable character in quotes
 // when it is in the printable ASCII range (e.g. "110 ('n')").
-SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
+inline SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
     append_uint(s, b);
     if (b >= 0x20 && b < 0x7f) {
         s += " ('";
@@ -85779,30 +86726,36 @@ inline error_code array::for_each_at_path_with_wildcard(std::string_view json_pa
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback);
-        if(err) { return err; }
+        // An element that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     // Specific index case in which we access the element at the given index
-    size_t idx = 0;
-
     for (char c : key) {
       if(c < '0' || c > '9'){
         return INVALID_JSON_POINTER;
       }
-      idx = idx*10 + (c - '0');
     }
-
-    auto element = at(idx);
+    // Rejects leading zeros and indexes that overflow size_t, as DOM does.
+    size_t idx;
+    size_t idx_length;
+    error_code error = internal::parse_json_pointer_array_index(key, idx, idx_length);
     value val;
-    SIMDJSON_TRY(element.get(val));
+    if (!error) { error = at(idx).get(val); }
+    if (error) {
+      if (error == INDEX_OUT_OF_BOUNDS && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }
     if (remaining_path.empty()){
       callback(val);
       return SUCCESS;
     } else {
-      return element.for_each_at_path_with_wildcard(remaining_path, callback);
+      return val.for_each_at_path_with_wildcard(remaining_path, callback);
     }
   }
 }
@@ -90113,13 +91066,21 @@ inline error_code object::for_each_at_path_with_wildcard(std::string_view json_p
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback));
+        // A field that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     value val;
-    SIMDJSON_TRY(find_field(key).get(val));
+    error_code error = find_field(key).get(val);
+    if (error) {
+      if (error == NO_SUCH_FIELD && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }

     if (remaining_path.empty()) {
       callback(val);
@@ -99628,6 +100589,20 @@ public:
   #define SIMDJSON_KEY_SELECTOR_HAS_LSX 0
 #endif

+// Clang 15 and earlier reject a call to a consteval function from within a
+// consteval function template when an argument refers to one of the caller's
+// reference parameters ("function parameter 'keys' with unknown value cannot
+// be used in a constant expression"). With those compilers, the helpers below
+// are merely constexpr: the perfect-hash tables are still computed at compile
+// time because they initialize static constexpr data members.
+#ifndef SIMDJSON_KEY_SELECTOR_CONSTEVAL
+#if defined(__clang__) && ((defined(__apple_build_version__) && __apple_build_version__ < 15000000) || (!defined(__apple_build_version__) && __clang_major__ < 16))
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL constexpr
+#else
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL consteval
+#endif
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS

 namespace simdjson {
@@ -99682,7 +100657,7 @@ constexpr std::size_t char_at(std::string_view key, std::size_t pos) noexcept {
 // lengths differ modulo the table size are separated by the length term in the
 // hash, so they need no position coverage.
 template <std::size_t N>
-consteval std::size_t count_undistinguished_pairs(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t count_undistinguished_pairs(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -99705,7 +100680,7 @@ consteval std::size_t count_undistinguished_pairs(
 }

 template <std::size_t N>
-consteval bool positions_distinguish(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool positions_distinguish(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -99715,7 +100690,7 @@ consteval bool positions_distinguish(

 // Number of distinct (length % modulus, char_at(key, pos)) pairs at a position.
 template <std::size_t N>
-consteval std::size_t discriminating_power(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t discriminating_power(
     const std::array<std::string_view, N>& keys,
     std::size_t pos,
     std::size_t modulus) {
@@ -99739,7 +100714,7 @@ consteval std::size_t discriminating_power(
 }

 template <std::size_t N>
-consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
     std::size_t m = 0;
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].size() > m) { m = keys[i].size(); }
@@ -99749,7 +100724,7 @@ consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys

 // Bounded backtracking DFS for a minimal set of distinguishing positions.
 template <std::size_t N>
-consteval bool backtracking_search(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool backtracking_search(
     const std::array<std::string_view, N>& keys,
     const std::size_t* candidates,
     std::size_t num_candidates,
@@ -99800,7 +100775,7 @@ consteval bool backtracking_search(

 // Phase 1: select character positions that distinguish all colliding pairs.
 template <std::size_t N>
-consteval std::size_t select_positions(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t select_positions(
     const std::array<std::string_view, N>& keys,
     std::array<std::size_t, MAX_POSITIONS>& positions,
     std::size_t modulus) {
@@ -99879,7 +100854,7 @@ struct phf_result {
 // (position, character) symbol at a time; never revisits a value. Equivalence
 // classes (keys sharing the same undetermined symbols) keep the search cheap.
 template <std::size_t N, std::size_t M>
-consteval bool try_generate_gperf(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_generate_gperf(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -100027,7 +101002,7 @@ consteval bool try_generate_gperf(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -100046,7 +101021,7 @@ consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_
 }

 template <std::size_t N, std::size_t M, std::size_t MaxM>
-consteval bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     if (try_compute_phf<N, M>(keys, result)) { return true; }
     constexpr std::size_t NextM = M * 2;
     if constexpr (NextM <= MaxM) { return try_gperf_po2<N, NextM, MaxM>(keys, result); }
@@ -100081,7 +101056,7 @@ constexpr std::size_t hd_key_hash_4(std::string_view key) noexcept {
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_hash_and_displace(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_hash_and_displace(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -100181,7 +101156,7 @@ consteval bool try_hash_and_displace(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -100200,7 +101175,7 @@ consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, p
 }

 template <std::size_t N, std::size_t M>
-consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     phf_result<N> result{};
     if (try_compute_phf_hd<N, M>(keys, result)) { return result; }
@@ -100216,7 +101191,7 @@ consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>
 // Compute a perfect hash for `keys`: try gperf at power-of-two sizes (capped so
 // the runtime tables stay within uint8 indices), then fall back to H&D.
 template <std::size_t N>
-consteval phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
     constexpr std::size_t StartM = next_power_of_2(N);
     constexpr std::size_t GPERF_MAX_TABLE =
         phf_result<N>::MAX_TABLE_SIZE < 256 ? phf_result<N>::MAX_TABLE_SIZE : 256;
@@ -100253,7 +101228,7 @@ constexpr std::size_t compute_max_key_len(const std::array<std::string_view, N>&

 // Validate keys and build the runtime tables from the computed perfect hash.
 template <std::size_t N, std::size_t TableSize, std::size_t MaxKeyLen>
-consteval phf_data<N, TableSize, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_data<N, TableSize, MaxKeyLen>
 build_phf_data(const std::array<std::string_view, N>& keys, const phf_result<N>& result) {
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].empty())            { compile_time_error("empty keys are not allowed in key_selector"); }
@@ -100562,7 +101537,7 @@ constexpr unsigned window_value(const std::array<std::string_view, N>& keys,
 }

 template <std::size_t N, std::size_t MaxKeyLen>
-consteval window_data<N, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL window_data<N, MaxKeyLen>
 compute_window(const std::array<std::string_view, N>& keys) {
     window_data<N, MaxKeyLen> out{};

@@ -100647,7 +101622,7 @@ match_window_candidate(const char* p, std::uint8_t ki,
 // --- describe() string helpers (constexpr; no std::to_string, which is not) ---

 // Append the decimal form of v to s.
-SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
+inline SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
     if (v == 0) { s.push_back('0'); return; }
     char buf[20];
     std::size_t n = 0;
@@ -100657,7 +101632,7 @@ SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {

 // Append a byte as its decimal value, plus the printable character in quotes
 // when it is in the printable ASCII range (e.g. "110 ('n')").
-SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
+inline SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
     append_uint(s, b);
     if (b >= 0x20 && b < 0x7f) {
         s += " ('";
@@ -103498,30 +104473,36 @@ inline error_code array::for_each_at_path_with_wildcard(std::string_view json_pa
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback);
-        if(err) { return err; }
+        // An element that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     // Specific index case in which we access the element at the given index
-    size_t idx = 0;
-
     for (char c : key) {
       if(c < '0' || c > '9'){
         return INVALID_JSON_POINTER;
       }
-      idx = idx*10 + (c - '0');
     }
-
-    auto element = at(idx);
+    // Rejects leading zeros and indexes that overflow size_t, as DOM does.
+    size_t idx;
+    size_t idx_length;
+    error_code error = internal::parse_json_pointer_array_index(key, idx, idx_length);
     value val;
-    SIMDJSON_TRY(element.get(val));
+    if (!error) { error = at(idx).get(val); }
+    if (error) {
+      if (error == INDEX_OUT_OF_BOUNDS && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }
     if (remaining_path.empty()){
       callback(val);
       return SUCCESS;
     } else {
-      return element.for_each_at_path_with_wildcard(remaining_path, callback);
+      return val.for_each_at_path_with_wildcard(remaining_path, callback);
     }
   }
 }
@@ -107832,13 +108813,21 @@ inline error_code object::for_each_at_path_with_wildcard(std::string_view json_p
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback));
+        // A field that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     value val;
-    SIMDJSON_TRY(find_field(key).get(val));
+    error_code error = find_field(key).get(val);
+    if (error) {
+      if (error == NO_SUCH_FIELD && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }

     if (remaining_path.empty()) {
       callback(val);
@@ -117824,6 +118813,20 @@ public:
   #define SIMDJSON_KEY_SELECTOR_HAS_LSX 0
 #endif

+// Clang 15 and earlier reject a call to a consteval function from within a
+// consteval function template when an argument refers to one of the caller's
+// reference parameters ("function parameter 'keys' with unknown value cannot
+// be used in a constant expression"). With those compilers, the helpers below
+// are merely constexpr: the perfect-hash tables are still computed at compile
+// time because they initialize static constexpr data members.
+#ifndef SIMDJSON_KEY_SELECTOR_CONSTEVAL
+#if defined(__clang__) && ((defined(__apple_build_version__) && __apple_build_version__ < 15000000) || (!defined(__apple_build_version__) && __clang_major__ < 16))
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL constexpr
+#else
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL consteval
+#endif
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS

 namespace simdjson {
@@ -117878,7 +118881,7 @@ constexpr std::size_t char_at(std::string_view key, std::size_t pos) noexcept {
 // lengths differ modulo the table size are separated by the length term in the
 // hash, so they need no position coverage.
 template <std::size_t N>
-consteval std::size_t count_undistinguished_pairs(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t count_undistinguished_pairs(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -117901,7 +118904,7 @@ consteval std::size_t count_undistinguished_pairs(
 }

 template <std::size_t N>
-consteval bool positions_distinguish(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool positions_distinguish(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -117911,7 +118914,7 @@ consteval bool positions_distinguish(

 // Number of distinct (length % modulus, char_at(key, pos)) pairs at a position.
 template <std::size_t N>
-consteval std::size_t discriminating_power(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t discriminating_power(
     const std::array<std::string_view, N>& keys,
     std::size_t pos,
     std::size_t modulus) {
@@ -117935,7 +118938,7 @@ consteval std::size_t discriminating_power(
 }

 template <std::size_t N>
-consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
     std::size_t m = 0;
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].size() > m) { m = keys[i].size(); }
@@ -117945,7 +118948,7 @@ consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys

 // Bounded backtracking DFS for a minimal set of distinguishing positions.
 template <std::size_t N>
-consteval bool backtracking_search(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool backtracking_search(
     const std::array<std::string_view, N>& keys,
     const std::size_t* candidates,
     std::size_t num_candidates,
@@ -117996,7 +118999,7 @@ consteval bool backtracking_search(

 // Phase 1: select character positions that distinguish all colliding pairs.
 template <std::size_t N>
-consteval std::size_t select_positions(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t select_positions(
     const std::array<std::string_view, N>& keys,
     std::array<std::size_t, MAX_POSITIONS>& positions,
     std::size_t modulus) {
@@ -118075,7 +119078,7 @@ struct phf_result {
 // (position, character) symbol at a time; never revisits a value. Equivalence
 // classes (keys sharing the same undetermined symbols) keep the search cheap.
 template <std::size_t N, std::size_t M>
-consteval bool try_generate_gperf(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_generate_gperf(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -118223,7 +119226,7 @@ consteval bool try_generate_gperf(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -118242,7 +119245,7 @@ consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_
 }

 template <std::size_t N, std::size_t M, std::size_t MaxM>
-consteval bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     if (try_compute_phf<N, M>(keys, result)) { return true; }
     constexpr std::size_t NextM = M * 2;
     if constexpr (NextM <= MaxM) { return try_gperf_po2<N, NextM, MaxM>(keys, result); }
@@ -118277,7 +119280,7 @@ constexpr std::size_t hd_key_hash_4(std::string_view key) noexcept {
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_hash_and_displace(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_hash_and_displace(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -118377,7 +119380,7 @@ consteval bool try_hash_and_displace(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -118396,7 +119399,7 @@ consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, p
 }

 template <std::size_t N, std::size_t M>
-consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     phf_result<N> result{};
     if (try_compute_phf_hd<N, M>(keys, result)) { return result; }
@@ -118412,7 +119415,7 @@ consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>
 // Compute a perfect hash for `keys`: try gperf at power-of-two sizes (capped so
 // the runtime tables stay within uint8 indices), then fall back to H&D.
 template <std::size_t N>
-consteval phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
     constexpr std::size_t StartM = next_power_of_2(N);
     constexpr std::size_t GPERF_MAX_TABLE =
         phf_result<N>::MAX_TABLE_SIZE < 256 ? phf_result<N>::MAX_TABLE_SIZE : 256;
@@ -118449,7 +119452,7 @@ constexpr std::size_t compute_max_key_len(const std::array<std::string_view, N>&

 // Validate keys and build the runtime tables from the computed perfect hash.
 template <std::size_t N, std::size_t TableSize, std::size_t MaxKeyLen>
-consteval phf_data<N, TableSize, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_data<N, TableSize, MaxKeyLen>
 build_phf_data(const std::array<std::string_view, N>& keys, const phf_result<N>& result) {
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].empty())            { compile_time_error("empty keys are not allowed in key_selector"); }
@@ -118758,7 +119761,7 @@ constexpr unsigned window_value(const std::array<std::string_view, N>& keys,
 }

 template <std::size_t N, std::size_t MaxKeyLen>
-consteval window_data<N, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL window_data<N, MaxKeyLen>
 compute_window(const std::array<std::string_view, N>& keys) {
     window_data<N, MaxKeyLen> out{};

@@ -118843,7 +119846,7 @@ match_window_candidate(const char* p, std::uint8_t ki,
 // --- describe() string helpers (constexpr; no std::to_string, which is not) ---

 // Append the decimal form of v to s.
-SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
+inline SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
     if (v == 0) { s.push_back('0'); return; }
     char buf[20];
     std::size_t n = 0;
@@ -118853,7 +119856,7 @@ SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {

 // Append a byte as its decimal value, plus the printable character in quotes
 // when it is in the printable ASCII range (e.g. "110 ('n')").
-SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
+inline SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
     append_uint(s, b);
     if (b >= 0x20 && b < 0x7f) {
         s += " ('";
@@ -121694,30 +122697,36 @@ inline error_code array::for_each_at_path_with_wildcard(std::string_view json_pa
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback);
-        if(err) { return err; }
+        // An element that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     // Specific index case in which we access the element at the given index
-    size_t idx = 0;
-
     for (char c : key) {
       if(c < '0' || c > '9'){
         return INVALID_JSON_POINTER;
       }
-      idx = idx*10 + (c - '0');
     }
-
-    auto element = at(idx);
+    // Rejects leading zeros and indexes that overflow size_t, as DOM does.
+    size_t idx;
+    size_t idx_length;
+    error_code error = internal::parse_json_pointer_array_index(key, idx, idx_length);
     value val;
-    SIMDJSON_TRY(element.get(val));
+    if (!error) { error = at(idx).get(val); }
+    if (error) {
+      if (error == INDEX_OUT_OF_BOUNDS && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }
     if (remaining_path.empty()){
       callback(val);
       return SUCCESS;
     } else {
-      return element.for_each_at_path_with_wildcard(remaining_path, callback);
+      return val.for_each_at_path_with_wildcard(remaining_path, callback);
     }
   }
 }
@@ -126028,13 +127037,21 @@ inline error_code object::for_each_at_path_with_wildcard(std::string_view json_p
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback));
+        // A field that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     value val;
-    SIMDJSON_TRY(find_field(key).get(val));
+    error_code error = find_field(key).get(val);
+    if (error) {
+      if (error == NO_SUCH_FIELD && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }

     if (remaining_path.empty()) {
       callback(val);
@@ -136020,6 +137037,20 @@ public:
   #define SIMDJSON_KEY_SELECTOR_HAS_LSX 0
 #endif

+// Clang 15 and earlier reject a call to a consteval function from within a
+// consteval function template when an argument refers to one of the caller's
+// reference parameters ("function parameter 'keys' with unknown value cannot
+// be used in a constant expression"). With those compilers, the helpers below
+// are merely constexpr: the perfect-hash tables are still computed at compile
+// time because they initialize static constexpr data members.
+#ifndef SIMDJSON_KEY_SELECTOR_CONSTEVAL
+#if defined(__clang__) && ((defined(__apple_build_version__) && __apple_build_version__ < 15000000) || (!defined(__apple_build_version__) && __clang_major__ < 16))
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL constexpr
+#else
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL consteval
+#endif
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS

 namespace simdjson {
@@ -136074,7 +137105,7 @@ constexpr std::size_t char_at(std::string_view key, std::size_t pos) noexcept {
 // lengths differ modulo the table size are separated by the length term in the
 // hash, so they need no position coverage.
 template <std::size_t N>
-consteval std::size_t count_undistinguished_pairs(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t count_undistinguished_pairs(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -136097,7 +137128,7 @@ consteval std::size_t count_undistinguished_pairs(
 }

 template <std::size_t N>
-consteval bool positions_distinguish(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool positions_distinguish(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -136107,7 +137138,7 @@ consteval bool positions_distinguish(

 // Number of distinct (length % modulus, char_at(key, pos)) pairs at a position.
 template <std::size_t N>
-consteval std::size_t discriminating_power(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t discriminating_power(
     const std::array<std::string_view, N>& keys,
     std::size_t pos,
     std::size_t modulus) {
@@ -136131,7 +137162,7 @@ consteval std::size_t discriminating_power(
 }

 template <std::size_t N>
-consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
     std::size_t m = 0;
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].size() > m) { m = keys[i].size(); }
@@ -136141,7 +137172,7 @@ consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys

 // Bounded backtracking DFS for a minimal set of distinguishing positions.
 template <std::size_t N>
-consteval bool backtracking_search(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool backtracking_search(
     const std::array<std::string_view, N>& keys,
     const std::size_t* candidates,
     std::size_t num_candidates,
@@ -136192,7 +137223,7 @@ consteval bool backtracking_search(

 // Phase 1: select character positions that distinguish all colliding pairs.
 template <std::size_t N>
-consteval std::size_t select_positions(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t select_positions(
     const std::array<std::string_view, N>& keys,
     std::array<std::size_t, MAX_POSITIONS>& positions,
     std::size_t modulus) {
@@ -136271,7 +137302,7 @@ struct phf_result {
 // (position, character) symbol at a time; never revisits a value. Equivalence
 // classes (keys sharing the same undetermined symbols) keep the search cheap.
 template <std::size_t N, std::size_t M>
-consteval bool try_generate_gperf(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_generate_gperf(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -136419,7 +137450,7 @@ consteval bool try_generate_gperf(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -136438,7 +137469,7 @@ consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_
 }

 template <std::size_t N, std::size_t M, std::size_t MaxM>
-consteval bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     if (try_compute_phf<N, M>(keys, result)) { return true; }
     constexpr std::size_t NextM = M * 2;
     if constexpr (NextM <= MaxM) { return try_gperf_po2<N, NextM, MaxM>(keys, result); }
@@ -136473,7 +137504,7 @@ constexpr std::size_t hd_key_hash_4(std::string_view key) noexcept {
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_hash_and_displace(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_hash_and_displace(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -136573,7 +137604,7 @@ consteval bool try_hash_and_displace(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -136592,7 +137623,7 @@ consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, p
 }

 template <std::size_t N, std::size_t M>
-consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     phf_result<N> result{};
     if (try_compute_phf_hd<N, M>(keys, result)) { return result; }
@@ -136608,7 +137639,7 @@ consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>
 // Compute a perfect hash for `keys`: try gperf at power-of-two sizes (capped so
 // the runtime tables stay within uint8 indices), then fall back to H&D.
 template <std::size_t N>
-consteval phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
     constexpr std::size_t StartM = next_power_of_2(N);
     constexpr std::size_t GPERF_MAX_TABLE =
         phf_result<N>::MAX_TABLE_SIZE < 256 ? phf_result<N>::MAX_TABLE_SIZE : 256;
@@ -136645,7 +137676,7 @@ constexpr std::size_t compute_max_key_len(const std::array<std::string_view, N>&

 // Validate keys and build the runtime tables from the computed perfect hash.
 template <std::size_t N, std::size_t TableSize, std::size_t MaxKeyLen>
-consteval phf_data<N, TableSize, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_data<N, TableSize, MaxKeyLen>
 build_phf_data(const std::array<std::string_view, N>& keys, const phf_result<N>& result) {
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].empty())            { compile_time_error("empty keys are not allowed in key_selector"); }
@@ -136954,7 +137985,7 @@ constexpr unsigned window_value(const std::array<std::string_view, N>& keys,
 }

 template <std::size_t N, std::size_t MaxKeyLen>
-consteval window_data<N, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL window_data<N, MaxKeyLen>
 compute_window(const std::array<std::string_view, N>& keys) {
     window_data<N, MaxKeyLen> out{};

@@ -137039,7 +138070,7 @@ match_window_candidate(const char* p, std::uint8_t ki,
 // --- describe() string helpers (constexpr; no std::to_string, which is not) ---

 // Append the decimal form of v to s.
-SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
+inline SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
     if (v == 0) { s.push_back('0'); return; }
     char buf[20];
     std::size_t n = 0;
@@ -137049,7 +138080,7 @@ SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {

 // Append a byte as its decimal value, plus the printable character in quotes
 // when it is in the printable ASCII range (e.g. "110 ('n')").
-SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
+inline SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
     append_uint(s, b);
     if (b >= 0x20 && b < 0x7f) {
         s += " ('";
@@ -139890,30 +140921,36 @@ inline error_code array::for_each_at_path_with_wildcard(std::string_view json_pa
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback);
-        if(err) { return err; }
+        // An element that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     // Specific index case in which we access the element at the given index
-    size_t idx = 0;
-
     for (char c : key) {
       if(c < '0' || c > '9'){
         return INVALID_JSON_POINTER;
       }
-      idx = idx*10 + (c - '0');
     }
-
-    auto element = at(idx);
+    // Rejects leading zeros and indexes that overflow size_t, as DOM does.
+    size_t idx;
+    size_t idx_length;
+    error_code error = internal::parse_json_pointer_array_index(key, idx, idx_length);
     value val;
-    SIMDJSON_TRY(element.get(val));
+    if (!error) { error = at(idx).get(val); }
+    if (error) {
+      if (error == INDEX_OUT_OF_BOUNDS && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }
     if (remaining_path.empty()){
       callback(val);
       return SUCCESS;
     } else {
-      return element.for_each_at_path_with_wildcard(remaining_path, callback);
+      return val.for_each_at_path_with_wildcard(remaining_path, callback);
     }
   }
 }
@@ -144224,13 +145261,21 @@ inline error_code object::for_each_at_path_with_wildcard(std::string_view json_p
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback));
+        // A field that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     value val;
-    SIMDJSON_TRY(find_field(key).get(val));
+    error_code error = find_field(key).get(val);
+    if (error) {
+      if (error == NO_SUCH_FIELD && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }

     if (remaining_path.empty()) {
       callback(val);
@@ -154331,6 +155376,20 @@ public:
   #define SIMDJSON_KEY_SELECTOR_HAS_LSX 0
 #endif

+// Clang 15 and earlier reject a call to a consteval function from within a
+// consteval function template when an argument refers to one of the caller's
+// reference parameters ("function parameter 'keys' with unknown value cannot
+// be used in a constant expression"). With those compilers, the helpers below
+// are merely constexpr: the perfect-hash tables are still computed at compile
+// time because they initialize static constexpr data members.
+#ifndef SIMDJSON_KEY_SELECTOR_CONSTEVAL
+#if defined(__clang__) && ((defined(__apple_build_version__) && __apple_build_version__ < 15000000) || (!defined(__apple_build_version__) && __clang_major__ < 16))
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL constexpr
+#else
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL consteval
+#endif
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS

 namespace simdjson {
@@ -154385,7 +155444,7 @@ constexpr std::size_t char_at(std::string_view key, std::size_t pos) noexcept {
 // lengths differ modulo the table size are separated by the length term in the
 // hash, so they need no position coverage.
 template <std::size_t N>
-consteval std::size_t count_undistinguished_pairs(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t count_undistinguished_pairs(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -154408,7 +155467,7 @@ consteval std::size_t count_undistinguished_pairs(
 }

 template <std::size_t N>
-consteval bool positions_distinguish(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool positions_distinguish(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -154418,7 +155477,7 @@ consteval bool positions_distinguish(

 // Number of distinct (length % modulus, char_at(key, pos)) pairs at a position.
 template <std::size_t N>
-consteval std::size_t discriminating_power(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t discriminating_power(
     const std::array<std::string_view, N>& keys,
     std::size_t pos,
     std::size_t modulus) {
@@ -154442,7 +155501,7 @@ consteval std::size_t discriminating_power(
 }

 template <std::size_t N>
-consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
     std::size_t m = 0;
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].size() > m) { m = keys[i].size(); }
@@ -154452,7 +155511,7 @@ consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys

 // Bounded backtracking DFS for a minimal set of distinguishing positions.
 template <std::size_t N>
-consteval bool backtracking_search(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool backtracking_search(
     const std::array<std::string_view, N>& keys,
     const std::size_t* candidates,
     std::size_t num_candidates,
@@ -154503,7 +155562,7 @@ consteval bool backtracking_search(

 // Phase 1: select character positions that distinguish all colliding pairs.
 template <std::size_t N>
-consteval std::size_t select_positions(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t select_positions(
     const std::array<std::string_view, N>& keys,
     std::array<std::size_t, MAX_POSITIONS>& positions,
     std::size_t modulus) {
@@ -154582,7 +155641,7 @@ struct phf_result {
 // (position, character) symbol at a time; never revisits a value. Equivalence
 // classes (keys sharing the same undetermined symbols) keep the search cheap.
 template <std::size_t N, std::size_t M>
-consteval bool try_generate_gperf(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_generate_gperf(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -154730,7 +155789,7 @@ consteval bool try_generate_gperf(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -154749,7 +155808,7 @@ consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_
 }

 template <std::size_t N, std::size_t M, std::size_t MaxM>
-consteval bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     if (try_compute_phf<N, M>(keys, result)) { return true; }
     constexpr std::size_t NextM = M * 2;
     if constexpr (NextM <= MaxM) { return try_gperf_po2<N, NextM, MaxM>(keys, result); }
@@ -154784,7 +155843,7 @@ constexpr std::size_t hd_key_hash_4(std::string_view key) noexcept {
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_hash_and_displace(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_hash_and_displace(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -154884,7 +155943,7 @@ consteval bool try_hash_and_displace(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -154903,7 +155962,7 @@ consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, p
 }

 template <std::size_t N, std::size_t M>
-consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     phf_result<N> result{};
     if (try_compute_phf_hd<N, M>(keys, result)) { return result; }
@@ -154919,7 +155978,7 @@ consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>
 // Compute a perfect hash for `keys`: try gperf at power-of-two sizes (capped so
 // the runtime tables stay within uint8 indices), then fall back to H&D.
 template <std::size_t N>
-consteval phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
     constexpr std::size_t StartM = next_power_of_2(N);
     constexpr std::size_t GPERF_MAX_TABLE =
         phf_result<N>::MAX_TABLE_SIZE < 256 ? phf_result<N>::MAX_TABLE_SIZE : 256;
@@ -154956,7 +156015,7 @@ constexpr std::size_t compute_max_key_len(const std::array<std::string_view, N>&

 // Validate keys and build the runtime tables from the computed perfect hash.
 template <std::size_t N, std::size_t TableSize, std::size_t MaxKeyLen>
-consteval phf_data<N, TableSize, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_data<N, TableSize, MaxKeyLen>
 build_phf_data(const std::array<std::string_view, N>& keys, const phf_result<N>& result) {
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].empty())            { compile_time_error("empty keys are not allowed in key_selector"); }
@@ -155265,7 +156324,7 @@ constexpr unsigned window_value(const std::array<std::string_view, N>& keys,
 }

 template <std::size_t N, std::size_t MaxKeyLen>
-consteval window_data<N, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL window_data<N, MaxKeyLen>
 compute_window(const std::array<std::string_view, N>& keys) {
     window_data<N, MaxKeyLen> out{};

@@ -155350,7 +156409,7 @@ match_window_candidate(const char* p, std::uint8_t ki,
 // --- describe() string helpers (constexpr; no std::to_string, which is not) ---

 // Append the decimal form of v to s.
-SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
+inline SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
     if (v == 0) { s.push_back('0'); return; }
     char buf[20];
     std::size_t n = 0;
@@ -155360,7 +156419,7 @@ SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {

 // Append a byte as its decimal value, plus the printable character in quotes
 // when it is in the printable ASCII range (e.g. "110 ('n')").
-SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
+inline SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
     append_uint(s, b);
     if (b >= 0x20 && b < 0x7f) {
         s += " ('";
@@ -158201,30 +159260,36 @@ inline error_code array::for_each_at_path_with_wildcard(std::string_view json_pa
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback);
-        if(err) { return err; }
+        // An element that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     // Specific index case in which we access the element at the given index
-    size_t idx = 0;
-
     for (char c : key) {
       if(c < '0' || c > '9'){
         return INVALID_JSON_POINTER;
       }
-      idx = idx*10 + (c - '0');
     }
-
-    auto element = at(idx);
+    // Rejects leading zeros and indexes that overflow size_t, as DOM does.
+    size_t idx;
+    size_t idx_length;
+    error_code error = internal::parse_json_pointer_array_index(key, idx, idx_length);
     value val;
-    SIMDJSON_TRY(element.get(val));
+    if (!error) { error = at(idx).get(val); }
+    if (error) {
+      if (error == INDEX_OUT_OF_BOUNDS && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }
     if (remaining_path.empty()){
       callback(val);
       return SUCCESS;
     } else {
-      return element.for_each_at_path_with_wildcard(remaining_path, callback);
+      return val.for_each_at_path_with_wildcard(remaining_path, callback);
     }
   }
 }
@@ -162535,13 +163600,21 @@ inline error_code object::for_each_at_path_with_wildcard(std::string_view json_p
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback));
+        // A field that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     value val;
-    SIMDJSON_TRY(find_field(key).get(val));
+    error_code error = find_field(key).get(val);
+    if (error) {
+      if (error == NO_SUCH_FIELD && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }

     if (remaining_path.empty()) {
       callback(val);
@@ -172949,6 +174022,20 @@ public:
   #define SIMDJSON_KEY_SELECTOR_HAS_LSX 0
 #endif

+// Clang 15 and earlier reject a call to a consteval function from within a
+// consteval function template when an argument refers to one of the caller's
+// reference parameters ("function parameter 'keys' with unknown value cannot
+// be used in a constant expression"). With those compilers, the helpers below
+// are merely constexpr: the perfect-hash tables are still computed at compile
+// time because they initialize static constexpr data members.
+#ifndef SIMDJSON_KEY_SELECTOR_CONSTEVAL
+#if defined(__clang__) && ((defined(__apple_build_version__) && __apple_build_version__ < 15000000) || (!defined(__apple_build_version__) && __clang_major__ < 16))
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL constexpr
+#else
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL consteval
+#endif
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS

 namespace simdjson {
@@ -173003,7 +174090,7 @@ constexpr std::size_t char_at(std::string_view key, std::size_t pos) noexcept {
 // lengths differ modulo the table size are separated by the length term in the
 // hash, so they need no position coverage.
 template <std::size_t N>
-consteval std::size_t count_undistinguished_pairs(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t count_undistinguished_pairs(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -173026,7 +174113,7 @@ consteval std::size_t count_undistinguished_pairs(
 }

 template <std::size_t N>
-consteval bool positions_distinguish(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool positions_distinguish(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -173036,7 +174123,7 @@ consteval bool positions_distinguish(

 // Number of distinct (length % modulus, char_at(key, pos)) pairs at a position.
 template <std::size_t N>
-consteval std::size_t discriminating_power(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t discriminating_power(
     const std::array<std::string_view, N>& keys,
     std::size_t pos,
     std::size_t modulus) {
@@ -173060,7 +174147,7 @@ consteval std::size_t discriminating_power(
 }

 template <std::size_t N>
-consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
     std::size_t m = 0;
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].size() > m) { m = keys[i].size(); }
@@ -173070,7 +174157,7 @@ consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys

 // Bounded backtracking DFS for a minimal set of distinguishing positions.
 template <std::size_t N>
-consteval bool backtracking_search(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool backtracking_search(
     const std::array<std::string_view, N>& keys,
     const std::size_t* candidates,
     std::size_t num_candidates,
@@ -173121,7 +174208,7 @@ consteval bool backtracking_search(

 // Phase 1: select character positions that distinguish all colliding pairs.
 template <std::size_t N>
-consteval std::size_t select_positions(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t select_positions(
     const std::array<std::string_view, N>& keys,
     std::array<std::size_t, MAX_POSITIONS>& positions,
     std::size_t modulus) {
@@ -173200,7 +174287,7 @@ struct phf_result {
 // (position, character) symbol at a time; never revisits a value. Equivalence
 // classes (keys sharing the same undetermined symbols) keep the search cheap.
 template <std::size_t N, std::size_t M>
-consteval bool try_generate_gperf(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_generate_gperf(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -173348,7 +174435,7 @@ consteval bool try_generate_gperf(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -173367,7 +174454,7 @@ consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_
 }

 template <std::size_t N, std::size_t M, std::size_t MaxM>
-consteval bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     if (try_compute_phf<N, M>(keys, result)) { return true; }
     constexpr std::size_t NextM = M * 2;
     if constexpr (NextM <= MaxM) { return try_gperf_po2<N, NextM, MaxM>(keys, result); }
@@ -173402,7 +174489,7 @@ constexpr std::size_t hd_key_hash_4(std::string_view key) noexcept {
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_hash_and_displace(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_hash_and_displace(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -173502,7 +174589,7 @@ consteval bool try_hash_and_displace(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -173521,7 +174608,7 @@ consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, p
 }

 template <std::size_t N, std::size_t M>
-consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     phf_result<N> result{};
     if (try_compute_phf_hd<N, M>(keys, result)) { return result; }
@@ -173537,7 +174624,7 @@ consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>
 // Compute a perfect hash for `keys`: try gperf at power-of-two sizes (capped so
 // the runtime tables stay within uint8 indices), then fall back to H&D.
 template <std::size_t N>
-consteval phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
     constexpr std::size_t StartM = next_power_of_2(N);
     constexpr std::size_t GPERF_MAX_TABLE =
         phf_result<N>::MAX_TABLE_SIZE < 256 ? phf_result<N>::MAX_TABLE_SIZE : 256;
@@ -173574,7 +174661,7 @@ constexpr std::size_t compute_max_key_len(const std::array<std::string_view, N>&

 // Validate keys and build the runtime tables from the computed perfect hash.
 template <std::size_t N, std::size_t TableSize, std::size_t MaxKeyLen>
-consteval phf_data<N, TableSize, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_data<N, TableSize, MaxKeyLen>
 build_phf_data(const std::array<std::string_view, N>& keys, const phf_result<N>& result) {
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].empty())            { compile_time_error("empty keys are not allowed in key_selector"); }
@@ -173883,7 +174970,7 @@ constexpr unsigned window_value(const std::array<std::string_view, N>& keys,
 }

 template <std::size_t N, std::size_t MaxKeyLen>
-consteval window_data<N, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL window_data<N, MaxKeyLen>
 compute_window(const std::array<std::string_view, N>& keys) {
     window_data<N, MaxKeyLen> out{};

@@ -173968,7 +175055,7 @@ match_window_candidate(const char* p, std::uint8_t ki,
 // --- describe() string helpers (constexpr; no std::to_string, which is not) ---

 // Append the decimal form of v to s.
-SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
+inline SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
     if (v == 0) { s.push_back('0'); return; }
     char buf[20];
     std::size_t n = 0;
@@ -173978,7 +175065,7 @@ SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {

 // Append a byte as its decimal value, plus the printable character in quotes
 // when it is in the printable ASCII range (e.g. "110 ('n')").
-SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
+inline SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
     append_uint(s, b);
     if (b >= 0x20 && b < 0x7f) {
         s += " ('";
@@ -176819,30 +177906,36 @@ inline error_code array::for_each_at_path_with_wildcard(std::string_view json_pa
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback);
-        if(err) { return err; }
+        // An element that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     // Specific index case in which we access the element at the given index
-    size_t idx = 0;
-
     for (char c : key) {
       if(c < '0' || c > '9'){
         return INVALID_JSON_POINTER;
       }
-      idx = idx*10 + (c - '0');
     }
-
-    auto element = at(idx);
+    // Rejects leading zeros and indexes that overflow size_t, as DOM does.
+    size_t idx;
+    size_t idx_length;
+    error_code error = internal::parse_json_pointer_array_index(key, idx, idx_length);
     value val;
-    SIMDJSON_TRY(element.get(val));
+    if (!error) { error = at(idx).get(val); }
+    if (error) {
+      if (error == INDEX_OUT_OF_BOUNDS && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }
     if (remaining_path.empty()){
       callback(val);
       return SUCCESS;
     } else {
-      return element.for_each_at_path_with_wildcard(remaining_path, callback);
+      return val.for_each_at_path_with_wildcard(remaining_path, callback);
     }
   }
 }
@@ -181153,13 +182246,21 @@ inline error_code object::for_each_at_path_with_wildcard(std::string_view json_p
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback));
+        // A field that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     value val;
-    SIMDJSON_TRY(find_field(key).get(val));
+    error_code error = find_field(key).get(val);
+    if (error) {
+      if (error == NO_SUCH_FIELD && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }

     if (remaining_path.empty()) {
       callback(val);
@@ -191057,6 +192158,20 @@ public:
   #define SIMDJSON_KEY_SELECTOR_HAS_LSX 0
 #endif

+// Clang 15 and earlier reject a call to a consteval function from within a
+// consteval function template when an argument refers to one of the caller's
+// reference parameters ("function parameter 'keys' with unknown value cannot
+// be used in a constant expression"). With those compilers, the helpers below
+// are merely constexpr: the perfect-hash tables are still computed at compile
+// time because they initialize static constexpr data members.
+#ifndef SIMDJSON_KEY_SELECTOR_CONSTEVAL
+#if defined(__clang__) && ((defined(__apple_build_version__) && __apple_build_version__ < 15000000) || (!defined(__apple_build_version__) && __clang_major__ < 16))
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL constexpr
+#else
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL consteval
+#endif
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS

 namespace simdjson {
@@ -191111,7 +192226,7 @@ constexpr std::size_t char_at(std::string_view key, std::size_t pos) noexcept {
 // lengths differ modulo the table size are separated by the length term in the
 // hash, so they need no position coverage.
 template <std::size_t N>
-consteval std::size_t count_undistinguished_pairs(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t count_undistinguished_pairs(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -191134,7 +192249,7 @@ consteval std::size_t count_undistinguished_pairs(
 }

 template <std::size_t N>
-consteval bool positions_distinguish(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool positions_distinguish(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -191144,7 +192259,7 @@ consteval bool positions_distinguish(

 // Number of distinct (length % modulus, char_at(key, pos)) pairs at a position.
 template <std::size_t N>
-consteval std::size_t discriminating_power(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t discriminating_power(
     const std::array<std::string_view, N>& keys,
     std::size_t pos,
     std::size_t modulus) {
@@ -191168,7 +192283,7 @@ consteval std::size_t discriminating_power(
 }

 template <std::size_t N>
-consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
     std::size_t m = 0;
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].size() > m) { m = keys[i].size(); }
@@ -191178,7 +192293,7 @@ consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys

 // Bounded backtracking DFS for a minimal set of distinguishing positions.
 template <std::size_t N>
-consteval bool backtracking_search(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool backtracking_search(
     const std::array<std::string_view, N>& keys,
     const std::size_t* candidates,
     std::size_t num_candidates,
@@ -191229,7 +192344,7 @@ consteval bool backtracking_search(

 // Phase 1: select character positions that distinguish all colliding pairs.
 template <std::size_t N>
-consteval std::size_t select_positions(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t select_positions(
     const std::array<std::string_view, N>& keys,
     std::array<std::size_t, MAX_POSITIONS>& positions,
     std::size_t modulus) {
@@ -191308,7 +192423,7 @@ struct phf_result {
 // (position, character) symbol at a time; never revisits a value. Equivalence
 // classes (keys sharing the same undetermined symbols) keep the search cheap.
 template <std::size_t N, std::size_t M>
-consteval bool try_generate_gperf(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_generate_gperf(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -191456,7 +192571,7 @@ consteval bool try_generate_gperf(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -191475,7 +192590,7 @@ consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_
 }

 template <std::size_t N, std::size_t M, std::size_t MaxM>
-consteval bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     if (try_compute_phf<N, M>(keys, result)) { return true; }
     constexpr std::size_t NextM = M * 2;
     if constexpr (NextM <= MaxM) { return try_gperf_po2<N, NextM, MaxM>(keys, result); }
@@ -191510,7 +192625,7 @@ constexpr std::size_t hd_key_hash_4(std::string_view key) noexcept {
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_hash_and_displace(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_hash_and_displace(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -191610,7 +192725,7 @@ consteval bool try_hash_and_displace(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -191629,7 +192744,7 @@ consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, p
 }

 template <std::size_t N, std::size_t M>
-consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     phf_result<N> result{};
     if (try_compute_phf_hd<N, M>(keys, result)) { return result; }
@@ -191645,7 +192760,7 @@ consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>
 // Compute a perfect hash for `keys`: try gperf at power-of-two sizes (capped so
 // the runtime tables stay within uint8 indices), then fall back to H&D.
 template <std::size_t N>
-consteval phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
     constexpr std::size_t StartM = next_power_of_2(N);
     constexpr std::size_t GPERF_MAX_TABLE =
         phf_result<N>::MAX_TABLE_SIZE < 256 ? phf_result<N>::MAX_TABLE_SIZE : 256;
@@ -191682,7 +192797,7 @@ constexpr std::size_t compute_max_key_len(const std::array<std::string_view, N>&

 // Validate keys and build the runtime tables from the computed perfect hash.
 template <std::size_t N, std::size_t TableSize, std::size_t MaxKeyLen>
-consteval phf_data<N, TableSize, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_data<N, TableSize, MaxKeyLen>
 build_phf_data(const std::array<std::string_view, N>& keys, const phf_result<N>& result) {
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].empty())            { compile_time_error("empty keys are not allowed in key_selector"); }
@@ -191991,7 +193106,7 @@ constexpr unsigned window_value(const std::array<std::string_view, N>& keys,
 }

 template <std::size_t N, std::size_t MaxKeyLen>
-consteval window_data<N, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL window_data<N, MaxKeyLen>
 compute_window(const std::array<std::string_view, N>& keys) {
     window_data<N, MaxKeyLen> out{};

@@ -192076,7 +193191,7 @@ match_window_candidate(const char* p, std::uint8_t ki,
 // --- describe() string helpers (constexpr; no std::to_string, which is not) ---

 // Append the decimal form of v to s.
-SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
+inline SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
     if (v == 0) { s.push_back('0'); return; }
     char buf[20];
     std::size_t n = 0;
@@ -192086,7 +193201,7 @@ SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {

 // Append a byte as its decimal value, plus the printable character in quotes
 // when it is in the printable ASCII range (e.g. "110 ('n')").
-SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
+inline SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
     append_uint(s, b);
     if (b >= 0x20 && b < 0x7f) {
         s += " ('";
@@ -194927,30 +196042,36 @@ inline error_code array::for_each_at_path_with_wildcard(std::string_view json_pa
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback);
-        if(err) { return err; }
+        // An element that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     // Specific index case in which we access the element at the given index
-    size_t idx = 0;
-
     for (char c : key) {
       if(c < '0' || c > '9'){
         return INVALID_JSON_POINTER;
       }
-      idx = idx*10 + (c - '0');
     }
-
-    auto element = at(idx);
+    // Rejects leading zeros and indexes that overflow size_t, as DOM does.
+    size_t idx;
+    size_t idx_length;
+    error_code error = internal::parse_json_pointer_array_index(key, idx, idx_length);
     value val;
-    SIMDJSON_TRY(element.get(val));
+    if (!error) { error = at(idx).get(val); }
+    if (error) {
+      if (error == INDEX_OUT_OF_BOUNDS && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }
     if (remaining_path.empty()){
       callback(val);
       return SUCCESS;
     } else {
-      return element.for_each_at_path_with_wildcard(remaining_path, callback);
+      return val.for_each_at_path_with_wildcard(remaining_path, callback);
     }
   }
 }
@@ -199261,13 +200382,21 @@ inline error_code object::for_each_at_path_with_wildcard(std::string_view json_p
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback));
+        // A field that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     value val;
-    SIMDJSON_TRY(find_field(key).get(val));
+    error_code error = find_field(key).get(val);
+    if (error) {
+      if (error == NO_SUCH_FIELD && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }

     if (remaining_path.empty()) {
       callback(val);
@@ -209188,6 +210317,20 @@ public:
   #define SIMDJSON_KEY_SELECTOR_HAS_LSX 0
 #endif

+// Clang 15 and earlier reject a call to a consteval function from within a
+// consteval function template when an argument refers to one of the caller's
+// reference parameters ("function parameter 'keys' with unknown value cannot
+// be used in a constant expression"). With those compilers, the helpers below
+// are merely constexpr: the perfect-hash tables are still computed at compile
+// time because they initialize static constexpr data members.
+#ifndef SIMDJSON_KEY_SELECTOR_CONSTEVAL
+#if defined(__clang__) && ((defined(__apple_build_version__) && __apple_build_version__ < 15000000) || (!defined(__apple_build_version__) && __clang_major__ < 16))
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL constexpr
+#else
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL consteval
+#endif
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS

 namespace simdjson {
@@ -209242,7 +210385,7 @@ constexpr std::size_t char_at(std::string_view key, std::size_t pos) noexcept {
 // lengths differ modulo the table size are separated by the length term in the
 // hash, so they need no position coverage.
 template <std::size_t N>
-consteval std::size_t count_undistinguished_pairs(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t count_undistinguished_pairs(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -209265,7 +210408,7 @@ consteval std::size_t count_undistinguished_pairs(
 }

 template <std::size_t N>
-consteval bool positions_distinguish(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool positions_distinguish(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -209275,7 +210418,7 @@ consteval bool positions_distinguish(

 // Number of distinct (length % modulus, char_at(key, pos)) pairs at a position.
 template <std::size_t N>
-consteval std::size_t discriminating_power(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t discriminating_power(
     const std::array<std::string_view, N>& keys,
     std::size_t pos,
     std::size_t modulus) {
@@ -209299,7 +210442,7 @@ consteval std::size_t discriminating_power(
 }

 template <std::size_t N>
-consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
     std::size_t m = 0;
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].size() > m) { m = keys[i].size(); }
@@ -209309,7 +210452,7 @@ consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys

 // Bounded backtracking DFS for a minimal set of distinguishing positions.
 template <std::size_t N>
-consteval bool backtracking_search(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool backtracking_search(
     const std::array<std::string_view, N>& keys,
     const std::size_t* candidates,
     std::size_t num_candidates,
@@ -209360,7 +210503,7 @@ consteval bool backtracking_search(

 // Phase 1: select character positions that distinguish all colliding pairs.
 template <std::size_t N>
-consteval std::size_t select_positions(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t select_positions(
     const std::array<std::string_view, N>& keys,
     std::array<std::size_t, MAX_POSITIONS>& positions,
     std::size_t modulus) {
@@ -209439,7 +210582,7 @@ struct phf_result {
 // (position, character) symbol at a time; never revisits a value. Equivalence
 // classes (keys sharing the same undetermined symbols) keep the search cheap.
 template <std::size_t N, std::size_t M>
-consteval bool try_generate_gperf(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_generate_gperf(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -209587,7 +210730,7 @@ consteval bool try_generate_gperf(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -209606,7 +210749,7 @@ consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_
 }

 template <std::size_t N, std::size_t M, std::size_t MaxM>
-consteval bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     if (try_compute_phf<N, M>(keys, result)) { return true; }
     constexpr std::size_t NextM = M * 2;
     if constexpr (NextM <= MaxM) { return try_gperf_po2<N, NextM, MaxM>(keys, result); }
@@ -209641,7 +210784,7 @@ constexpr std::size_t hd_key_hash_4(std::string_view key) noexcept {
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_hash_and_displace(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_hash_and_displace(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -209741,7 +210884,7 @@ consteval bool try_hash_and_displace(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -209760,7 +210903,7 @@ consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, p
 }

 template <std::size_t N, std::size_t M>
-consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     phf_result<N> result{};
     if (try_compute_phf_hd<N, M>(keys, result)) { return result; }
@@ -209776,7 +210919,7 @@ consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>
 // Compute a perfect hash for `keys`: try gperf at power-of-two sizes (capped so
 // the runtime tables stay within uint8 indices), then fall back to H&D.
 template <std::size_t N>
-consteval phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
     constexpr std::size_t StartM = next_power_of_2(N);
     constexpr std::size_t GPERF_MAX_TABLE =
         phf_result<N>::MAX_TABLE_SIZE < 256 ? phf_result<N>::MAX_TABLE_SIZE : 256;
@@ -209813,7 +210956,7 @@ constexpr std::size_t compute_max_key_len(const std::array<std::string_view, N>&

 // Validate keys and build the runtime tables from the computed perfect hash.
 template <std::size_t N, std::size_t TableSize, std::size_t MaxKeyLen>
-consteval phf_data<N, TableSize, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_data<N, TableSize, MaxKeyLen>
 build_phf_data(const std::array<std::string_view, N>& keys, const phf_result<N>& result) {
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].empty())            { compile_time_error("empty keys are not allowed in key_selector"); }
@@ -210122,7 +211265,7 @@ constexpr unsigned window_value(const std::array<std::string_view, N>& keys,
 }

 template <std::size_t N, std::size_t MaxKeyLen>
-consteval window_data<N, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL window_data<N, MaxKeyLen>
 compute_window(const std::array<std::string_view, N>& keys) {
     window_data<N, MaxKeyLen> out{};

@@ -210207,7 +211350,7 @@ match_window_candidate(const char* p, std::uint8_t ki,
 // --- describe() string helpers (constexpr; no std::to_string, which is not) ---

 // Append the decimal form of v to s.
-SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
+inline SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
     if (v == 0) { s.push_back('0'); return; }
     char buf[20];
     std::size_t n = 0;
@@ -210217,7 +211360,7 @@ SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {

 // Append a byte as its decimal value, plus the printable character in quotes
 // when it is in the printable ASCII range (e.g. "110 ('n')").
-SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
+inline SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
     append_uint(s, b);
     if (b >= 0x20 && b < 0x7f) {
         s += " ('";
@@ -213058,30 +214201,36 @@ inline error_code array::for_each_at_path_with_wildcard(std::string_view json_pa
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback);
-        if(err) { return err; }
+        // An element that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     // Specific index case in which we access the element at the given index
-    size_t idx = 0;
-
     for (char c : key) {
       if(c < '0' || c > '9'){
         return INVALID_JSON_POINTER;
       }
-      idx = idx*10 + (c - '0');
     }
-
-    auto element = at(idx);
+    // Rejects leading zeros and indexes that overflow size_t, as DOM does.
+    size_t idx;
+    size_t idx_length;
+    error_code error = internal::parse_json_pointer_array_index(key, idx, idx_length);
     value val;
-    SIMDJSON_TRY(element.get(val));
+    if (!error) { error = at(idx).get(val); }
+    if (error) {
+      if (error == INDEX_OUT_OF_BOUNDS && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }
     if (remaining_path.empty()){
       callback(val);
       return SUCCESS;
     } else {
-      return element.for_each_at_path_with_wildcard(remaining_path, callback);
+      return val.for_each_at_path_with_wildcard(remaining_path, callback);
     }
   }
 }
@@ -217392,13 +218541,21 @@ inline error_code object::for_each_at_path_with_wildcard(std::string_view json_p
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback));
+        // A field that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     value val;
-    SIMDJSON_TRY(find_field(key).get(val));
+    error_code error = find_field(key).get(val);
+    if (error) {
+      if (error == NO_SUCH_FIELD && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }

     if (remaining_path.empty()) {
       callback(val);
@@ -227322,6 +228479,20 @@ public:
   #define SIMDJSON_KEY_SELECTOR_HAS_LSX 0
 #endif

+// Clang 15 and earlier reject a call to a consteval function from within a
+// consteval function template when an argument refers to one of the caller's
+// reference parameters ("function parameter 'keys' with unknown value cannot
+// be used in a constant expression"). With those compilers, the helpers below
+// are merely constexpr: the perfect-hash tables are still computed at compile
+// time because they initialize static constexpr data members.
+#ifndef SIMDJSON_KEY_SELECTOR_CONSTEVAL
+#if defined(__clang__) && ((defined(__apple_build_version__) && __apple_build_version__ < 15000000) || (!defined(__apple_build_version__) && __clang_major__ < 16))
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL constexpr
+#else
+  #define SIMDJSON_KEY_SELECTOR_CONSTEVAL consteval
+#endif
+#endif
+
 #if SIMDJSON_SUPPORTS_CONCEPTS

 namespace simdjson {
@@ -227376,7 +228547,7 @@ constexpr std::size_t char_at(std::string_view key, std::size_t pos) noexcept {
 // lengths differ modulo the table size are separated by the length term in the
 // hash, so they need no position coverage.
 template <std::size_t N>
-consteval std::size_t count_undistinguished_pairs(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t count_undistinguished_pairs(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -227399,7 +228570,7 @@ consteval std::size_t count_undistinguished_pairs(
 }

 template <std::size_t N>
-consteval bool positions_distinguish(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool positions_distinguish(
     const std::array<std::string_view, N>& keys,
     const std::size_t* positions,
     std::size_t num_positions,
@@ -227409,7 +228580,7 @@ consteval bool positions_distinguish(

 // Number of distinct (length % modulus, char_at(key, pos)) pairs at a position.
 template <std::size_t N>
-consteval std::size_t discriminating_power(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t discriminating_power(
     const std::array<std::string_view, N>& keys,
     std::size_t pos,
     std::size_t modulus) {
@@ -227433,7 +228604,7 @@ consteval std::size_t discriminating_power(
 }

 template <std::size_t N>
-consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t max_key_length(const std::array<std::string_view, N>& keys) {
     std::size_t m = 0;
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].size() > m) { m = keys[i].size(); }
@@ -227443,7 +228614,7 @@ consteval std::size_t max_key_length(const std::array<std::string_view, N>& keys

 // Bounded backtracking DFS for a minimal set of distinguishing positions.
 template <std::size_t N>
-consteval bool backtracking_search(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool backtracking_search(
     const std::array<std::string_view, N>& keys,
     const std::size_t* candidates,
     std::size_t num_candidates,
@@ -227494,7 +228665,7 @@ consteval bool backtracking_search(

 // Phase 1: select character positions that distinguish all colliding pairs.
 template <std::size_t N>
-consteval std::size_t select_positions(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL std::size_t select_positions(
     const std::array<std::string_view, N>& keys,
     std::array<std::size_t, MAX_POSITIONS>& positions,
     std::size_t modulus) {
@@ -227573,7 +228744,7 @@ struct phf_result {
 // (position, character) symbol at a time; never revisits a value. Equivalence
 // classes (keys sharing the same undetermined symbols) keep the search cheap.
 template <std::size_t N, std::size_t M>
-consteval bool try_generate_gperf(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_generate_gperf(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -227721,7 +228892,7 @@ consteval bool try_generate_gperf(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -227740,7 +228911,7 @@ consteval bool try_compute_phf(const std::array<std::string_view, N>& keys, phf_
 }

 template <std::size_t N, std::size_t M, std::size_t MaxM>
-consteval bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_gperf_po2(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     if (try_compute_phf<N, M>(keys, result)) { return true; }
     constexpr std::size_t NextM = M * 2;
     if constexpr (NextM <= MaxM) { return try_gperf_po2<N, NextM, MaxM>(keys, result); }
@@ -227775,7 +228946,7 @@ constexpr std::size_t hd_key_hash_4(std::string_view key) noexcept {
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_hash_and_displace(
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_hash_and_displace(
     const std::array<std::string_view, N>& keys,
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS>& asso_values,
     std::size_t& num_positions,
@@ -227875,7 +229046,7 @@ consteval bool try_hash_and_displace(
 }

 template <std::size_t N, std::size_t M>
-consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, phf_result<N>& result) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     std::array<std::array<std::size_t, 256>, MAX_POSITIONS> asso{};
     std::size_t npos{};
@@ -227894,7 +229065,7 @@ consteval bool try_compute_phf_hd(const std::array<std::string_view, N>& keys, p
 }

 template <std::size_t N, std::size_t M>
-consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>& keys) {
     static_assert(M <= phf_result<N>::MAX_TABLE_SIZE, "Table size M exceeds maximum");
     phf_result<N> result{};
     if (try_compute_phf_hd<N, M>(keys, result)) { return result; }
@@ -227910,7 +229081,7 @@ consteval phf_result<N> compute_phf_hd_po2(const std::array<std::string_view, N>
 // Compute a perfect hash for `keys`: try gperf at power-of-two sizes (capped so
 // the runtime tables stay within uint8 indices), then fall back to H&D.
 template <std::size_t N>
-consteval phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_result<N> compute_phf(const std::array<std::string_view, N>& keys) {
     constexpr std::size_t StartM = next_power_of_2(N);
     constexpr std::size_t GPERF_MAX_TABLE =
         phf_result<N>::MAX_TABLE_SIZE < 256 ? phf_result<N>::MAX_TABLE_SIZE : 256;
@@ -227947,7 +229118,7 @@ constexpr std::size_t compute_max_key_len(const std::array<std::string_view, N>&

 // Validate keys and build the runtime tables from the computed perfect hash.
 template <std::size_t N, std::size_t TableSize, std::size_t MaxKeyLen>
-consteval phf_data<N, TableSize, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL phf_data<N, TableSize, MaxKeyLen>
 build_phf_data(const std::array<std::string_view, N>& keys, const phf_result<N>& result) {
     for (std::size_t i = 0; i < N; ++i) {
         if (keys[i].empty())            { compile_time_error("empty keys are not allowed in key_selector"); }
@@ -228256,7 +229427,7 @@ constexpr unsigned window_value(const std::array<std::string_view, N>& keys,
 }

 template <std::size_t N, std::size_t MaxKeyLen>
-consteval window_data<N, MaxKeyLen>
+SIMDJSON_KEY_SELECTOR_CONSTEVAL window_data<N, MaxKeyLen>
 compute_window(const std::array<std::string_view, N>& keys) {
     window_data<N, MaxKeyLen> out{};

@@ -228341,7 +229512,7 @@ match_window_candidate(const char* p, std::uint8_t ki,
 // --- describe() string helpers (constexpr; no std::to_string, which is not) ---

 // Append the decimal form of v to s.
-SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
+inline SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {
     if (v == 0) { s.push_back('0'); return; }
     char buf[20];
     std::size_t n = 0;
@@ -228351,7 +229522,7 @@ SIMDJSON_CONSTEXPR_STRING void append_uint(std::string& s, std::size_t v) {

 // Append a byte as its decimal value, plus the printable character in quotes
 // when it is in the printable ASCII range (e.g. "110 ('n')").
-SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
+inline SIMDJSON_CONSTEXPR_STRING void append_byte(std::string& s, unsigned b) {
     append_uint(s, b);
     if (b >= 0x20 && b < 0x7f) {
         s += " ('";
@@ -231192,30 +232363,36 @@ inline error_code array::for_each_at_path_with_wildcard(std::string_view json_pa
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback);
-        if(err) { return err; }
+        // An element that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     // Specific index case in which we access the element at the given index
-    size_t idx = 0;
-
     for (char c : key) {
       if(c < '0' || c > '9'){
         return INVALID_JSON_POINTER;
       }
-      idx = idx*10 + (c - '0');
     }
-
-    auto element = at(idx);
+    // Rejects leading zeros and indexes that overflow size_t, as DOM does.
+    size_t idx;
+    size_t idx_length;
+    error_code error = internal::parse_json_pointer_array_index(key, idx, idx_length);
     value val;
-    SIMDJSON_TRY(element.get(val));
+    if (!error) { error = at(idx).get(val); }
+    if (error) {
+      if (error == INDEX_OUT_OF_BOUNDS && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }
     if (remaining_path.empty()){
       callback(val);
       return SUCCESS;
     } else {
-      return element.for_each_at_path_with_wildcard(remaining_path, callback);
+      return val.for_each_at_path_with_wildcard(remaining_path, callback);
     }
   }
 }
@@ -235526,13 +236703,21 @@ inline error_code object::for_each_at_path_with_wildcard(std::string_view json_p
       if (remaining_path.empty()) {
         callback(val);
       } else {
-        SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback));
+        // A field that does not match the rest of the path is skipped.
+        error_code err = val.for_each_at_path_with_wildcard(remaining_path, callback);
+        if (err && !internal::is_matching_failure_error(err)) { return err; }
       }
     }
     return SUCCESS;
   } else {
     value val;
-    SIMDJSON_TRY(find_field(key).get(val));
+    error_code error = find_field(key).get(val);
+    if (error) {
+      if (error == NO_SUCH_FIELD && internal::json_path_has_wildcard(remaining_path)) {
+        return SUCCESS;
+      }
+      return error;
+    }

     if (remaining_path.empty()) {
       callback(val);
@@ -244286,10 +245471,10 @@ simdjson_fastfloat_really_inline bool rounds_to_nearest() noexcept {
 //  https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013
 #elif defined(__clang__)
 #pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wfloat-equal"
+SIMDJSON_DISABLE_GCC_WARNING(-Wfloat-equal)
 #elif defined(__GNUC__)
 #pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wfloat-equal"
+SIMDJSON_DISABLE_GCC_WARNING(-Wfloat-equal)
 #endif
   return (fmini + 1.0f == 1.0f - fmini);
 #ifdef SIMDJSON_FASTFLOAT_VISUAL_STUDIO
@@ -244530,7 +245715,7 @@ from_chars_float_advanced(UC const *first, UC const *last, T &value,
 #ifdef __clang__
 #pragma clang diagnostic push
 #if (!defined(__APPLE_CC__) && __clang_major__ >= 10) || (__clang_major__ >= 13)
-#pragma clang diagnostic ignored "-Wc++20-extensions"
+SIMDJSON_DISABLE_GCC_WARNING(-Wc++20-extensions)
 #endif
 #endif
   if simdjson_fastfloat_unlikely (pns.too_many_digits) {