wuffs gen -version=0.3.0-alpha.11
diff --git a/release/c/wuffs-v0.3.c b/release/c/wuffs-v0.3.c
index 21a403e..07c5e1a 100644
--- a/release/c/wuffs-v0.3.c
+++ b/release/c/wuffs-v0.3.c
@@ -65,15 +65,15 @@
 // each major.minor branch, the commit count should increase monotonically.
 //
 // WUFFS_VERSION was overridden by "wuffs gen -version" based on revision
-// 0a9075f81c0dfb10e6ad1ea3f797f416aa8ab742 committed on 2020-07-11.
+// ca1113620b228a7bc7ca86364d5fdfc848361e95 committed on 2020-08-17.
 #define WUFFS_VERSION 0x000030000
 #define WUFFS_VERSION_MAJOR 0
 #define WUFFS_VERSION_MINOR 3
 #define WUFFS_VERSION_PATCH 0
-#define WUFFS_VERSION_PRE_RELEASE_LABEL "alpha.10"
-#define WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT 2566
-#define WUFFS_VERSION_BUILD_METADATA_COMMIT_DATE 20200711
-#define WUFFS_VERSION_STRING "0.3.0-alpha.10+2566.20200711"
+#define WUFFS_VERSION_PRE_RELEASE_LABEL "alpha.11"
+#define WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT 2663
+#define WUFFS_VERSION_BUILD_METADATA_COMMIT_DATE 20200817
+#define WUFFS_VERSION_STRING "0.3.0-alpha.11+2663.20200817"
 
 // Define WUFFS_CONFIG__STATIC_FUNCTIONS to make all of Wuffs' functions have
 // static storage. The motivation is discussed in the "ALLOW STATIC
@@ -905,6 +905,30 @@
   return ret;
 }
 
+static inline wuffs_base__slice_u16  //
+wuffs_base__empty_slice_u16() {
+  wuffs_base__slice_u16 ret;
+  ret.ptr = NULL;
+  ret.len = 0;
+  return ret;
+}
+
+static inline wuffs_base__slice_u32  //
+wuffs_base__empty_slice_u32() {
+  wuffs_base__slice_u32 ret;
+  ret.ptr = NULL;
+  ret.len = 0;
+  return ret;
+}
+
+static inline wuffs_base__slice_u64  //
+wuffs_base__empty_slice_u64() {
+  wuffs_base__slice_u64 ret;
+  ret.ptr = NULL;
+  ret.len = 0;
+  return ret;
+}
+
 static inline wuffs_base__table_u8  //
 wuffs_base__empty_table_u8() {
   wuffs_base__table_u8 ret;
@@ -915,6 +939,36 @@
   return ret;
 }
 
+static inline wuffs_base__table_u16  //
+wuffs_base__empty_table_u16() {
+  wuffs_base__table_u16 ret;
+  ret.ptr = NULL;
+  ret.width = 0;
+  ret.height = 0;
+  ret.stride = 0;
+  return ret;
+}
+
+static inline wuffs_base__table_u32  //
+wuffs_base__empty_table_u32() {
+  wuffs_base__table_u32 ret;
+  ret.ptr = NULL;
+  ret.width = 0;
+  ret.height = 0;
+  ret.stride = 0;
+  return ret;
+}
+
+static inline wuffs_base__table_u64  //
+wuffs_base__empty_table_u64() {
+  wuffs_base__table_u64 ret;
+  ret.ptr = NULL;
+  ret.width = 0;
+  ret.height = 0;
+  ret.stride = 0;
+  return ret;
+}
+
 // wuffs_base__slice_u8__subslice_i returns s[i:].
 //
 // It returns an empty slice if i is out of bounds.
@@ -1903,10 +1957,14 @@
 #ifdef __cplusplus
   inline bool is_valid() const;
   inline void compact();
-  inline uint64_t reader_available() const;
   inline uint64_t reader_io_position() const;
-  inline uint64_t writer_available() const;
+  inline size_t reader_length() const;
+  inline uint8_t* reader_pointer() const;
+  inline wuffs_base__slice_u8 reader_slice() const;
   inline uint64_t writer_io_position() const;
+  inline size_t writer_length() const;
+  inline uint8_t* writer_pointer() const;
+  inline wuffs_base__slice_u8 writer_slice() const;
 #endif  // __cplusplus
 
 } wuffs_base__io_buffer;
@@ -2032,18 +2090,25 @@
 }
 
 static inline uint64_t  //
-wuffs_base__io_buffer__reader_available(const wuffs_base__io_buffer* buf) {
-  return buf ? buf->meta.wi - buf->meta.ri : 0;
-}
-
-static inline uint64_t  //
 wuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {
   return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
 }
 
-static inline uint64_t  //
-wuffs_base__io_buffer__writer_available(const wuffs_base__io_buffer* buf) {
-  return buf ? buf->data.len - buf->meta.wi : 0;
+static inline size_t  //
+wuffs_base__io_buffer__reader_length(const wuffs_base__io_buffer* buf) {
+  return buf ? buf->meta.wi - buf->meta.ri : 0;
+}
+
+static inline uint8_t*  //
+wuffs_base__io_buffer__reader_pointer(const wuffs_base__io_buffer* buf) {
+  return buf ? (buf->data.ptr + buf->meta.ri) : NULL;
+}
+
+static inline wuffs_base__slice_u8  //
+wuffs_base__io_buffer__reader_slice(const wuffs_base__io_buffer* buf) {
+  return buf ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.ri,
+                                         buf->meta.wi - buf->meta.ri)
+             : wuffs_base__empty_slice_u8();
 }
 
 static inline uint64_t  //
@@ -2051,6 +2116,23 @@
   return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
 }
 
+static inline size_t  //
+wuffs_base__io_buffer__writer_length(const wuffs_base__io_buffer* buf) {
+  return buf ? buf->data.len - buf->meta.wi : 0;
+}
+
+static inline uint8_t*  //
+wuffs_base__io_buffer__writer_pointer(const wuffs_base__io_buffer* buf) {
+  return buf ? (buf->data.ptr + buf->meta.wi) : NULL;
+}
+
+static inline wuffs_base__slice_u8  //
+wuffs_base__io_buffer__writer_slice(const wuffs_base__io_buffer* buf) {
+  return buf ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.wi,
+                                         buf->data.len - buf->meta.wi)
+             : wuffs_base__empty_slice_u8();
+}
+
 #ifdef __cplusplus
 
 inline bool  //
@@ -2064,18 +2146,23 @@
 }
 
 inline uint64_t  //
-wuffs_base__io_buffer::reader_available() const {
-  return wuffs_base__io_buffer__reader_available(this);
-}
-
-inline uint64_t  //
 wuffs_base__io_buffer::reader_io_position() const {
   return wuffs_base__io_buffer__reader_io_position(this);
 }
 
-inline uint64_t  //
-wuffs_base__io_buffer::writer_available() const {
-  return wuffs_base__io_buffer__writer_available(this);
+inline size_t  //
+wuffs_base__io_buffer::reader_length() const {
+  return wuffs_base__io_buffer__reader_length(this);
+}
+
+inline uint8_t*  //
+wuffs_base__io_buffer::reader_pointer() const {
+  return wuffs_base__io_buffer__reader_pointer(this);
+}
+
+inline wuffs_base__slice_u8  //
+wuffs_base__io_buffer::reader_slice() const {
+  return wuffs_base__io_buffer__reader_slice(this);
 }
 
 inline uint64_t  //
@@ -2083,6 +2170,21 @@
   return wuffs_base__io_buffer__writer_io_position(this);
 }
 
+inline size_t  //
+wuffs_base__io_buffer::writer_length() const {
+  return wuffs_base__io_buffer__writer_length(this);
+}
+
+inline uint8_t*  //
+wuffs_base__io_buffer::writer_pointer() const {
+  return wuffs_base__io_buffer__writer_pointer(this);
+}
+
+inline wuffs_base__slice_u8  //
+wuffs_base__io_buffer::writer_slice() const {
+  return wuffs_base__io_buffer__writer_slice(this);
+}
+
 #endif  // __cplusplus
 
 // ---------------- Tokens
@@ -2100,6 +2202,7 @@
   inline int64_t value_base_category() const;
   inline uint64_t value_minor() const;
   inline uint64_t value_base_detail() const;
+  inline int64_t value_base_detail__sign_extended() const;
   inline bool continued() const;
   inline uint64_t length() const;
 #endif  // __cplusplus
@@ -2126,6 +2229,8 @@
 #define WUFFS_BASE__TOKEN__CONTINUED__SHIFT 16
 #define WUFFS_BASE__TOKEN__LENGTH__SHIFT 0
 
+#define WUFFS_BASE__TOKEN__VALUE_EXTENSION__NUM_BITS 46
+
 // --------
 
 #define WUFFS_BASE__TOKEN__VBC__FILLER 0
@@ -2134,6 +2239,8 @@
 #define WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT 3
 #define WUFFS_BASE__TOKEN__VBC__LITERAL 4
 #define WUFFS_BASE__TOKEN__VBC__NUMBER 5
+#define WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED 6
+#define WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED 7
 
 // --------
 
@@ -2208,7 +2315,7 @@
 // --------
 
 // For a source string of "123" or "0x9A", it is valid for a tokenizer to
-// return any one of:
+// return any combination of:
 //  - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT.
 //  - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED.
 //  - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED.
@@ -2227,11 +2334,14 @@
 
 // The number 300 might be represented as "\x01\x2C", "\x2C\x01\x00\x00" or
 // "300", which are big-endian, little-endian or text. For binary formats, the
-// token length discriminates e.g. u16 little-endian vs u32 little-endian.
+// token length (after adjusting for FORMAT_IGNORE_ETC) discriminates
+// e.g. u16 little-endian vs u32 little-endian.
 #define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN 0x00100
 #define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_LITTLE_ENDIAN 0x00200
 #define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT 0x00400
 
+#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE 0x01000
+
 // --------
 
 // wuffs_base__token__value returns the token's high 46 bits, sign-extended. A
@@ -2272,6 +2382,15 @@
   return (t->repr >> WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT) & 0x1FFFFF;
 }
 
+static inline int64_t  //
+wuffs_base__token__value_base_detail__sign_extended(
+    const wuffs_base__token* t) {
+  // The VBD is 21 bits in the middle of t->repr. Left shift the high (64 - 21
+  // - ETC__SHIFT) bits off, then right shift (sign-extending) back down.
+  uint64_t u = t->repr << (43 - WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT);
+  return ((int64_t)u) >> 43;
+}
+
 static inline bool  //
 wuffs_base__token__continued(const wuffs_base__token* t) {
   return t->repr & 0x10000;
@@ -2314,6 +2433,11 @@
   return wuffs_base__token__value_base_detail(this);
 }
 
+inline int64_t  //
+wuffs_base__token::value_base_detail__sign_extended() const {
+  return wuffs_base__token__value_base_detail__sign_extended(this);
+}
+
 inline bool  //
 wuffs_base__token::continued() const {
   return wuffs_base__token__continued(this);
@@ -2338,6 +2462,14 @@
   return ret;
 }
 
+static inline wuffs_base__slice_token  //
+wuffs_base__empty_slice_token() {
+  wuffs_base__slice_token ret;
+  ret.ptr = NULL;
+  ret.len = 0;
+  return ret;
+}
+
 // --------
 
 // wuffs_base__token_buffer_meta is the metadata for a
@@ -2360,10 +2492,14 @@
 #ifdef __cplusplus
   inline bool is_valid() const;
   inline void compact();
-  inline uint64_t reader_available() const;
+  inline uint64_t reader_length() const;
+  inline wuffs_base__token* reader_pointer() const;
+  inline wuffs_base__slice_token reader_slice() const;
   inline uint64_t reader_token_position() const;
-  inline uint64_t writer_available() const;
+  inline uint64_t writer_length() const;
   inline uint64_t writer_token_position() const;
+  inline wuffs_base__token* writer_pointer() const;
+  inline wuffs_base__slice_token writer_slice() const;
 #endif  // __cplusplus
 
 } wuffs_base__token_buffer;
@@ -2466,11 +2602,22 @@
 }
 
 static inline uint64_t  //
-wuffs_base__token_buffer__reader_available(
-    const wuffs_base__token_buffer* buf) {
+wuffs_base__token_buffer__reader_length(const wuffs_base__token_buffer* buf) {
   return buf ? buf->meta.wi - buf->meta.ri : 0;
 }
 
+static inline wuffs_base__token*  //
+wuffs_base__token_buffer__reader_pointer(const wuffs_base__token_buffer* buf) {
+  return buf ? (buf->data.ptr + buf->meta.ri) : NULL;
+}
+
+static inline wuffs_base__slice_token  //
+wuffs_base__token_buffer__reader_slice(const wuffs_base__token_buffer* buf) {
+  return buf ? wuffs_base__make_slice_token(buf->data.ptr + buf->meta.ri,
+                                            buf->meta.wi - buf->meta.ri)
+             : wuffs_base__empty_slice_token();
+}
+
 static inline uint64_t  //
 wuffs_base__token_buffer__reader_token_position(
     const wuffs_base__token_buffer* buf) {
@@ -2478,11 +2625,22 @@
 }
 
 static inline uint64_t  //
-wuffs_base__token_buffer__writer_available(
-    const wuffs_base__token_buffer* buf) {
+wuffs_base__token_buffer__writer_length(const wuffs_base__token_buffer* buf) {
   return buf ? buf->data.len - buf->meta.wi : 0;
 }
 
+static inline wuffs_base__token*  //
+wuffs_base__token_buffer__writer_pointer(const wuffs_base__token_buffer* buf) {
+  return buf ? (buf->data.ptr + buf->meta.wi) : NULL;
+}
+
+static inline wuffs_base__slice_token  //
+wuffs_base__token_buffer__writer_slice(const wuffs_base__token_buffer* buf) {
+  return buf ? wuffs_base__make_slice_token(buf->data.ptr + buf->meta.wi,
+                                            buf->data.len - buf->meta.wi)
+             : wuffs_base__empty_slice_token();
+}
+
 static inline uint64_t  //
 wuffs_base__token_buffer__writer_token_position(
     const wuffs_base__token_buffer* buf) {
@@ -2502,8 +2660,18 @@
 }
 
 inline uint64_t  //
-wuffs_base__token_buffer::reader_available() const {
-  return wuffs_base__token_buffer__reader_available(this);
+wuffs_base__token_buffer::reader_length() const {
+  return wuffs_base__token_buffer__reader_length(this);
+}
+
+inline wuffs_base__token*  //
+wuffs_base__token_buffer::reader_pointer() const {
+  return wuffs_base__token_buffer__reader_pointer(this);
+}
+
+inline wuffs_base__slice_token  //
+wuffs_base__token_buffer::reader_slice() const {
+  return wuffs_base__token_buffer__reader_slice(this);
 }
 
 inline uint64_t  //
@@ -2512,8 +2680,18 @@
 }
 
 inline uint64_t  //
-wuffs_base__token_buffer::writer_available() const {
-  return wuffs_base__token_buffer__writer_available(this);
+wuffs_base__token_buffer::writer_length() const {
+  return wuffs_base__token_buffer__writer_length(this);
+}
+
+inline wuffs_base__token*  //
+wuffs_base__token_buffer::writer_pointer() const {
+  return wuffs_base__token_buffer__writer_pointer(this);
+}
+
+inline wuffs_base__slice_token  //
+wuffs_base__token_buffer::writer_slice() const {
+  return wuffs_base__token_buffer__writer_slice(this);
 }
 
 inline uint64_t  //
@@ -4016,6 +4194,106 @@
 
 // ---------------- IEEE 754 Floating Point
 
+// wuffs_base__ieee_754_bit_representation__etc converts between a double
+// precision numerical value and its IEEE 754 representations:
+//   - 16-bit: 1 sign bit,  5 exponent bits, 10 explicit significand bits.
+//   - 32-bit: 1 sign bit,  8 exponent bits, 23 explicit significand bits.
+//   - 64-bit: 1 sign bit, 11 exponent bits, 52 explicit significand bits.
+//
+// For example, it converts between:
+//  - +1.0 and 0x3C00, 0x3F80_0000 or 0x3FF0_0000_0000_0000.
+//  - +5.5 and 0x4580, 0x40B0_0000 or 0x4016_0000_0000_0000.
+//  - -inf and 0xFC00, 0xFF80_0000 or 0xFFF0_0000_0000_0000.
+//
+// Converting from f64 to shorter formats (f16 or f32, represented in C as
+// uint16_t and uint32_t) may be lossy. Such functions have names that look
+// like etc_truncate, as converting finite numbers produce equal or smaller
+// (closer-to-zero) finite numbers. For example, 1048576.0 is a perfectly valid
+// f64 number, but converting it to a f16 (with truncation) produces 65504.0,
+// the largest finite f16 number. Truncating a f64-typed value d to f32 does
+// not always produce the same result as the C-style cast ((float)d), as
+// casting can convert from finite numbers to infinite ones.
+//
+// Converting infinities or NaNs produces infinities or NaNs and always report
+// no loss, even though there a multiple NaN representations so that round-
+// tripping a f64-typed NaN may produce a different 64 bits. Nonetheless, the
+// etc_truncate functions preserve a NaN's "quiet vs signaling" bit.
+//
+// See https://en.wikipedia.org/wiki/Double-precision_floating-point_format
+
+typedef struct {
+  uint16_t value;
+  bool lossy;
+} wuffs_base__lossy_value_u16;
+
+typedef struct {
+  uint32_t value;
+  bool lossy;
+} wuffs_base__lossy_value_u32;
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //
+wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //
+wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f);
+
+static inline uint64_t  //
+wuffs_base__ieee_754_bit_representation__from_f64_to_u64(double f) {
+  uint64_t u = 0;
+  if (sizeof(uint64_t) == sizeof(double)) {
+    memcpy(&u, &f, sizeof(uint64_t));
+  }
+  return u;
+}
+
+static inline double  //
+wuffs_base__ieee_754_bit_representation__from_u16_to_f64(uint16_t u) {
+  uint64_t v = ((uint64_t)(u & 0x8000)) << 48;
+
+  do {
+    uint64_t exp = (u >> 10) & 0x1F;
+    uint64_t man = u & 0x3FF;
+    if (exp == 0x1F) {  // Infinity or NaN.
+      exp = 2047;
+    } else if (exp != 0) {  // Normal.
+      exp += 1008;          // 1008 = 1023 - 15, the difference in biases.
+    } else if (man != 0) {  // Subnormal but non-zero.
+      uint32_t clz = wuffs_base__count_leading_zeroes_u64(man);
+      exp = 1062 - clz;  // 1062 = 1008 + 64 - 10.
+      man = 0x3FF & (man << (clz - 53));
+    } else {  // Zero.
+      break;
+    }
+    v |= (exp << 52) | (man << 42);
+  } while (0);
+
+  double f = 0;
+  if (sizeof(uint64_t) == sizeof(double)) {
+    memcpy(&f, &v, sizeof(uint64_t));
+  }
+  return f;
+}
+
+static inline double  //
+wuffs_base__ieee_754_bit_representation__from_u32_to_f64(uint32_t u) {
+  float f = 0;
+  if (sizeof(uint32_t) == sizeof(float)) {
+    memcpy(&f, &u, sizeof(uint32_t));
+  }
+  return (double)f;
+}
+
+static inline double  //
+wuffs_base__ieee_754_bit_representation__from_u64_to_f64(uint64_t u) {
+  double f = 0;
+  if (sizeof(uint64_t) == sizeof(double)) {
+    memcpy(&f, &u, sizeof(uint64_t));
+  }
+  return f;
+}
+
+// ---------------- Parsing and Rendering Numbers
+
 // wuffs_base__parse_number_f64 parses the floating point number in s. For
 // example, if s contains the bytes "1.5" then it will return the double 1.5.
 //
@@ -4052,39 +4330,6 @@
 WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64  //
 wuffs_base__parse_number_f64(wuffs_base__slice_u8 s, uint32_t options);
 
-// --------
-
-// wuffs_base__ieee_754_bit_representation__etc converts between a double
-// precision numerical value and its IEEE 754 64-bit representation (1 sign
-// bit, 11 exponent bits, 52 explicit significand bits).
-//
-// For example, it converts between:
-//  - +1.0 and 0x3FF0_0000_0000_0000.
-//  - +5.5 and 0x4016_0000_0000_0000.
-//  - -inf and 0xFFF0_0000_0000_0000.
-//
-// See https://en.wikipedia.org/wiki/Double-precision_floating-point_format
-
-static inline uint64_t  //
-wuffs_base__ieee_754_bit_representation__from_f64(double f) {
-  uint64_t u = 0;
-  if (sizeof(uint64_t) == sizeof(double)) {
-    memcpy(&u, &f, sizeof(uint64_t));
-  }
-  return u;
-}
-
-static inline double  //
-wuffs_base__ieee_754_bit_representation__to_f64(uint64_t u) {
-  double f = 0;
-  if (sizeof(uint64_t) == sizeof(double)) {
-    memcpy(&f, &u, sizeof(uint64_t));
-  }
-  return f;
-}
-
-// ---------------- Integer
-
 // wuffs_base__parse_number_i64 parses the ASCII integer in s. For example, if
 // s contains the bytes "-123" then it will return the int64_t -123.
 //
@@ -4135,7 +4380,12 @@
 
 // --------
 
+// WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL is the string length of
+// "-9223372036854775808" and "+9223372036854775807", INT64_MIN and INT64_MAX.
 #define WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL 20
+
+// WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL is the string length of
+// "+18446744073709551615", UINT64_MAX.
 #define WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL 21
 
 // wuffs_base__render_number_f64 writes the decimal encoding of x to dst and
@@ -4242,6 +4492,30 @@
                              bool src_closed,
                              uint32_t options);
 
+// wuffs_base__base_16__encode2 converts "jk" to "6A6B", where e.g. 'j' is
+// U+006A. There are 2 dst bytes for every src byte.
+//
+// For modular builds that divide the base module into sub-modules, using this
+// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
+// just WUFFS_CONFIG__MODULE__BASE__CORE.
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output  //
+wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
+                             wuffs_base__slice_u8 src,
+                             bool src_closed,
+                             uint32_t options);
+
+// wuffs_base__base_16__encode4 converts "jk" to "\\x6A\\x6B", where e.g. 'j'
+// is U+006A. There are 4 dst bytes for every src byte.
+//
+// For modular builds that divide the base module into sub-modules, using this
+// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
+// just WUFFS_CONFIG__MODULE__BASE__CORE.
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output  //
+wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
+                             wuffs_base__slice_u8 src,
+                             bool src_closed,
+                             uint32_t options);
+
 // ---------------- Base-64
 
 // Options (bitwise or'ed together) for wuffs_base__base_64__xxx functions.
@@ -4387,7 +4661,7 @@
 wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point);
 
 // wuffs_base__utf_8__next returns the next UTF-8 code point (and that code
-// point's byte length) at the start of s.
+// point's byte length) at the start of the read-only slice (s_ptr, s_len).
 //
 // There are exactly two cases in which this function returns something where
 // wuffs_base__utf_8__next__output__is_valid is false:
@@ -4400,7 +4674,7 @@
 //
 // In any case, it always returns an output that satisfies both of:
 //  - (output.code_point  <= WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL).
-//  - (output.byte_length <= s.len).
+//  - (output.byte_length <= s_len).
 //
 // If s is a sub-slice of a larger slice of valid UTF-8, but that sub-slice
 // boundary occurs in the middle of a multi-byte UTF-8 encoding of a single
@@ -4411,44 +4685,46 @@
 // function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
 // WUFFS_CONFIG__MODULE__BASE__CORE.
 WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output  //
-wuffs_base__utf_8__next(wuffs_base__slice_u8 s);
+wuffs_base__utf_8__next(const uint8_t* s_ptr, size_t s_len);
 
 // wuffs_base__utf_8__next_from_end is like wuffs_base__utf_8__next except that
-// it looks at the end of s instead of the start.
+// it looks at the end of (s_ptr, s_len) instead of the start.
 //
 // For modular builds that divide the base module into sub-modules, using this
 // function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
 // WUFFS_CONFIG__MODULE__BASE__CORE.
 WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output  //
-wuffs_base__utf_8__next_from_end(wuffs_base__slice_u8 s);
+wuffs_base__utf_8__next_from_end(const uint8_t* s_ptr, size_t s_len);
 
 // wuffs_base__utf_8__longest_valid_prefix returns the largest n such that the
-// sub-slice s[..n] is valid UTF-8.
+// sub-slice s[..n] is valid UTF-8, where s is the read-only slice (s_ptr,
+// s_len).
 //
-// In particular, it returns s.len if and only if all of s is valid UTF-8.
+// In particular, it returns s_len if and only if all of s is valid UTF-8.
 //
 // If s is a sub-slice of a larger slice of valid UTF-8, but that sub-slice
 // boundary occurs in the middle of a multi-byte UTF-8 encoding of a single
-// code point, then this function will return less than s.len. It is the
+// code point, then this function will return less than s_len. It is the
 // caller's responsibility to split on or otherwise manage UTF-8 boundaries.
 //
 // For modular builds that divide the base module into sub-modules, using this
 // function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
 // WUFFS_CONFIG__MODULE__BASE__CORE.
 WUFFS_BASE__MAYBE_STATIC size_t  //
-wuffs_base__utf_8__longest_valid_prefix(wuffs_base__slice_u8 s);
+wuffs_base__utf_8__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len);
 
 // wuffs_base__ascii__longest_valid_prefix returns the largest n such that the
-// sub-slice s[..n] is valid ASCII.
+// sub-slice s[..n] is valid ASCII, where s is the read-only slice (s_ptr,
+// s_len).
 //
-// In particular, it returns s.len if and only if all of s is valid ASCII.
+// In particular, it returns s_len if and only if all of s is valid ASCII.
 // Equivalently, when none of the bytes in s have the 0x80 high bit set.
 //
 // For modular builds that divide the base module into sub-modules, using this
 // function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
 // WUFFS_CONFIG__MODULE__BASE__CORE.
 WUFFS_BASE__MAYBE_STATIC size_t  //
-wuffs_base__ascii__longest_valid_prefix(wuffs_base__slice_u8 s);
+wuffs_base__ascii__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len);
 
 // ---------------- Interface Declarations.
 
@@ -5422,6 +5698,230 @@
 
 // ---------------- Status Codes
 
+extern const char wuffs_cbor__error__bad_input[];
+extern const char wuffs_cbor__error__unsupported_recursion_depth[];
+
+// ---------------- Public Consts
+
+#define WUFFS_CBOR__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
+
+#define WUFFS_CBOR__DECODER_DEPTH_MAX_INCL 1024
+
+#define WUFFS_CBOR__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 2
+
+#define WUFFS_CBOR__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 9
+
+#define WUFFS_CBOR__TOKEN_VALUE_MAJOR 787997
+
+#define WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK 262143
+
+#define WUFFS_CBOR__TOKEN_VALUE_MINOR__MINUS_1_MINUS_X 16777216
+
+#define WUFFS_CBOR__TOKEN_VALUE_MINOR__SIMPLE_VALUE 8388608
+
+#define WUFFS_CBOR__TOKEN_VALUE_MINOR__TAG 4194304
+
+// ---------------- Struct Declarations
+
+typedef struct wuffs_cbor__decoder__struct wuffs_cbor__decoder;
+
+// ---------------- Public Initializer Prototypes
+
+// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
+// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
+//
+// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
+// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
+
+wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
+wuffs_cbor__decoder__initialize(
+    wuffs_cbor__decoder* self,
+    size_t sizeof_star_self,
+    uint64_t wuffs_version,
+    uint32_t options);
+
+size_t
+sizeof__wuffs_cbor__decoder();
+
+// ---------------- Allocs
+
+// These functions allocate and initialize Wuffs structs. They return NULL if
+// memory allocation fails. If they return non-NULL, there is no need to call
+// wuffs_foo__bar__initialize, but the caller is responsible for eventually
+// calling free on the returned pointer. That pointer is effectively a C++
+// std::unique_ptr<T, decltype(&free)>.
+
+wuffs_cbor__decoder*
+wuffs_cbor__decoder__alloc();
+
+static inline wuffs_base__token_decoder*
+wuffs_cbor__decoder__alloc_as__wuffs_base__token_decoder() {
+  return (wuffs_base__token_decoder*)(wuffs_cbor__decoder__alloc());
+}
+
+// ---------------- Upcasts
+
+static inline wuffs_base__token_decoder*
+wuffs_cbor__decoder__upcast_as__wuffs_base__token_decoder(
+    wuffs_cbor__decoder* p) {
+  return (wuffs_base__token_decoder*)p;
+}
+
+// ---------------- Public Function Prototypes
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
+wuffs_cbor__decoder__set_quirk_enabled(
+    wuffs_cbor__decoder* self,
+    uint32_t a_quirk,
+    bool a_enabled);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
+wuffs_cbor__decoder__workbuf_len(
+    const wuffs_cbor__decoder* self);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status
+wuffs_cbor__decoder__decode_tokens(
+    wuffs_cbor__decoder* self,
+    wuffs_base__token_buffer* a_dst,
+    wuffs_base__io_buffer* a_src,
+    wuffs_base__slice_u8 a_workbuf);
+
+// ---------------- Struct Definitions
+
+// These structs' fields, and the sizeof them, are private implementation
+// details that aren't guaranteed to be stable across Wuffs versions.
+//
+// See https://en.wikipedia.org/wiki/Opaque_pointer#C
+
+#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
+
+struct wuffs_cbor__decoder__struct {
+  // Do not access the private_impl's or private_data's fields directly. There
+  // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
+  // the wuffs_foo__bar__baz functions.
+  //
+  // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
+  // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
+
+  struct {
+    uint32_t magic;
+    uint32_t active_coroutine;
+    wuffs_base__vtable vtable_for__wuffs_base__token_decoder;
+    wuffs_base__vtable null_vtable;
+
+    bool f_end_of_data;
+
+    uint32_t p_decode_tokens[1];
+  } private_impl;
+
+  struct {
+    uint32_t f_stack[64];
+    uint64_t f_container_num_remaining[1024];
+
+    struct {
+      uint64_t v_string_length;
+      uint32_t v_depth;
+      uint32_t v_token_length;
+      bool v_tagged;
+      uint8_t v_indefinite_string_major_type;
+    } s_decode_tokens[1];
+  } private_data;
+
+#ifdef __cplusplus
+#if (__cplusplus >= 201103L)
+  using unique_ptr = std::unique_ptr<wuffs_cbor__decoder, decltype(&free)>;
+
+  // On failure, the alloc_etc functions return nullptr. They don't throw.
+
+  static inline unique_ptr
+  alloc() {
+    return unique_ptr(wuffs_cbor__decoder__alloc(), &free);
+  }
+
+  static inline wuffs_base__token_decoder::unique_ptr
+  alloc_as__wuffs_base__token_decoder() {
+    return wuffs_base__token_decoder::unique_ptr(
+        wuffs_cbor__decoder__alloc_as__wuffs_base__token_decoder(), &free);
+  }
+#endif  // (__cplusplus >= 201103L)
+
+#if (__cplusplus >= 201103L) && !defined(WUFFS_IMPLEMENTATION)
+  // Disallow constructing or copying an object via standard C++ mechanisms,
+  // e.g. the "new" operator, as this struct is intentionally opaque. Its total
+  // size and field layout is not part of the public, stable, memory-safe API.
+  // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
+  // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
+  // their first argument) rather than tweaking bar.private_impl.qux fields.
+  //
+  // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
+  // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
+  // order to provide convenience methods. These forward on "this", so that you
+  // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
+  wuffs_cbor__decoder__struct() = delete;
+  wuffs_cbor__decoder__struct(const wuffs_cbor__decoder__struct&) = delete;
+  wuffs_cbor__decoder__struct& operator=(
+      const wuffs_cbor__decoder__struct&) = delete;
+
+  // As above, the size of the struct is not part of the public API, and unless
+  // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
+  // allocated, not stack allocated. Its size is not intended to be known at
+  // compile time, but it is unfortunately divulged as a side effect of
+  // defining C++ convenience methods. Use "sizeof__T()", calling the function,
+  // instead of "sizeof T", invoking the operator. To make the two values
+  // different, so that passing the latter will be rejected by the initialize
+  // function, we add an arbitrary amount of dead weight.
+  uint8_t dead_weight[123000000];  // 123 MB.
+#endif  // (__cplusplus >= 201103L) && !defined(WUFFS_IMPLEMENTATION)
+
+  inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
+  initialize(
+      size_t sizeof_star_self,
+      uint64_t wuffs_version,
+      uint32_t options) {
+    return wuffs_cbor__decoder__initialize(
+        this, sizeof_star_self, wuffs_version, options);
+  }
+
+  inline wuffs_base__token_decoder*
+  upcast_as__wuffs_base__token_decoder() {
+    return (wuffs_base__token_decoder*)this;
+  }
+
+  inline wuffs_base__empty_struct
+  set_quirk_enabled(
+      uint32_t a_quirk,
+      bool a_enabled) {
+    return wuffs_cbor__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
+  }
+
+  inline wuffs_base__range_ii_u64
+  workbuf_len() const {
+    return wuffs_cbor__decoder__workbuf_len(this);
+  }
+
+  inline wuffs_base__status
+  decode_tokens(
+      wuffs_base__token_buffer* a_dst,
+      wuffs_base__io_buffer* a_src,
+      wuffs_base__slice_u8 a_workbuf) {
+    return wuffs_cbor__decoder__decode_tokens(this, a_dst, a_src, a_workbuf);
+  }
+
+#endif  // __cplusplus
+};  // struct wuffs_cbor__decoder__struct
+
+#endif  // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------- Status Codes
+
 // ---------------- Public Consts
 
 // ---------------- Struct Declarations
@@ -7076,6 +7576,7 @@
 extern const char wuffs_json__error__bad_utf_8[];
 extern const char wuffs_json__error__bad_backslash_escape[];
 extern const char wuffs_json__error__bad_input[];
+extern const char wuffs_json__error__bad_quirk_combination[];
 extern const char wuffs_json__error__unsupported_number_length[];
 extern const char wuffs_json__error__unsupported_recursion_depth[];
 
@@ -7105,25 +7606,29 @@
 
 #define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_V 1225364487
 
-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X 1225364488
+#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X_AS_BYTES 1225364488
 
-#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO 1225364489
+#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X_AS_CODE_POINTS 1225364489
 
-#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK 1225364490
+#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO 1225364490
 
-#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE 1225364491
+#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK 1225364491
 
-#define WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA 1225364492
+#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE 1225364492
 
-#define WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS 1225364493
+#define WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA 1225364493
 
-#define WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR 1225364494
+#define WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS 1225364494
 
-#define WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK 1225364495
+#define WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR 1225364495
 
-#define WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE 1225364496
+#define WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK 1225364496
 
-#define WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE 1225364497
+#define WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE 1225364497
+
+#define WUFFS_JSON__QUIRK_JSON_POINTER_ALLOW_TILDE_R_TILDE_N 1225364498
+
+#define WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE 1225364499
 
 // ---------------- Struct Declarations
 
@@ -7213,10 +7718,11 @@
     wuffs_base__vtable vtable_for__wuffs_base__token_decoder;
     wuffs_base__vtable null_vtable;
 
-    bool f_quirks[18];
+    bool f_quirks[20];
     bool f_allow_leading_ars;
     bool f_allow_leading_ubom;
     bool f_end_of_data;
+    uint32_t f_string_value_minor;
 
     uint32_t p_decode_tokens[1];
     uint32_t p_decode_leading[1];
@@ -7899,6 +8405,236 @@
 }  // extern "C"
 #endif
 
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+
+// ---------------- Auxiliary - Base
+
+// Auxiliary code is discussed at
+// https://github.com/google/wuffs/blob/master/doc/note/auxiliary-code.md
+
+#include <stdio.h>
+
+#include <string>
+
+namespace wuffs_aux {
+
+using IOBuffer = wuffs_base__io_buffer;
+
+namespace sync_io {
+
+// --------
+
+class Input {
+ public:
+  virtual IOBuffer* BringsItsOwnIOBuffer();
+  virtual std::string CopyIn(IOBuffer* dst) = 0;
+};
+
+// --------
+
+// FileInput is an Input that reads from a file source.
+//
+// It does not take responsibility for closing the file when done.
+class FileInput : public Input {
+ public:
+  FileInput(FILE* f);
+
+  virtual std::string CopyIn(IOBuffer* dst);
+
+ private:
+  FILE* m_f;
+
+  // Delete the copy and assign constructors.
+  FileInput(const FileInput&) = delete;
+  FileInput& operator=(const FileInput&) = delete;
+};
+
+// --------
+
+// MemoryInput is an Input that reads from an in-memory source.
+//
+// It does not take responsibility for freeing the memory when done.
+class MemoryInput : public Input {
+ public:
+  MemoryInput(const char* ptr, size_t len);
+  MemoryInput(const uint8_t* ptr, size_t len);
+
+  virtual IOBuffer* BringsItsOwnIOBuffer();
+  virtual std::string CopyIn(IOBuffer* dst);
+
+ private:
+  IOBuffer m_io;
+
+  // Delete the copy and assign constructors.
+  MemoryInput(const MemoryInput&) = delete;
+  MemoryInput& operator=(const MemoryInput&) = delete;
+};
+
+// --------
+
+}  // namespace sync_io
+
+}  // namespace wuffs_aux
+
+// ---------------- Auxiliary - CBOR
+
+namespace wuffs_aux {
+
+struct DecodeCborResult {
+  DecodeCborResult(std::string&& error_message0, uint64_t cursor_position0);
+
+  std::string error_message;
+  uint64_t cursor_position;
+};
+
+class DecodeCborCallbacks {
+ public:
+  // AppendXxx are called for leaf nodes: literals, numbers, strings, etc.
+
+  virtual std::string AppendNull() = 0;
+  virtual std::string AppendUndefined() = 0;
+  virtual std::string AppendBool(bool val) = 0;
+  virtual std::string AppendF64(double val) = 0;
+  virtual std::string AppendI64(int64_t val) = 0;
+  virtual std::string AppendU64(uint64_t val) = 0;
+  virtual std::string AppendByteString(std::string&& val) = 0;
+  virtual std::string AppendTextString(std::string&& val) = 0;
+  virtual std::string AppendMinus1MinusX(uint64_t val) = 0;
+  virtual std::string AppendCborSimpleValue(uint8_t val) = 0;
+  virtual std::string AppendCborTag(uint64_t val) = 0;
+
+  // Push and Pop are called for container nodes: CBOR arrays (lists) and CBOR
+  // maps (dictionaries).
+  //
+  // The flags bits combine exactly one of:
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT
+  // and exactly one of:
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT
+
+  virtual std::string Push(uint32_t flags) = 0;
+  virtual std::string Pop(uint32_t flags) = 0;
+
+  // Done is always the last Callback method called by DecodeCbor, whether or
+  // not parsing the input as CBOR encountered an error. Even when successful,
+  // trailing data may remain in input and buffer.
+  //
+  // Do not keep a reference to buffer or buffer.data.ptr after Done returns,
+  // as DecodeCbor may then de-allocate the backing array.
+  //
+  // The default Done implementation is a no-op.
+  virtual void Done(DecodeCborResult& result,
+                    sync_io::Input& input,
+                    IOBuffer& buffer);
+};
+
+// DecodeCbor calls callbacks based on the CBOR-formatted data in input.
+//
+// On success, the returned error_message is empty and cursor_position counts
+// the number of bytes consumed. On failure, error_message is non-empty and
+// cursor_position is the location of the error. That error may be a content
+// error (invalid CBOR) or an input error (e.g. network failure).
+DecodeCborResult DecodeCbor(
+    DecodeCborCallbacks& callbacks,
+    sync_io::Input& input,
+    wuffs_base__slice_u32 quirks = wuffs_base__empty_slice_u32());
+
+}  // namespace wuffs_aux
+
+// ---------------- Auxiliary - JSON
+
+namespace wuffs_aux {
+
+struct DecodeJsonResult {
+  DecodeJsonResult(std::string&& error_message0, uint64_t cursor_position0);
+
+  std::string error_message;
+  uint64_t cursor_position;
+};
+
+class DecodeJsonCallbacks {
+ public:
+  // AppendXxx are called for leaf nodes: literals, numbers and strings. For
+  // strings, the Callbacks implementation is responsible for tracking map keys
+  // versus other values.
+
+  // The JSON file format as specified deals only with (UTF-8) text strings,
+  // but an unofficial extension allows "ijk\x89m" escapes within those
+  // strings. DecodeJsonCallbacks' AppendByteString will not be called unless
+  // WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X_AS_BYTES is passed to DecodeJson. If
+  // it is passed, AppendTextString will not be called and all byte strings are
+  // potentially invalid UTF-8. It is up to the AppendByteString implementation
+  // whether to test the std::string for UTF-8 validity.
+  //
+  // The default AppendByteString implementation returns an error message.
+
+  virtual std::string AppendNull() = 0;
+  virtual std::string AppendBool(bool val) = 0;
+  virtual std::string AppendF64(double val) = 0;
+  virtual std::string AppendI64(int64_t val) = 0;
+  virtual std::string AppendByteString(std::string&& val);
+  virtual std::string AppendTextString(std::string&& val) = 0;
+
+  // Push and Pop are called for container nodes: JSON arrays (lists) and JSON
+  // objects (dictionaries).
+  //
+  // The flags bits combine exactly one of:
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT
+  // and exactly one of:
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST
+  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT
+
+  virtual std::string Push(uint32_t flags) = 0;
+  virtual std::string Pop(uint32_t flags) = 0;
+
+  // Done is always the last Callback method called by DecodeJson, whether or
+  // not parsing the input as JSON encountered an error. Even when successful,
+  // trailing data may remain in input and buffer. See "Unintuitive JSON
+  // Parsing" (https://nullprogram.com/blog/2019/12/28/) which discusses JSON
+  // parsing and when it stops.
+  //
+  // Do not keep a reference to buffer or buffer.data.ptr after Done returns,
+  // as DecodeJson may then de-allocate the backing array.
+  //
+  // The default Done implementation is a no-op.
+  virtual void Done(DecodeJsonResult& result,
+                    sync_io::Input& input,
+                    IOBuffer& buffer);
+};
+
+extern const char DecodeJson_BadJsonPointer[];
+extern const char DecodeJson_NoMatch[];
+
+// DecodeJson calls callbacks based on the JSON-formatted data in input.
+//
+// On success, the returned error_message is empty and cursor_position counts
+// the number of bytes consumed. On failure, error_message is non-empty and
+// cursor_position is the location of the error. That error may be a content
+// error (invalid JSON) or an input error (e.g. network failure).
+//
+// json_pointer is a query in the JSON Pointer (RFC 6901) syntax. The callbacks
+// run for the input's sub-node that matches the query. DecodeJson_NoMatch is
+// returned if no matching sub-node was found. The empty query matches the
+// input's root node, consistent with JSON Pointer semantics.
+//
+// The JSON Pointer implementation is greedy: duplicate keys are not rejected
+// but only the first match for each '/'-separated fragment is followed.
+DecodeJsonResult DecodeJson(
+    DecodeJsonCallbacks& callbacks,
+    sync_io::Input& input,
+    wuffs_base__slice_u32 quirks = wuffs_base__empty_slice_u32(),
+    std::string json_pointer = std::string());
+
+}  // namespace wuffs_aux
+
+#endif  // defined(__cplusplus) && (__cplusplus >= 201103L)
+
 // WUFFS C HEADER ENDS HERE.
 #ifdef WUFFS_IMPLEMENTATION
 
@@ -9231,7 +9967,7 @@
 //
 // The 1214 bias in this look-up table equals 1023 + 191. 1023 is the bias for
 // IEEE 754 double-precision floating point. 191 is ((3 * 64) - 1) and
-// wuffs_base__private_implementation__parse_number_f64_eisel works with
+// wuffs_base__private_implementation__parse_number_f64_eisel_lemire works with
 // multiples-of-64-bit mantissas.
 //
 // For example, the third approximation, for 1e-324, consists of the uint32_t
@@ -9898,6 +10634,136 @@
 
 // ---------------- IEEE 754 Floating Point
 
+WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //
+wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f) {
+  uint64_t u = 0;
+  if (sizeof(uint64_t) == sizeof(double)) {
+    memcpy(&u, &f, sizeof(uint64_t));
+  }
+  uint16_t neg = ((uint16_t)((u >> 63) << 15));
+  u &= 0x7FFFFFFFFFFFFFFF;
+  uint64_t exp = u >> 52;
+  uint64_t man = u & 0x000FFFFFFFFFFFFF;
+
+  if (exp == 0x7FF) {
+    if (man == 0) {  // Infinity.
+      wuffs_base__lossy_value_u16 ret;
+      ret.value = neg | 0x7C00;
+      ret.lossy = false;
+      return ret;
+    }
+    // NaN. Shift the 52 mantissa bits to 10 mantissa bits, keeping the most
+    // significant mantissa bit (quiet vs signaling NaNs). Also set the low 9
+    // bits of ret.value so that the 10-bit mantissa is non-zero.
+    wuffs_base__lossy_value_u16 ret;
+    ret.value = neg | 0x7DFF | ((uint16_t)(man >> 42));
+    ret.lossy = false;
+    return ret;
+
+  } else if (exp > 0x40E) {  // Truncate to the largest finite f16.
+    wuffs_base__lossy_value_u16 ret;
+    ret.value = neg | 0x7BFF;
+    ret.lossy = true;
+    return ret;
+
+  } else if (exp <= 0x3E6) {  // Truncate to zero.
+    wuffs_base__lossy_value_u16 ret;
+    ret.value = neg;
+    ret.lossy = (u != 0);
+    return ret;
+
+  } else if (exp <= 0x3F0) {  // Normal f64, subnormal f16.
+    // Convert from a 53-bit mantissa (after realizing the implicit bit) to a
+    // 10-bit mantissa and then adjust for the exponent.
+    man |= 0x0010000000000000;
+    uint32_t shift = ((uint32_t)(1051 - exp));  // 1051 = 0x3F0 + 53 - 10.
+    uint64_t shifted_man = man >> shift;
+    wuffs_base__lossy_value_u16 ret;
+    ret.value = neg | ((uint16_t)shifted_man);
+    ret.lossy = (shifted_man << shift) != man;
+    return ret;
+  }
+
+  // Normal f64, normal f16.
+
+  // Re-bias from 1023 to 15 and shift above f16's 10 mantissa bits.
+  exp = (exp - 1008) << 10;  // 1008 = 1023 - 15 = 0x3FF - 0xF.
+
+  // Convert from a 52-bit mantissa (excluding the implicit bit) to a 10-bit
+  // mantissa (again excluding the implicit bit). We lose some information if
+  // any of the bottom 42 bits are non-zero.
+  wuffs_base__lossy_value_u16 ret;
+  ret.value = neg | ((uint16_t)exp) | ((uint16_t)(man >> 42));
+  ret.lossy = (man << 22) != 0;
+  return ret;
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //
+wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f) {
+  uint64_t u = 0;
+  if (sizeof(uint64_t) == sizeof(double)) {
+    memcpy(&u, &f, sizeof(uint64_t));
+  }
+  uint32_t neg = ((uint32_t)(u >> 63)) << 31;
+  u &= 0x7FFFFFFFFFFFFFFF;
+  uint64_t exp = u >> 52;
+  uint64_t man = u & 0x000FFFFFFFFFFFFF;
+
+  if (exp == 0x7FF) {
+    if (man == 0) {  // Infinity.
+      wuffs_base__lossy_value_u32 ret;
+      ret.value = neg | 0x7F800000;
+      ret.lossy = false;
+      return ret;
+    }
+    // NaN. Shift the 52 mantissa bits to 23 mantissa bits, keeping the most
+    // significant mantissa bit (quiet vs signaling NaNs). Also set the low 22
+    // bits of ret.value so that the 23-bit mantissa is non-zero.
+    wuffs_base__lossy_value_u32 ret;
+    ret.value = neg | 0x7FBFFFFF | ((uint32_t)(man >> 29));
+    ret.lossy = false;
+    return ret;
+
+  } else if (exp > 0x47E) {  // Truncate to the largest finite f32.
+    wuffs_base__lossy_value_u32 ret;
+    ret.value = neg | 0x7F7FFFFF;
+    ret.lossy = true;
+    return ret;
+
+  } else if (exp <= 0x369) {  // Truncate to zero.
+    wuffs_base__lossy_value_u32 ret;
+    ret.value = neg;
+    ret.lossy = (u != 0);
+    return ret;
+
+  } else if (exp <= 0x380) {  // Normal f64, subnormal f32.
+    // Convert from a 53-bit mantissa (after realizing the implicit bit) to a
+    // 23-bit mantissa and then adjust for the exponent.
+    man |= 0x0010000000000000;
+    uint32_t shift = ((uint32_t)(926 - exp));  // 926 = 0x380 + 53 - 23.
+    uint64_t shifted_man = man >> shift;
+    wuffs_base__lossy_value_u32 ret;
+    ret.value = neg | ((uint32_t)shifted_man);
+    ret.lossy = (shifted_man << shift) != man;
+    return ret;
+  }
+
+  // Normal f64, normal f32.
+
+  // Re-bias from 1023 to 127 and shift above f32's 23 mantissa bits.
+  exp = (exp - 896) << 23;  // 896 = 1023 - 127 = 0x3FF - 0x7F.
+
+  // Convert from a 52-bit mantissa (excluding the implicit bit) to a 23-bit
+  // mantissa (again excluding the implicit bit). We lose some information if
+  // any of the bottom 29 bits are non-zero.
+  wuffs_base__lossy_value_u32 ret;
+  ret.value = neg | ((uint32_t)exp) | ((uint32_t)(man >> 29));
+  ret.lossy = (man << 35) != 0;
+  return ret;
+}
+
+// --------
+
 #define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE 2047
 #define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION 800
 
@@ -10712,9 +11578,9 @@
 
 // --------
 
-// wuffs_base__private_implementation__parse_number_f64_eisel produces the IEEE
-// 754 double-precision value for an exact mantissa and base-10 exponent. For
-// example:
+// wuffs_base__private_implementation__parse_number_f64_eisel_lemire produces
+// the IEEE 754 double-precision value for an exact mantissa and base-10
+// exponent. For example:
 //  - when parsing "12345.678e+02", man is 12345678 and exp10 is -1.
 //  - when parsing "-12", man is 12 and exp10 is 0. Processing the leading
 //    minus sign is the responsibility of the caller, not this function.
@@ -10724,7 +11590,8 @@
 //
 // On failure, it returns a negative value.
 //
-// The algorithm is based on an original idea by Michael Eisel. See
+// The algorithm is based on an original idea by Michael Eisel that was refined
+// by Daniel Lemire. See
 // https://lemire.me/blog/2020/03/10/fast-float-parsing-in-practice/
 //
 // Preconditions:
@@ -10732,8 +11599,9 @@
 //  - exp10 is in the range -326 ..= 310, the same range of the
 //    wuffs_base__private_implementation__powers_of_10 array.
 static int64_t  //
-wuffs_base__private_implementation__parse_number_f64_eisel(uint64_t man,
-                                                           int32_t exp10) {
+wuffs_base__private_implementation__parse_number_f64_eisel_lemire(
+    uint64_t man,
+    int32_t exp10) {
   // Look up the (possibly truncated) base-2 representation of (10 ** exp10).
   // The look-up table was constructed so that it is already normalized: the
   // table entry's mantissa's MSB (most significant bit) is on.
@@ -10965,7 +11833,7 @@
     }
     wuffs_base__result_f64 ret;
     ret.status.repr = NULL;
-    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(
+    ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
         (nan ? 0x7FFFFFFFFFFFFFFF : 0x7FF0000000000000) |
         (negative ? 0x8000000000000000 : 0));
     return ret;
@@ -11002,11 +11870,11 @@
       goto infinity;
     }
 
-    // Try the fast Eisel algorithm again. Calculating the (man, exp10) pair
-    // from the high_prec_dec h is more correct but slower than the approach
-    // taken in wuffs_base__parse_number_f64. The latter is optimized for the
-    // common cases (e.g. assuming no underscores or a leading '+' sign) rather
-    // than the full set of cases allowed by the Wuffs API.
+    // Try the fast Eisel-Lemire algorithm again. Calculating the (man, exp10)
+    // pair from the high_prec_dec h is more correct but slower than the
+    // approach taken in wuffs_base__parse_number_f64. The latter is optimized
+    // for the common cases (e.g. assuming no underscores or a leading '+'
+    // sign) rather than the full set of cases allowed by the Wuffs API.
     if (h->num_digits <= 19) {
       uint64_t man = 0;
       uint32_t i;
@@ -11015,12 +11883,13 @@
       }
       int32_t exp10 = h->decimal_point - ((int32_t)(h->num_digits));
       if ((man != 0) && (-326 <= exp10) && (exp10 <= 310)) {
-        int64_t r = wuffs_base__private_implementation__parse_number_f64_eisel(
-            man, exp10);
+        int64_t r =
+            wuffs_base__private_implementation__parse_number_f64_eisel_lemire(
+                man, exp10);
         if (r >= 0) {
           wuffs_base__result_f64 ret;
           ret.status.repr = NULL;
-          ret.value = wuffs_base__ieee_754_bit_representation__to_f64(
+          ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
               ((uint64_t)r) | (((uint64_t)(h->negative)) << 63));
           return ret;
         }
@@ -11115,7 +11984,7 @@
 
     wuffs_base__result_f64 ret;
     ret.status.repr = NULL;
-    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);
+    ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits);
     return ret;
   } while (0);
 
@@ -11125,7 +11994,7 @@
 
     wuffs_base__result_f64 ret;
     ret.status.repr = NULL;
-    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);
+    ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits);
     return ret;
   } while (0);
 
@@ -11142,7 +12011,7 @@
 
     wuffs_base__result_f64 ret;
     ret.status.repr = NULL;
-    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);
+    ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits);
     return ret;
   } while (0);
 }
@@ -11163,9 +12032,9 @@
   // "Do It Yourself Floating Point" type from Loitsch (†), but the exponent
   // here is base-10, not base-2.
   //
-  // If s's number fits in a (man, exp10), parse that pair with the Eisel
-  // algorithm. If not, or if Eisel fails, parsing s with the fallback
-  // algorithm is slower but comprehensive.
+  // If s's number fits in a (man, exp10), parse that pair with the
+  // Eisel-Lemire algorithm. If not, or if Eisel-Lemire fails, parsing s with
+  // the fallback algorithm is slower but comprehensive.
   //
   // † "Printing Floating-Point Numbers Quickly and Accurately with Integers"
   // (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf).
@@ -11321,7 +12190,7 @@
       }
     }
 
-    // The wuffs_base__private_implementation__parse_number_f64_eisel
+    // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire
     // preconditions include that exp10 is in the range -326 ..= 310.
     if ((exp10 < -326) || (310 < exp10)) {
       goto fallback;
@@ -11329,7 +12198,7 @@
 
     // If man and exp10 are small enough, all three of (man), (10 ** exp10) and
     // (man ** (10 ** exp10)) are exactly representable by a double. We don't
-    // need to run the Eisel algorithm.
+    // need to run the Eisel-Lemire algorithm.
     if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) {
       double d = (double)man;
       if (exp10 >= 0) {
@@ -11343,22 +12212,23 @@
       return ret;
     }
 
-    // The wuffs_base__private_implementation__parse_number_f64_eisel
+    // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire
     // preconditions include that man is non-zero. Parsing "0" should be caught
     // by the "If man and exp10 are small enough" above, but "0e99" might not.
     if (man == 0) {
       goto fallback;
     }
 
-    // Our man and exp10 are in range. Run the Eisel algorithm.
+    // Our man and exp10 are in range. Run the Eisel-Lemire algorithm.
     int64_t r =
-        wuffs_base__private_implementation__parse_number_f64_eisel(man, exp10);
+        wuffs_base__private_implementation__parse_number_f64_eisel_lemire(
+            man, exp10);
     if (r < 0) {
       goto fallback;
     }
     wuffs_base__result_f64 ret;
     ret.status.repr = NULL;
-    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(
+    ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
         ((uint64_t)r) | (((uint64_t)negative) << 63));
     return ret;
   } while (0);
@@ -11574,7 +12444,7 @@
                               uint32_t options) {
   // Decompose x (64 bits) into negativity (1 bit), base-2 exponent (11 bits
   // with a -1023 bias) and mantissa (52 bits).
-  uint64_t bits = wuffs_base__ieee_754_bit_representation__from_f64(x);
+  uint64_t bits = wuffs_base__ieee_754_bit_representation__from_f64_to_u64(x);
   bool neg = (bits >> 63) != 0;
   int32_t exp2 = ((int32_t)(bits >> 52)) & 0x7FF;
   uint64_t man = bits & 0x000FFFFFFFFFFFFFul;
@@ -11771,6 +12641,11 @@
     // 8     9     A     B     C     D     E     F
 };
 
+static const uint8_t wuffs_base__private_implementation__encode_base16[16] = {
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,  // 0x00 ..= 0x07.
+    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,  // 0x08 ..= 0x0F.
+};
+
 // --------
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__result_i64  //
@@ -12161,6 +13036,82 @@
   return o;
 }
 
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output  //
+wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
+                             wuffs_base__slice_u8 src,
+                             bool src_closed,
+                             uint32_t options) {
+  wuffs_base__transform__output o;
+  size_t dst_len2 = dst.len / 2;
+  size_t len;
+  if (dst_len2 < src.len) {
+    len = dst_len2;
+    o.status.repr = wuffs_base__suspension__short_write;
+  } else {
+    len = src.len;
+    if (!src_closed) {
+      o.status.repr = wuffs_base__suspension__short_read;
+    } else {
+      o.status.repr = NULL;
+    }
+  }
+
+  uint8_t* d = dst.ptr;
+  uint8_t* s = src.ptr;
+  size_t n = len;
+
+  while (n--) {
+    uint8_t c = *s;
+    d[0] = wuffs_base__private_implementation__encode_base16[c >> 4];
+    d[1] = wuffs_base__private_implementation__encode_base16[c & 0x0F];
+    d += 2;
+    s += 1;
+  }
+
+  o.num_dst = len * 2;
+  o.num_src = len;
+  return o;
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output  //
+wuffs_base__base_16__encode4(wuffs_base__slice_u8 dst,
+                             wuffs_base__slice_u8 src,
+                             bool src_closed,
+                             uint32_t options) {
+  wuffs_base__transform__output o;
+  size_t dst_len4 = dst.len / 4;
+  size_t len;
+  if (dst_len4 < src.len) {
+    len = dst_len4;
+    o.status.repr = wuffs_base__suspension__short_write;
+  } else {
+    len = src.len;
+    if (!src_closed) {
+      o.status.repr = wuffs_base__suspension__short_read;
+    } else {
+      o.status.repr = NULL;
+    }
+  }
+
+  uint8_t* d = dst.ptr;
+  uint8_t* s = src.ptr;
+  size_t n = len;
+
+  while (n--) {
+    uint8_t c = *s;
+    d[0] = '\\';
+    d[1] = 'x';
+    d[2] = wuffs_base__private_implementation__encode_base16[c >> 4];
+    d[3] = wuffs_base__private_implementation__encode_base16[c & 0x0F];
+    d += 4;
+    s += 1;
+  }
+
+  o.num_dst = len * 4;
+  o.num_src = len;
+  return o;
+}
+
 // ---------------- Base-64
 
 // The two base-64 alphabets, std and url, differ only in the last two codes.
@@ -14097,20 +15048,20 @@
 };
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output  //
-wuffs_base__utf_8__next(wuffs_base__slice_u8 s) {
-  if (s.len == 0) {
+wuffs_base__utf_8__next(const uint8_t* s_ptr, size_t s_len) {
+  if (s_len == 0) {
     return wuffs_base__make_utf_8__next__output(0, 0);
   }
-  uint32_t c = s.ptr[0];
+  uint32_t c = s_ptr[0];
   switch (wuffs_base__utf_8__byte_length_minus_1[c & 0xFF]) {
     case 0:
       return wuffs_base__make_utf_8__next__output(c, 1);
 
     case 1:
-      if (s.len < 2) {
+      if (s_len < 2) {
         break;
       }
-      c = wuffs_base__load_u16le__no_bounds_check(s.ptr);
+      c = wuffs_base__load_u16le__no_bounds_check(s_ptr);
       if ((c & 0xC000) != 0x8000) {
         break;
       }
@@ -14118,10 +15069,10 @@
       return wuffs_base__make_utf_8__next__output(c, 2);
 
     case 2:
-      if (s.len < 3) {
+      if (s_len < 3) {
         break;
       }
-      c = wuffs_base__load_u24le__no_bounds_check(s.ptr);
+      c = wuffs_base__load_u24le__no_bounds_check(s_ptr);
       if ((c & 0xC0C000) != 0x808000) {
         break;
       }
@@ -14133,10 +15084,10 @@
       return wuffs_base__make_utf_8__next__output(c, 3);
 
     case 3:
-      if (s.len < 4) {
+      if (s_len < 4) {
         break;
       }
-      c = wuffs_base__load_u32le__no_bounds_check(s.ptr);
+      c = wuffs_base__load_u32le__no_bounds_check(s_ptr);
       if ((c & 0xC0C0C000) != 0x80808000) {
         break;
       }
@@ -14153,16 +15104,16 @@
 }
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output  //
-wuffs_base__utf_8__next_from_end(wuffs_base__slice_u8 s) {
-  if (s.len == 0) {
+wuffs_base__utf_8__next_from_end(const uint8_t* s_ptr, size_t s_len) {
+  if (s_len == 0) {
     return wuffs_base__make_utf_8__next__output(0, 0);
   }
-  uint8_t* ptr = &s.ptr[s.len - 1];
+  const uint8_t* ptr = &s_ptr[s_len - 1];
   if (*ptr < 0x80) {
     return wuffs_base__make_utf_8__next__output(*ptr, 1);
 
   } else if (*ptr < 0xC0) {
-    uint8_t* too_far = &s.ptr[(s.len > 4) ? (s.len - 4) : 0];
+    const uint8_t* too_far = &s_ptr[(s_len > 4) ? (s_len - 4) : 0];
     uint32_t n = 1;
     while (ptr != too_far) {
       ptr--;
@@ -14172,8 +15123,7 @@
       } else if (*ptr < 0xC0) {
         continue;
       }
-      wuffs_base__utf_8__next__output o =
-          wuffs_base__utf_8__next(wuffs_base__make_slice_u8(ptr, n));
+      wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(ptr, n);
       if (o.byte_length != n) {
         break;
       }
@@ -14186,29 +15136,29 @@
 }
 
 WUFFS_BASE__MAYBE_STATIC size_t  //
-wuffs_base__utf_8__longest_valid_prefix(wuffs_base__slice_u8 s) {
+wuffs_base__utf_8__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) {
   // TODO: possibly optimize the all-ASCII case (4 or 8 bytes at a time).
   //
   // TODO: possibly optimize this by manually inlining the
   // wuffs_base__utf_8__next calls.
-  size_t original_len = s.len;
-  while (s.len > 0) {
-    wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(s);
+  size_t original_len = s_len;
+  while (s_len > 0) {
+    wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(s_ptr, s_len);
     if ((o.code_point > 0x7F) && (o.byte_length == 1)) {
       break;
     }
-    s.ptr += o.byte_length;
-    s.len -= o.byte_length;
+    s_ptr += o.byte_length;
+    s_len -= o.byte_length;
   }
-  return original_len - s.len;
+  return original_len - s_len;
 }
 
 WUFFS_BASE__MAYBE_STATIC size_t  //
-wuffs_base__ascii__longest_valid_prefix(wuffs_base__slice_u8 s) {
+wuffs_base__ascii__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) {
   // TODO: possibly optimize this by checking 4 or 8 bytes at a time.
-  uint8_t* original_ptr = s.ptr;
-  uint8_t* p = s.ptr;
-  uint8_t* q = s.ptr + s.len;
+  const uint8_t* original_ptr = s_ptr;
+  const uint8_t* p = s_ptr;
+  const uint8_t* q = s_ptr + s_len;
   for (; (p != q) && ((*p & 0x80) == 0); p++) {
   }
   return (size_t)(p - original_ptr);
@@ -15707,6 +16657,739 @@
 
 #endif  // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP)
 
+#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR)
+
+// ---------------- Status Codes Implementations
+
+const char wuffs_cbor__error__bad_input[] = "#cbor: bad input";
+const char wuffs_cbor__error__unsupported_recursion_depth[] = "#cbor: unsupported recursion depth";
+const char wuffs_cbor__error__internal_error_inconsistent_i_o[] = "#cbor: internal error: inconsistent I/O";
+const char wuffs_cbor__error__internal_error_inconsistent_token_length[] = "#cbor: internal error: inconsistent token length";
+
+// ---------------- Private Consts
+
+static const uint32_t
+WUFFS_CBOR__LITERALS[4]WUFFS_BASE__POTENTIALLY_UNUSED = {
+  8388612, 8388616, 8388610, 8388609,
+};
+
+static const uint8_t
+WUFFS_CBOR__TOKEN_LENGTHS[32]WUFFS_BASE__POTENTIALLY_UNUSED = {
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1,
+  2, 3, 5, 9, 0, 0, 0, 1,
+};
+
+// ---------------- Private Initializer Prototypes
+
+// ---------------- Private Function Prototypes
+
+// ---------------- VTables
+
+const wuffs_base__token_decoder__func_ptrs
+wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder = {
+  (wuffs_base__status(*)(void*,
+      wuffs_base__token_buffer*,
+      wuffs_base__io_buffer*,
+      wuffs_base__slice_u8))(&wuffs_cbor__decoder__decode_tokens),
+  (wuffs_base__empty_struct(*)(void*,
+      uint32_t,
+      bool))(&wuffs_cbor__decoder__set_quirk_enabled),
+  (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_cbor__decoder__workbuf_len),
+};
+
+// ---------------- Initializer Implementations
+
+wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
+wuffs_cbor__decoder__initialize(
+    wuffs_cbor__decoder* self,
+    size_t sizeof_star_self,
+    uint64_t wuffs_version,
+    uint32_t options){
+  if (!self) {
+    return wuffs_base__make_status(wuffs_base__error__bad_receiver);
+  }
+  if (sizeof(*self) != sizeof_star_self) {
+    return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
+  }
+  if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
+      (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
+    return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
+  }
+
+  if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
+    // The whole point of this if-check is to detect an uninitialized *self.
+    // We disable the warning on GCC. Clang-5.0 does not have this warning.
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+    if (self->private_impl.magic != 0) {
+      return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
+    }
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+  } else {
+    if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
+      memset(self, 0, sizeof(*self));
+      options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
+    } else {
+      memset(&(self->private_impl), 0, sizeof(self->private_impl));
+    }
+  }
+
+  self->private_impl.magic = WUFFS_BASE__MAGIC;
+  self->private_impl.vtable_for__wuffs_base__token_decoder.vtable_name =
+      wuffs_base__token_decoder__vtable_name;
+  self->private_impl.vtable_for__wuffs_base__token_decoder.function_pointers =
+      (const void*)(&wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder);
+  return wuffs_base__make_status(NULL);
+}
+
+wuffs_cbor__decoder*
+wuffs_cbor__decoder__alloc() {
+  wuffs_cbor__decoder* x =
+      (wuffs_cbor__decoder*)(calloc(sizeof(wuffs_cbor__decoder), 1));
+  if (!x) {
+    return NULL;
+  }
+  if (wuffs_cbor__decoder__initialize(
+      x, sizeof(wuffs_cbor__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
+    free(x);
+    return NULL;
+  }
+  return x;
+}
+
+size_t
+sizeof__wuffs_cbor__decoder() {
+  return sizeof(wuffs_cbor__decoder);
+}
+
+// ---------------- Function Implementations
+
+// -------- func cbor.decoder.set_quirk_enabled
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
+wuffs_cbor__decoder__set_quirk_enabled(
+    wuffs_cbor__decoder* self,
+    uint32_t a_quirk,
+    bool a_enabled) {
+  return wuffs_base__make_empty_struct();
+}
+
+// -------- func cbor.decoder.workbuf_len
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
+wuffs_cbor__decoder__workbuf_len(
+    const wuffs_cbor__decoder* self) {
+  if (!self) {
+    return wuffs_base__utility__empty_range_ii_u64();
+  }
+  if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+      (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+    return wuffs_base__utility__empty_range_ii_u64();
+  }
+
+  return wuffs_base__utility__empty_range_ii_u64();
+}
+
+// -------- func cbor.decoder.decode_tokens
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status
+wuffs_cbor__decoder__decode_tokens(
+    wuffs_cbor__decoder* self,
+    wuffs_base__token_buffer* a_dst,
+    wuffs_base__io_buffer* a_src,
+    wuffs_base__slice_u8 a_workbuf) {
+  if (!self) {
+    return wuffs_base__make_status(wuffs_base__error__bad_receiver);
+  }
+  if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+    return wuffs_base__make_status(
+        (self->private_impl.magic == WUFFS_BASE__DISABLED)
+        ? wuffs_base__error__disabled_by_previous_error
+        : wuffs_base__error__initialize_not_called);
+  }
+  if (!a_dst || !a_src) {
+    self->private_impl.magic = WUFFS_BASE__DISABLED;
+    return wuffs_base__make_status(wuffs_base__error__bad_argument);
+  }
+  if ((self->private_impl.active_coroutine != 0) &&
+      (self->private_impl.active_coroutine != 1)) {
+    self->private_impl.magic = WUFFS_BASE__DISABLED;
+    return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
+  }
+  self->private_impl.active_coroutine = 0;
+  wuffs_base__status status = wuffs_base__make_status(NULL);
+
+  uint64_t v_string_length = 0;
+  uint64_t v_n64 = 0;
+  uint32_t v_depth = 0;
+  uint32_t v_stack_byte = 0;
+  uint32_t v_stack_bit = 0;
+  uint32_t v_stack_val = 0;
+  uint32_t v_token_length = 0;
+  uint32_t v_vminor = 0;
+  uint32_t v_vminor_alt = 0;
+  uint32_t v_continued = 0;
+  uint8_t v_c = 0;
+  uint8_t v_c_major = 0;
+  uint8_t v_c_minor = 0;
+  bool v_tagged = false;
+  uint8_t v_indefinite_string_major_type = 0;
+
+  wuffs_base__token* iop_a_dst = NULL;
+  wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_dst) {
+    io0_a_dst = a_dst->data.ptr;
+    io1_a_dst = io0_a_dst + a_dst->meta.wi;
+    iop_a_dst = io1_a_dst;
+    io2_a_dst = io0_a_dst + a_dst->data.len;
+    if (a_dst->meta.closed) {
+      io2_a_dst = iop_a_dst;
+    }
+  }
+  const uint8_t* iop_a_src = NULL;
+  const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_src) {
+    io0_a_src = a_src->data.ptr;
+    io1_a_src = io0_a_src + a_src->meta.ri;
+    iop_a_src = io1_a_src;
+    io2_a_src = io0_a_src + a_src->meta.wi;
+  }
+
+  uint32_t coro_susp_point = self->private_impl.p_decode_tokens[0];
+  if (coro_susp_point) {
+    v_string_length = self->private_data.s_decode_tokens[0].v_string_length;
+    v_depth = self->private_data.s_decode_tokens[0].v_depth;
+    v_token_length = self->private_data.s_decode_tokens[0].v_token_length;
+    v_tagged = self->private_data.s_decode_tokens[0].v_tagged;
+    v_indefinite_string_major_type = self->private_data.s_decode_tokens[0].v_indefinite_string_major_type;
+  }
+  switch (coro_susp_point) {
+    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+    if (self->private_impl.f_end_of_data) {
+      status = wuffs_base__make_status(wuffs_base__note__end_of_data);
+      goto ok;
+    }
+    label__outer__continue:;
+    while (true) {
+      while (true) {
+        while (true) {
+          if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1) {
+            status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+            goto label__outer__continue;
+          }
+          if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
+            if (a_src && a_src->meta.closed) {
+              status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
+              goto exit;
+            }
+            status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
+            goto label__outer__continue;
+          }
+          v_c = wuffs_base__load_u8be__no_bounds_check(iop_a_src);
+          if ((v_indefinite_string_major_type != 0) && (v_indefinite_string_major_type != (v_c >> 5))) {
+            if (v_c != 255) {
+              status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
+              goto exit;
+            }
+            v_vminor = 4194560;
+            if (v_indefinite_string_major_type == 3) {
+              v_vminor |= 19;
+            }
+            v_indefinite_string_major_type = 0;
+            (iop_a_src += 1, wuffs_base__make_empty_struct());
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            goto label__goto_parsed_a_leaf_value__break;
+          }
+          (iop_a_src += 1, wuffs_base__make_empty_struct());
+          v_c_major = ((uint8_t)((v_c >> 5)));
+          v_c_minor = (v_c & 31);
+          if (v_c_minor < 24) {
+            v_string_length = ((uint64_t)(v_c_minor));
+          } else {
+            while (true) {
+              if (v_c_minor == 24) {
+                if (((uint64_t)(io2_a_src - iop_a_src)) >= 1) {
+                  v_string_length = ((uint64_t)(wuffs_base__load_u8be__no_bounds_check(iop_a_src)));
+                  (iop_a_src += 1, wuffs_base__make_empty_struct());
+                  goto label__goto_have_string_length__break;
+                }
+              } else if (v_c_minor == 25) {
+                if (((uint64_t)(io2_a_src - iop_a_src)) >= 2) {
+                  v_string_length = ((uint64_t)(wuffs_base__load_u16be__no_bounds_check(iop_a_src)));
+                  (iop_a_src += 2, wuffs_base__make_empty_struct());
+                  goto label__goto_have_string_length__break;
+                }
+              } else if (v_c_minor == 26) {
+                if (((uint64_t)(io2_a_src - iop_a_src)) >= 4) {
+                  v_string_length = ((uint64_t)(wuffs_base__load_u32be__no_bounds_check(iop_a_src)));
+                  (iop_a_src += 4, wuffs_base__make_empty_struct());
+                  goto label__goto_have_string_length__break;
+                }
+              } else if (v_c_minor == 27) {
+                if (((uint64_t)(io2_a_src - iop_a_src)) >= 8) {
+                  v_string_length = wuffs_base__load_u64be__no_bounds_check(iop_a_src);
+                  (iop_a_src += 8, wuffs_base__make_empty_struct());
+                  goto label__goto_have_string_length__break;
+                }
+              } else {
+                v_string_length = 0;
+                goto label__goto_have_string_length__break;
+              }
+              if (iop_a_src > io1_a_src) {
+                (iop_a_src--, wuffs_base__make_empty_struct());
+                if (a_src && a_src->meta.closed) {
+                  status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
+                  goto exit;
+                }
+                status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
+                v_c_major = 0;
+                v_c_minor = 0;
+                goto label__outer__continue;
+              }
+              status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o);
+              goto exit;
+            }
+            label__goto_have_string_length__break:;
+          }
+          if (v_c_major == 0) {
+            if (v_c_minor < 26) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)((14680064 | ((uint32_t)((v_string_length & 65535)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            } else if (v_c_minor < 28) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)((14680064 | ((uint32_t)((v_string_length >> 46)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                  (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (~(v_string_length & 70368744177663) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) |
+                  (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            }
+          } else if (v_c_major == 1) {
+            if (v_c_minor < 26) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)((12582912 | (2097151 - ((uint32_t)((v_string_length & 65535))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            } else if (v_c_minor < 28) {
+              if (v_string_length < 9223372036854775808u) {
+                *iop_a_dst++ = wuffs_base__make_token(
+                    (((uint64_t)((12582912 | (2097151 - ((uint32_t)((v_string_length >> 46))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                    (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                    (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                *iop_a_dst++ = wuffs_base__make_token(
+                    (~((18446744073709551615u - v_string_length) & 70368744177663) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) |
+                    (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              } else {
+                *iop_a_dst++ = wuffs_base__make_token(
+                    (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
+                    (((uint64_t)(16777216)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                    (((uint64_t)(9)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              }
+              goto label__goto_parsed_a_leaf_value__break;
+            }
+          } else if (v_c_major == 2) {
+            if (v_c_minor == 0) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(4194560)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            } else if (v_c_minor < 28) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(4194560)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                  (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            } else if (v_c_minor == 31) {
+              if (v_indefinite_string_major_type != 0) {
+                goto label__goto_fail__break;
+              }
+              v_indefinite_string_major_type = 2;
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(4194560)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__outer__continue;
+            } else {
+              goto label__goto_fail__break;
+            }
+            label__0__continue:;
+            while (true) {
+              if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+                status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
+                goto label__0__continue;
+              }
+              v_n64 = wuffs_base__u64__min(v_string_length, ((uint64_t)(io2_a_src - iop_a_src)));
+              v_token_length = ((uint32_t)((v_n64 & 65535)));
+              if (v_n64 > 65535) {
+                v_token_length = 65535;
+              } else if (v_token_length <= 0) {
+                if (a_src && a_src->meta.closed) {
+                  status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
+                  goto exit;
+                }
+                status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
+                goto label__0__continue;
+              }
+              if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) {
+                status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length);
+                goto exit;
+              }
+              v_string_length -= ((uint64_t)(v_token_length));
+              v_continued = 0;
+              if ((v_string_length > 0) || (v_indefinite_string_major_type > 0)) {
+                v_continued = 1;
+              }
+              (iop_a_src += v_token_length, wuffs_base__make_empty_struct());
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(4194816)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                  (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              if (v_string_length > 0) {
+                goto label__0__continue;
+              } else if (v_indefinite_string_major_type > 0) {
+                goto label__outer__continue;
+              }
+              goto label__goto_parsed_a_leaf_value__break;
+            }
+          } else if (v_c_major == 3) {
+            if (v_c_minor == 0) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            } else if (v_c_minor < 28) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                  (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            } else if (v_c_minor == 31) {
+              if (v_indefinite_string_major_type != 0) {
+                goto label__goto_fail__break;
+              }
+              v_indefinite_string_major_type = 3;
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__outer__continue;
+            } else {
+              goto label__goto_fail__break;
+            }
+            label__1__continue:;
+            while (true) {
+              if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+                status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
+                goto label__1__continue;
+              }
+              v_n64 = wuffs_base__u64__min(v_string_length, 65535);
+              v_n64 = ((uint64_t)(wuffs_base__utf_8__longest_valid_prefix(iop_a_src,
+                  ((size_t)(wuffs_base__u64__min(((uint64_t)(io2_a_src - iop_a_src)), v_n64))))));
+              v_token_length = ((uint32_t)((v_n64 & 65535)));
+              if (v_token_length <= 0) {
+                if ((a_src && a_src->meta.closed) || (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
+                  status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
+                  goto exit;
+                }
+                status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
+                goto label__1__continue;
+              }
+              if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) {
+                status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length);
+                goto exit;
+              }
+              v_string_length -= ((uint64_t)(v_token_length));
+              v_continued = 0;
+              if ((v_string_length > 0) || (v_indefinite_string_major_type > 0)) {
+                v_continued = 1;
+              }
+              (iop_a_src += v_token_length, wuffs_base__make_empty_struct());
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                  (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              if (v_string_length > 0) {
+                goto label__1__continue;
+              } else if (v_indefinite_string_major_type > 0) {
+                goto label__outer__continue;
+              }
+              goto label__goto_parsed_a_leaf_value__break;
+            }
+          } else if (v_c_major == 4) {
+            if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0) {
+              goto label__goto_fail__break;
+            } else if (v_depth >= 1024) {
+              status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth);
+              goto exit;
+            }
+            v_vminor = 2105361;
+            v_vminor_alt = 2101282;
+            if (v_depth > 0) {
+              v_stack_byte = ((v_depth - 1) / 16);
+              v_stack_bit = (((v_depth - 1) & 15) * 2);
+              if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
+                v_vminor = 2105377;
+                v_vminor_alt = 2105378;
+              } else {
+                v_vminor = 2105409;
+                v_vminor_alt = 2113570;
+              }
+            }
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            if (v_c_minor == 0) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            }
+            v_stack_byte = (v_depth / 16);
+            v_stack_bit = ((v_depth & 15) * 2);
+            self->private_data.f_stack[v_stack_byte] &= (4294967295 ^ (((uint32_t)(3)) << v_stack_bit));
+            self->private_data.f_container_num_remaining[v_depth] = v_string_length;
+            v_depth += 1;
+            v_tagged = false;
+            goto label__outer__continue;
+          } else if (v_c_major == 5) {
+            if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0) {
+              goto label__goto_fail__break;
+            } else if (v_depth >= 1024) {
+              status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth);
+              goto exit;
+            }
+            v_vminor = 2113553;
+            v_vminor_alt = 2101314;
+            if (v_depth > 0) {
+              v_stack_byte = ((v_depth - 1) / 16);
+              v_stack_bit = (((v_depth - 1) & 15) * 2);
+              if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
+                v_vminor = 2113569;
+                v_vminor_alt = 2105410;
+              } else {
+                v_vminor = 2113601;
+                v_vminor_alt = 2113602;
+              }
+            }
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            if (v_c_minor == 0) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            }
+            v_stack_byte = (v_depth / 16);
+            v_stack_bit = ((v_depth & 15) * 2);
+            self->private_data.f_stack[v_stack_byte] |= (((uint32_t)(3)) << v_stack_bit);
+            self->private_data.f_container_num_remaining[v_depth] = v_string_length;
+            v_depth += 1;
+            v_tagged = false;
+            goto label__outer__continue;
+          } else if (v_c_major == 6) {
+            if (v_c_minor >= 28) {
+              goto label__goto_fail__break;
+            }
+            if (v_string_length < 262144) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
+                  (((uint64_t)((4194304 | ((uint32_t)(v_string_length))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            } else {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
+                  (((uint64_t)((4194304 | ((uint32_t)((v_string_length >> 46)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                  (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (~(v_string_length & 70368744177663) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) |
+                  (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            }
+            v_tagged = true;
+            goto label__outer__continue;
+          } else if (v_c_major == 7) {
+            if (v_c_minor < 20) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
+                  (((uint64_t)((8388608 | ((uint32_t)((v_string_length & 255)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            } else if (v_c_minor < 24) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(WUFFS_CBOR__LITERALS[(v_c_minor & 3)])) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            } else if (v_c_minor == 24) {
+              if (v_string_length < 24) {
+                if ( ! (iop_a_src > io1_a_src)) {
+                  status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o);
+                  goto exit;
+                }
+                (iop_a_src--, wuffs_base__make_empty_struct());
+                goto label__goto_fail__break;
+              }
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
+                  (((uint64_t)((8388608 | ((uint32_t)((v_string_length & 255)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            } else if (v_c_minor < 28) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(10490113)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            } else if (v_c_minor == 31) {
+              if (v_tagged || (v_depth <= 0)) {
+                goto label__goto_fail__break;
+              }
+              v_depth -= 1;
+              if (self->private_data.f_container_num_remaining[v_depth] != 0) {
+                goto label__goto_fail__break;
+              }
+              v_stack_byte = (v_depth / 16);
+              v_stack_bit = ((v_depth & 15) * 2);
+              v_stack_val = (3 & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit));
+              if (v_stack_val == 1) {
+                goto label__goto_fail__break;
+              }
+              if (v_stack_val != 3) {
+                v_vminor_alt = 2097186;
+              } else {
+                v_vminor_alt = 2097218;
+              }
+              if (v_depth <= 0) {
+                v_vminor_alt |= 4096;
+              } else {
+                v_stack_byte = ((v_depth - 1) / 16);
+                v_stack_bit = (((v_depth - 1) & 15) * 2);
+                if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
+                  v_vminor_alt |= 8192;
+                } else {
+                  v_vminor_alt |= 16384;
+                }
+              }
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              goto label__goto_parsed_a_leaf_value__break;
+            }
+          }
+          goto label__goto_fail__break;
+        }
+        label__goto_fail__break:;
+        if (iop_a_src > io1_a_src) {
+          (iop_a_src--, wuffs_base__make_empty_struct());
+          status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
+          goto exit;
+        }
+        status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o);
+        goto exit;
+      }
+      label__goto_parsed_a_leaf_value__break:;
+      v_tagged = false;
+      while (v_depth > 0) {
+        v_stack_byte = ((v_depth - 1) / 16);
+        v_stack_bit = (((v_depth - 1) & 15) * 2);
+        self->private_data.f_stack[v_stack_byte] ^= (((uint32_t)(1)) << (v_stack_bit + 1));
+        if (1 == (3 & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit))) {
+          goto label__outer__continue;
+        }
+        if (self->private_data.f_container_num_remaining[(v_depth - 1)] <= 0) {
+          goto label__outer__continue;
+        }
+        self->private_data.f_container_num_remaining[(v_depth - 1)] -= 1;
+        if (self->private_data.f_container_num_remaining[(v_depth - 1)] > 0) {
+          goto label__outer__continue;
+        }
+        label__2__continue:;
+        while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+          status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+          WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
+          goto label__2__continue;
+        }
+        v_depth -= 1;
+        v_stack_byte = (v_depth / 16);
+        v_stack_bit = ((v_depth & 15) * 2);
+        if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
+          v_vminor_alt = 2097186;
+        } else {
+          v_vminor_alt = 2097218;
+        }
+        if (v_depth <= 0) {
+          v_vminor_alt |= 4096;
+        } else {
+          v_stack_byte = ((v_depth - 1) / 16);
+          v_stack_bit = (((v_depth - 1) & 15) * 2);
+          if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
+            v_vminor_alt |= 8192;
+          } else {
+            v_vminor_alt |= 16384;
+          }
+        }
+        *iop_a_dst++ = wuffs_base__make_token(
+            (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+            (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+      }
+      goto label__outer__break;
+    }
+    label__outer__break:;
+    self->private_impl.f_end_of_data = true;
+
+    goto ok;
+    ok:
+    self->private_impl.p_decode_tokens[0] = 0;
+    goto exit;
+  }
+
+  goto suspend;
+  suspend:
+  self->private_impl.p_decode_tokens[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+  self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
+  self->private_data.s_decode_tokens[0].v_string_length = v_string_length;
+  self->private_data.s_decode_tokens[0].v_depth = v_depth;
+  self->private_data.s_decode_tokens[0].v_token_length = v_token_length;
+  self->private_data.s_decode_tokens[0].v_tagged = v_tagged;
+  self->private_data.s_decode_tokens[0].v_indefinite_string_major_type = v_indefinite_string_major_type;
+
+  goto exit;
+  exit:
+  if (a_dst) {
+    a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+  }
+  if (a_src) {
+    a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+  }
+
+  if (wuffs_base__status__is_error(&status)) {
+    self->private_impl.magic = WUFFS_BASE__DISABLED;
+  }
+  return status;
+}
+
+#endif  // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR)
+
 #if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32)
 
 // ---------------- Status Codes Implementations
@@ -23788,6 +25471,7 @@
 const char wuffs_json__error__bad_utf_8[] = "#json: bad UTF-8";
 const char wuffs_json__error__bad_backslash_escape[] = "#json: bad backslash-escape";
 const char wuffs_json__error__bad_input[] = "#json: bad input";
+const char wuffs_json__error__bad_quirk_combination[] = "#json: bad quirk combination";
 const char wuffs_json__error__unsupported_number_length[] = "#json: unsupported number length";
 const char wuffs_json__error__unsupported_recursion_depth[] = "#json: unsupported recursion depth";
 const char wuffs_json__error__internal_error_inconsistent_i_o[] = "#json: internal error: inconsistent I/O";
@@ -23834,7 +25518,7 @@
 
 static const uint8_t
 WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_QUIRKS[8]WUFFS_BASE__POTENTIALLY_UNUSED = {
-  0, 1, 3, 4, 5, 6, 7, 9,
+  0, 1, 3, 4, 5, 6, 7, 10,
 };
 
 static const uint8_t
@@ -24030,7 +25714,7 @@
 
 #define WUFFS_JSON__QUIRKS_BASE 1225364480
 
-#define WUFFS_JSON__QUIRKS_COUNT 18
+#define WUFFS_JSON__QUIRKS_COUNT 20
 
 // ---------------- Private Initializer Prototypes
 
@@ -24172,7 +25856,7 @@
 
   if (a_quirk >= 1225364480) {
     a_quirk -= 1225364480;
-    if (a_quirk < 18) {
+    if (a_quirk < 20) {
       self->private_impl.f_quirks[a_quirk] = a_enabled;
     }
   }
@@ -24241,6 +25925,7 @@
   uint32_t v_multi_byte_utf8 = 0;
   uint32_t v_backslash_x_length = 0;
   uint8_t v_backslash_x_ok = 0;
+  uint8_t v_backslash_x_value = 0;
   uint32_t v_backslash_x_string = 0;
   uint8_t v_uni4_ok = 0;
   uint64_t v_uni4_string = 0;
@@ -24289,7 +25974,7 @@
       status = wuffs_base__make_status(wuffs_base__note__end_of_data);
       goto ok;
     }
-    if (self->private_impl.f_quirks[14] || self->private_impl.f_quirks[15]) {
+    if (self->private_impl.f_quirks[15] || self->private_impl.f_quirks[16]) {
       if (a_dst) {
         a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
       }
@@ -24308,6 +25993,15 @@
         goto suspend;
       }
     }
+    if (self->private_impl.f_quirks[8]) {
+      if (self->private_impl.f_quirks[9]) {
+        status = wuffs_base__make_status(wuffs_json__error__bad_quirk_combination);
+        goto exit;
+      }
+      self->private_impl.f_string_value_minor = 4194304;
+    } else {
+      self->private_impl.f_string_value_minor = 4194306;
+    }
     v_expect = 7858;
     label__outer__continue:;
     while (true) {
@@ -24368,7 +26062,10 @@
         }
         if (v_class == 1) {
           *iop_a_dst++ = wuffs_base__make_token(
-              (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+              (((uint64_t)((self->private_impl.f_string_value_minor |
+              1 |
+              16 |
+              256))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
               (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
               (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
           (iop_a_src += 1, wuffs_base__make_empty_struct());
@@ -24385,7 +26082,7 @@
               if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
                 if (v_string_length > 0) {
                   *iop_a_dst++ = wuffs_base__make_token(
-                      (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                      (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                       (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                       (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                   v_string_length = 0;
@@ -24410,7 +26107,7 @@
                 (iop_a_src += 4, wuffs_base__make_empty_struct());
                 if (v_string_length > 65527) {
                   *iop_a_dst++ = wuffs_base__make_token(
-                      (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                      (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                       (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                       (((uint64_t)((v_string_length + 4))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                   v_string_length = 0;
@@ -24425,7 +26122,7 @@
                 (iop_a_src += 1, wuffs_base__make_empty_struct());
                 if (v_string_length >= 65531) {
                   *iop_a_dst++ = wuffs_base__make_token(
-                      (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                      (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                       (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                       (((uint64_t)(65532)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                   v_string_length = 0;
@@ -24436,7 +26133,7 @@
               } else if (v_char == 1) {
                 if (v_string_length != 0) {
                   *iop_a_dst++ = wuffs_base__make_token(
-                      (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                      (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                       (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                       (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                   v_string_length = 0;
@@ -24445,7 +26142,7 @@
               } else if (v_char == 2) {
                 if (v_string_length > 0) {
                   *iop_a_dst++ = wuffs_base__make_token(
-                      (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                      (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                       (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                       (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                   v_string_length = 0;
@@ -24521,7 +26218,7 @@
                   } else {
                     if (((uint64_t)(io2_a_src - iop_a_src)) < 12) {
                       if (a_src && a_src->meta.closed) {
-                        if (self->private_impl.f_quirks[17]) {
+                        if (self->private_impl.f_quirks[19]) {
                           (iop_a_src += 6, wuffs_base__make_empty_struct());
                           *iop_a_dst++ = wuffs_base__make_token(
                               (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
@@ -24572,7 +26269,7 @@
                       goto label__string_loop_outer__continue;
                     }
                   }
-                  if (self->private_impl.f_quirks[17]) {
+                  if (self->private_impl.f_quirks[19]) {
                     if (((uint64_t)(io2_a_src - iop_a_src)) < 6) {
                       status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
                       goto exit;
@@ -24631,7 +26328,7 @@
                         (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                         (((uint64_t)(10)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                     goto label__string_loop_outer__continue;
-                  } else if (self->private_impl.f_quirks[17]) {
+                  } else if (self->private_impl.f_quirks[19]) {
                     (iop_a_src += 10, wuffs_base__make_empty_struct());
                     *iop_a_dst++ = wuffs_base__make_token(
                         (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
@@ -24639,42 +26336,74 @@
                         (((uint64_t)(10)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                     goto label__string_loop_outer__continue;
                   }
-                } else if ((v_c == 120) && self->private_impl.f_quirks[8]) {
-                  if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
-                    if (a_src && a_src->meta.closed) {
-                      status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
-                      goto exit;
+                } else if (v_c == 120) {
+                  if (self->private_impl.f_quirks[9]) {
+                    if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
+                      if (a_src && a_src->meta.closed) {
+                        status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
+                        goto exit;
+                      }
+                      status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+                      WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
+                      v_string_length = 0;
+                      v_char = 0;
+                      goto label__string_loop_outer__continue;
                     }
-                    status = wuffs_base__make_status(wuffs_base__suspension__short_read);
-                    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
-                    v_string_length = 0;
-                    v_char = 0;
-                    goto label__string_loop_outer__continue;
-                  }
-                  v_backslash_x_length = 0;
-                  while ((v_backslash_x_length <= 65531) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
                     v_backslash_x_string = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
                     v_backslash_x_ok = 128;
                     v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_backslash_x_string >> 16))];
                     v_backslash_x_ok &= v_c;
+                    v_backslash_x_value = ((uint8_t)(((v_c & 15) << 4)));
                     v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_backslash_x_string >> 24))];
                     v_backslash_x_ok &= v_c;
+                    v_backslash_x_value = ((uint8_t)((v_backslash_x_value | (v_c & 15))));
                     if ((v_backslash_x_ok == 0) || ((v_backslash_x_string & 65535) != 30812)) {
-                      goto label__1__break;
+                      status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
+                      goto exit;
                     }
                     (iop_a_src += 4, wuffs_base__make_empty_struct());
-                    v_backslash_x_length += 4;
+                    *iop_a_dst++ = wuffs_base__make_token(
+                        (((uint64_t)((6291456 | ((uint32_t)(v_backslash_x_value))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                        (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                    goto label__string_loop_outer__continue;
+                  } else if (self->private_impl.f_quirks[8]) {
+                    if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
+                      if (a_src && a_src->meta.closed) {
+                        status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
+                        goto exit;
+                      }
+                      status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+                      WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
+                      v_string_length = 0;
+                      v_char = 0;
+                      goto label__string_loop_outer__continue;
+                    }
+                    v_backslash_x_length = 0;
+                    while ((v_backslash_x_length <= 65531) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
+                      v_backslash_x_string = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+                      v_backslash_x_ok = 128;
+                      v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_backslash_x_string >> 16))];
+                      v_backslash_x_ok &= v_c;
+                      v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_backslash_x_string >> 24))];
+                      v_backslash_x_ok &= v_c;
+                      if ((v_backslash_x_ok == 0) || ((v_backslash_x_string & 65535) != 30812)) {
+                        goto label__1__break;
+                      }
+                      (iop_a_src += 4, wuffs_base__make_empty_struct());
+                      v_backslash_x_length += 4;
+                    }
+                    label__1__break:;
+                    if (v_backslash_x_length == 0) {
+                      status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
+                      goto exit;
+                    }
+                    *iop_a_dst++ = wuffs_base__make_token(
+                        (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 2048))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                        (((uint64_t)(v_backslash_x_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                    goto label__string_loop_outer__continue;
                   }
-                  label__1__break:;
-                  if (v_backslash_x_length == 0) {
-                    status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
-                    goto exit;
-                  }
-                  *iop_a_dst++ = wuffs_base__make_token(
-                      (((uint64_t)(4196355)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
-                      (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
-                      (((uint64_t)(v_backslash_x_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-                  goto label__string_loop_outer__continue;
                 }
                 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
                 goto exit;
@@ -24682,7 +26411,7 @@
                 if (((uint64_t)(io2_a_src - iop_a_src)) < 2) {
                   if (v_string_length > 0) {
                     *iop_a_dst++ = wuffs_base__make_token(
-                        (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                         (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                         (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                     v_string_length = 0;
@@ -24691,52 +26420,7 @@
                     }
                   }
                   if (a_src && a_src->meta.closed) {
-                    if (self->private_impl.f_quirks[17]) {
-                      *iop_a_dst++ = wuffs_base__make_token(
-                          (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
-                          (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
-                          (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-                      (iop_a_src += 1, wuffs_base__make_empty_struct());
-                      goto label__string_loop_outer__continue;
-                    }
-                    status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
-                    goto exit;
-                  }
-                  status = wuffs_base__make_status(wuffs_base__suspension__short_read);
-                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
-                  v_string_length = 0;
-                  v_char = 0;
-                  goto label__string_loop_outer__continue;
-                }
-                v_multi_byte_utf8 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
-                if ((v_multi_byte_utf8 & 49152) == 32768) {
-                  v_multi_byte_utf8 = ((1984 & (v_multi_byte_utf8 << 6)) | (63 & (v_multi_byte_utf8 >> 8)));
-                  (iop_a_src += 2, wuffs_base__make_empty_struct());
-                  if (v_string_length >= 65528) {
-                    *iop_a_dst++ = wuffs_base__make_token(
-                        (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
-                        (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
-                        (((uint64_t)((v_string_length + 2))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-                    v_string_length = 0;
-                    goto label__string_loop_outer__continue;
-                  }
-                  v_string_length += 2;
-                  goto label__string_loop_inner__continue;
-                }
-              } else if (v_char == 4) {
-                if (((uint64_t)(io2_a_src - iop_a_src)) < 3) {
-                  if (v_string_length > 0) {
-                    *iop_a_dst++ = wuffs_base__make_token(
-                        (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
-                        (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
-                        (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-                    v_string_length = 0;
-                    if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
-                      goto label__string_loop_outer__continue;
-                    }
-                  }
-                  if (a_src && a_src->meta.closed) {
-                    if (self->private_impl.f_quirks[17]) {
+                    if (self->private_impl.f_quirks[19]) {
                       *iop_a_dst++ = wuffs_base__make_token(
                           (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                           (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
@@ -24753,28 +26437,26 @@
                   v_char = 0;
                   goto label__string_loop_outer__continue;
                 }
-                v_multi_byte_utf8 = ((uint32_t)(wuffs_base__load_u24le__no_bounds_check(iop_a_src)));
-                if ((v_multi_byte_utf8 & 12632064) == 8421376) {
-                  v_multi_byte_utf8 = ((61440 & (v_multi_byte_utf8 << 12)) | (4032 & (v_multi_byte_utf8 >> 2)) | (63 & (v_multi_byte_utf8 >> 16)));
-                  if ((2047 < v_multi_byte_utf8) && ((v_multi_byte_utf8 < 55296) || (57343 < v_multi_byte_utf8))) {
-                    (iop_a_src += 3, wuffs_base__make_empty_struct());
-                    if (v_string_length >= 65528) {
-                      *iop_a_dst++ = wuffs_base__make_token(
-                          (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
-                          (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
-                          (((uint64_t)((v_string_length + 3))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-                      v_string_length = 0;
-                      goto label__string_loop_outer__continue;
-                    }
-                    v_string_length += 3;
-                    goto label__string_loop_inner__continue;
+                v_multi_byte_utf8 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
+                if ((v_multi_byte_utf8 & 49152) == 32768) {
+                  v_multi_byte_utf8 = ((1984 & (v_multi_byte_utf8 << 6)) | (63 & (v_multi_byte_utf8 >> 8)));
+                  (iop_a_src += 2, wuffs_base__make_empty_struct());
+                  if (v_string_length >= 65528) {
+                    *iop_a_dst++ = wuffs_base__make_token(
+                        (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                        (((uint64_t)((v_string_length + 2))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                    v_string_length = 0;
+                    goto label__string_loop_outer__continue;
                   }
+                  v_string_length += 2;
+                  goto label__string_loop_inner__continue;
                 }
-              } else if (v_char == 5) {
-                if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
+              } else if (v_char == 4) {
+                if (((uint64_t)(io2_a_src - iop_a_src)) < 3) {
                   if (v_string_length > 0) {
                     *iop_a_dst++ = wuffs_base__make_token(
-                        (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                         (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                         (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                     v_string_length = 0;
@@ -24783,7 +26465,7 @@
                     }
                   }
                   if (a_src && a_src->meta.closed) {
-                    if (self->private_impl.f_quirks[17]) {
+                    if (self->private_impl.f_quirks[19]) {
                       *iop_a_dst++ = wuffs_base__make_token(
                           (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                           (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
@@ -24800,6 +26482,53 @@
                   v_char = 0;
                   goto label__string_loop_outer__continue;
                 }
+                v_multi_byte_utf8 = ((uint32_t)(wuffs_base__load_u24le__no_bounds_check(iop_a_src)));
+                if ((v_multi_byte_utf8 & 12632064) == 8421376) {
+                  v_multi_byte_utf8 = ((61440 & (v_multi_byte_utf8 << 12)) | (4032 & (v_multi_byte_utf8 >> 2)) | (63 & (v_multi_byte_utf8 >> 16)));
+                  if ((2047 < v_multi_byte_utf8) && ((v_multi_byte_utf8 < 55296) || (57343 < v_multi_byte_utf8))) {
+                    (iop_a_src += 3, wuffs_base__make_empty_struct());
+                    if (v_string_length >= 65528) {
+                      *iop_a_dst++ = wuffs_base__make_token(
+                          (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                          (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                          (((uint64_t)((v_string_length + 3))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                      v_string_length = 0;
+                      goto label__string_loop_outer__continue;
+                    }
+                    v_string_length += 3;
+                    goto label__string_loop_inner__continue;
+                  }
+                }
+              } else if (v_char == 5) {
+                if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
+                  if (v_string_length > 0) {
+                    *iop_a_dst++ = wuffs_base__make_token(
+                        (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                        (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                    v_string_length = 0;
+                    if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+                      goto label__string_loop_outer__continue;
+                    }
+                  }
+                  if (a_src && a_src->meta.closed) {
+                    if (self->private_impl.f_quirks[19]) {
+                      *iop_a_dst++ = wuffs_base__make_token(
+                          (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                          (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
+                          (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                      (iop_a_src += 1, wuffs_base__make_empty_struct());
+                      goto label__string_loop_outer__continue;
+                    }
+                    status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
+                    goto exit;
+                  }
+                  status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14);
+                  v_string_length = 0;
+                  v_char = 0;
+                  goto label__string_loop_outer__continue;
+                }
                 v_multi_byte_utf8 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
                 if ((v_multi_byte_utf8 & 3233857536) == 2155905024) {
                   v_multi_byte_utf8 = ((1835008 & (v_multi_byte_utf8 << 18)) |
@@ -24810,7 +26539,7 @@
                     (iop_a_src += 4, wuffs_base__make_empty_struct());
                     if (v_string_length >= 65528) {
                       *iop_a_dst++ = wuffs_base__make_token(
-                          (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                          (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                           (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                           (((uint64_t)((v_string_length + 4))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                       v_string_length = 0;
@@ -24823,7 +26552,7 @@
               }
               if (v_string_length > 0) {
                 *iop_a_dst++ = wuffs_base__make_token(
-                    (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                    (((uint64_t)((self->private_impl.f_string_value_minor | 1 | 512))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                     (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
                     (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                 v_string_length = 0;
@@ -24843,7 +26572,7 @@
                 status = wuffs_base__make_status(wuffs_json__error__bad_c0_control_code);
                 goto exit;
               }
-              if (self->private_impl.f_quirks[17]) {
+              if (self->private_impl.f_quirks[19]) {
                 *iop_a_dst++ = wuffs_base__make_token(
                     (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                     (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
@@ -24864,17 +26593,20 @@
                 goto exit;
               }
               status = wuffs_base__make_status(wuffs_base__suspension__short_read);
-              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14);
+              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15);
               goto label__2__continue;
             }
             if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
               status = wuffs_base__make_status(wuffs_base__suspension__short_write);
-              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15);
+              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(16);
               goto label__2__continue;
             }
             (iop_a_src += 1, wuffs_base__make_empty_struct());
             *iop_a_dst++ = wuffs_base__make_token(
-                (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)((self->private_impl.f_string_value_minor |
+                1 |
+                16 |
+                256))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
             goto label__2__break;
           }
@@ -24890,13 +26622,13 @@
               (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
               (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
           if (0 == (v_expect & (((uint32_t)(1)) << 8))) {
-            if (self->private_impl.f_quirks[12]) {
+            if (self->private_impl.f_quirks[13]) {
               v_expect = 4162;
             } else {
               v_expect = 4098;
             }
           } else {
-            if (self->private_impl.f_quirks[12]) {
+            if (self->private_impl.f_quirks[13]) {
               v_expect = 8114;
             } else {
               v_expect = 7858;
@@ -24941,14 +26673,14 @@
               }
             }
             if (v_number_status == 1) {
-              if (self->private_impl.f_quirks[13]) {
+              if (self->private_impl.f_quirks[14]) {
                 if (a_dst) {
                   a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
                 }
                 if (a_src) {
                   a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
                 }
-                WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17);
                 status = wuffs_json__decoder__decode_inf_nan(self, a_dst, a_src);
                 if (a_dst) {
                   iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
@@ -24968,10 +26700,10 @@
               goto exit;
             } else {
               status = wuffs_base__make_status(wuffs_base__suspension__short_read);
-              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(17);
+              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(18);
               while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
                 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
-                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(18);
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(19);
               }
             }
           }
@@ -25087,7 +26819,7 @@
             goto label__goto_parsed_a_leaf_value__break;
           } else if (v_match == 1) {
             status = wuffs_base__make_status(wuffs_base__suspension__short_read);
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(19);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(20);
             goto label__outer__continue;
           }
         } else if (v_class == 10) {
@@ -25104,7 +26836,7 @@
             goto label__goto_parsed_a_leaf_value__break;
           } else if (v_match == 1) {
             status = wuffs_base__make_status(wuffs_base__suspension__short_read);
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(20);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(21);
             goto label__outer__continue;
           }
         } else if (v_class == 11) {
@@ -25121,17 +26853,17 @@
             goto label__goto_parsed_a_leaf_value__break;
           } else if (v_match == 1) {
             status = wuffs_base__make_status(wuffs_base__suspension__short_read);
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(21);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(22);
             goto label__outer__continue;
           }
-          if (self->private_impl.f_quirks[13]) {
+          if (self->private_impl.f_quirks[14]) {
             if (a_dst) {
               a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
             }
             if (a_src) {
               a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
             }
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23);
             status = wuffs_json__decoder__decode_inf_nan(self, a_dst, a_src);
             if (a_dst) {
               iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
@@ -25145,14 +26877,14 @@
             goto label__goto_parsed_a_leaf_value__break;
           }
         } else if (v_class == 12) {
-          if (self->private_impl.f_quirks[10] || self->private_impl.f_quirks[11]) {
+          if (self->private_impl.f_quirks[11] || self->private_impl.f_quirks[12]) {
             if (a_dst) {
               a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
             }
             if (a_src) {
               a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
             }
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24);
             status = wuffs_json__decoder__decode_comment(self, a_dst, a_src);
             if (a_dst) {
               iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
@@ -25176,14 +26908,14 @@
       v_expect = v_expect_after_value;
     }
     label__outer__break:;
-    if (self->private_impl.f_quirks[16]) {
+    if (self->private_impl.f_quirks[17]) {
       if (a_dst) {
         a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
       }
       if (a_src) {
         a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
       }
-      WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24);
+      WUFFS_BASE__COROUTINE_SUSPENSION_POINT(25);
       status = wuffs_json__decoder__decode_trailing_new_line(self, a_dst, a_src);
       if (a_dst) {
         iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
@@ -25451,8 +27183,8 @@
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
-    self->private_impl.f_allow_leading_ars = self->private_impl.f_quirks[14];
-    self->private_impl.f_allow_leading_ubom = self->private_impl.f_quirks[15];
+    self->private_impl.f_allow_leading_ars = self->private_impl.f_quirks[15];
+    self->private_impl.f_allow_leading_ubom = self->private_impl.f_quirks[16];
     label__0__continue:;
     while (self->private_impl.f_allow_leading_ars || self->private_impl.f_allow_leading_ubom) {
       if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
@@ -25577,7 +27309,7 @@
       WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
     }
     v_c2 = wuffs_base__load_u16le__no_bounds_check(iop_a_src);
-    if ((v_c2 == 10799) && self->private_impl.f_quirks[10]) {
+    if ((v_c2 == 10799) && self->private_impl.f_quirks[11]) {
       (iop_a_src += 2, wuffs_base__make_empty_struct());
       v_length = 2;
       label__comment_block__continue:;
@@ -25626,7 +27358,7 @@
           v_length += 1;
         }
       }
-    } else if ((v_c2 == 12079) && self->private_impl.f_quirks[11]) {
+    } else if ((v_c2 == 12079) && self->private_impl.f_quirks[12]) {
       (iop_a_src += 2, wuffs_base__make_empty_struct());
       v_length = 2;
       label__comment_line__continue:;
@@ -27228,6 +28960,984 @@
 
 #endif  // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB)
 
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+
+// ---------------- Auxiliary - Base
+
+// Auxiliary code is discussed at
+// https://github.com/google/wuffs/blob/master/doc/note/auxiliary-code.md
+
+#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__BASE)
+
+namespace wuffs_aux {
+
+namespace sync_io {
+
+// --------
+
+IOBuffer*  //
+Input::BringsItsOwnIOBuffer() {
+  return nullptr;
+}
+
+// --------
+
+FileInput::FileInput(FILE* f) : m_f(f) {}
+
+std::string  //
+FileInput::CopyIn(IOBuffer* dst) {
+  if (!m_f) {
+    return "wuffs_aux::sync_io::FileInput: nullptr file";
+  } else if (dst && !dst->meta.closed) {
+    size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);
+    dst->meta.wi += n;
+    dst->meta.closed = feof(m_f);
+    if (ferror(m_f)) {
+      return "wuffs_aux::sync_io::FileInput: error reading file";
+    }
+  }
+  return "";
+}
+
+// --------
+
+MemoryInput::MemoryInput(const char* ptr, size_t len)
+    : m_io(wuffs_base__ptr_u8__reader(
+          static_cast<uint8_t*>(static_cast<void*>(const_cast<char*>(ptr))),
+          len,
+          true)) {}
+
+MemoryInput::MemoryInput(const uint8_t* ptr, size_t len)
+    : m_io(wuffs_base__ptr_u8__reader(const_cast<uint8_t*>(ptr), len, true)) {}
+
+IOBuffer*  //
+MemoryInput::BringsItsOwnIOBuffer() {
+  return &m_io;
+}
+
+std::string  //
+MemoryInput::CopyIn(IOBuffer* dst) {
+  if (dst && !dst->meta.closed && (dst != &m_io)) {
+    size_t nd = dst->writer_length();
+    size_t ns = m_io.reader_length();
+    size_t n = (nd < ns) ? nd : ns;
+    memcpy(dst->writer_pointer(), m_io.reader_pointer(), n);
+    m_io.meta.ri += n;
+    dst->meta.wi += n;
+    dst->meta.closed = m_io.reader_length() == 0;
+  }
+  return "";
+}
+
+// --------
+
+}  // namespace sync_io
+
+}  // namespace wuffs_aux
+
+#endif  // !defined(WUFFS_CONFIG__MODULES) ||
+        // defined(WUFFS_CONFIG__MODULE__AUX__BASE)
+
+// ---------------- Auxiliary - CBOR
+
+#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__CBOR)
+
+#include <utility>
+
+namespace wuffs_aux {
+
+DecodeCborResult::DecodeCborResult(std::string&& error_message0,
+                                   uint64_t cursor_position0)
+    : error_message(std::move(error_message0)),
+      cursor_position(cursor_position0) {}
+
+void  //
+DecodeCborCallbacks::Done(DecodeCborResult& result,
+                          sync_io::Input& input,
+                          IOBuffer& buffer) {}
+
+DecodeCborResult  //
+DecodeCbor(DecodeCborCallbacks& callbacks,
+           sync_io::Input& input,
+           wuffs_base__slice_u32 quirks) {
+  // Prepare the wuffs_base__io_buffer and the resultant error_message.
+  wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
+  wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
+  std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);
+  if (!io_buf) {
+    fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[4096]);
+    fallback_io_buf = wuffs_base__ptr_u8__writer(fallback_io_array.get(), 4096);
+    io_buf = &fallback_io_buf;
+  }
+  size_t cursor_index = 0;
+  std::string ret_error_message;
+  std::string io_error_message;
+
+  do {
+    // Prepare the low-level CBOR decoder.
+    wuffs_cbor__decoder::unique_ptr dec = wuffs_cbor__decoder::alloc();
+    if (!dec) {
+      ret_error_message = "wuffs_aux::CborDecoder: out of memory";
+      goto done;
+    }
+    for (size_t i = 0; i < quirks.len; i++) {
+      dec->set_quirk_enabled(quirks.ptr[i], true);
+    }
+
+    // Prepare the wuffs_base__tok_buffer.
+    wuffs_base__token tok_array[256];
+    wuffs_base__token_buffer tok_buf =
+        wuffs_base__slice_token__writer(wuffs_base__make_slice_token(
+            &tok_array[0], (sizeof(tok_array) / sizeof(tok_array[0]))));
+    wuffs_base__status tok_status = wuffs_base__make_status(nullptr);
+
+    // Prepare other state.
+    uint32_t depth = 0;
+    std::string str;
+    int64_t extension_category = 0;
+    uint64_t extension_detail = 0;
+
+    // Valid token's VBCs range in 0 ..= 15. Values over that are for tokens
+    // from outside of the base package, such as the CBOR package.
+    constexpr int64_t EXT_CAT__CBOR_TAG = 16;
+
+    // Loop, doing these two things:
+    //  1. Get the next token.
+    //  2. Process that token.
+    while (true) {
+      // 1. Get the next token.
+
+      while (tok_buf.meta.ri >= tok_buf.meta.wi) {
+        if (tok_status.repr == nullptr) {
+          // No-op.
+        } else if (tok_status.repr == wuffs_base__suspension__short_write) {
+          tok_buf.compact();
+        } else if (tok_status.repr == wuffs_base__suspension__short_read) {
+          // Read from input to io_buf.
+          if (!io_error_message.empty()) {
+            ret_error_message = std::move(io_error_message);
+            goto done;
+          } else if (cursor_index != io_buf->meta.ri) {
+            ret_error_message =
+                "wuffs_aux::CborDecoder: internal error: bad cursor_index";
+            goto done;
+          } else if (io_buf->meta.closed) {
+            ret_error_message =
+                "wuffs_aux::CborDecoder: internal error: io_buf is closed";
+            goto done;
+          }
+          io_buf->compact();
+          if (io_buf->meta.wi >= io_buf->data.len) {
+            ret_error_message =
+                "wuffs_aux::CborDecoder: internal error: io_buf is full";
+            goto done;
+          }
+          cursor_index = io_buf->meta.ri;
+          io_error_message = input.CopyIn(io_buf);
+        } else {
+          ret_error_message = tok_status.message();
+          goto done;
+        }
+
+        if (WUFFS_CBOR__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {
+          ret_error_message =
+              "wuffs_aux::CborDecoder: internal error: bad WORKBUF_LEN";
+          goto done;
+        }
+        wuffs_base__slice_u8 work_buf = wuffs_base__empty_slice_u8();
+        tok_status = dec->decode_tokens(&tok_buf, io_buf, work_buf);
+      }
+
+      wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++];
+      uint64_t token_len = token.length();
+      if ((io_buf->meta.ri < cursor_index) ||
+          ((io_buf->meta.ri - cursor_index) < token_len)) {
+        ret_error_message =
+            "wuffs_aux::CborDecoder: internal error: bad token indexes";
+        goto done;
+      }
+      uint8_t* token_ptr = io_buf->data.ptr + cursor_index;
+      cursor_index += token_len;
+
+      // 2. Process that token.
+
+      uint64_t vbd = token.value_base_detail();
+
+      if (extension_category != 0) {
+        int64_t ext = token.value_extension();
+        if ((ext >= 0) && !token.continued()) {
+          extension_detail = (extension_detail
+                              << WUFFS_BASE__TOKEN__VALUE_EXTENSION__NUM_BITS) |
+                             static_cast<uint64_t>(ext);
+          switch (extension_category) {
+            case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED:
+              extension_category = 0;
+              ret_error_message =
+                  callbacks.AppendI64(static_cast<int64_t>(extension_detail));
+              goto parsed_a_value;
+            case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED:
+              extension_category = 0;
+              ret_error_message = callbacks.AppendU64(extension_detail);
+              goto parsed_a_value;
+            case EXT_CAT__CBOR_TAG:
+              extension_category = 0;
+              ret_error_message = callbacks.AppendCborTag(extension_detail);
+              if (!ret_error_message.empty()) {
+                goto done;
+              }
+              continue;
+          }
+        }
+        ret_error_message =
+            "wuffs_aux::CborDecoder: internal error: bad extended token";
+        goto done;
+      }
+
+      switch (token.value_base_category()) {
+        case WUFFS_BASE__TOKEN__VBC__FILLER:
+          continue;
+
+        case WUFFS_BASE__TOKEN__VBC__STRUCTURE: {
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+            ret_error_message = callbacks.Push(static_cast<uint32_t>(vbd));
+            if (!ret_error_message.empty()) {
+              goto done;
+            }
+            depth++;
+            continue;
+          }
+          ret_error_message = callbacks.Pop(static_cast<uint32_t>(vbd));
+          depth--;
+          goto parsed_a_value;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__STRING: {
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
+            // No-op.
+          } else if (vbd &
+                     WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
+            const char* ptr =  // Convert from (uint8_t*).
+                static_cast<const char*>(static_cast<void*>(token_ptr));
+            str.append(ptr, token_len);
+          } else {
+            goto fail;
+          }
+          if (token.continued()) {
+            continue;
+          }
+          ret_error_message =
+              (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8)
+                  ? callbacks.AppendTextString(std::move(str))
+                  : callbacks.AppendByteString(std::move(str));
+          str.clear();
+          goto parsed_a_value;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
+          uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
+          size_t n = wuffs_base__utf_8__encode(
+              wuffs_base__make_slice_u8(
+                  &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
+              static_cast<uint32_t>(vbd));
+          const char* ptr =  // Convert from (uint8_t*).
+              static_cast<const char*>(static_cast<void*>(&u[0]));
+          str.append(ptr, n);
+          if (token.continued()) {
+            continue;
+          }
+          goto fail;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__LITERAL: {
+          if (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__NULL) {
+            ret_error_message = callbacks.AppendNull();
+          } else if (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__UNDEFINED) {
+            ret_error_message = callbacks.AppendUndefined();
+          } else {
+            ret_error_message = callbacks.AppendBool(
+                vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE);
+          }
+          goto parsed_a_value;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__NUMBER: {
+          const uint64_t cfp_fbbe_fifb =
+              WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT |
+              WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN |
+              WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE;
+          if ((vbd & cfp_fbbe_fifb) == cfp_fbbe_fifb) {
+            double f;
+            switch (token_len) {
+              case 3:
+                f = wuffs_base__ieee_754_bit_representation__from_u16_to_f64(
+                    wuffs_base__load_u16be__no_bounds_check(token_ptr + 1));
+                break;
+              case 5:
+                f = wuffs_base__ieee_754_bit_representation__from_u32_to_f64(
+                    wuffs_base__load_u32be__no_bounds_check(token_ptr + 1));
+                break;
+              case 9:
+                f = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
+                    wuffs_base__load_u64be__no_bounds_check(token_ptr + 1));
+                break;
+              default:
+                goto fail;
+            }
+            ret_error_message = callbacks.AppendF64(f);
+            goto parsed_a_value;
+          }
+          goto fail;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED: {
+          if (token.continued()) {
+            extension_category = WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED;
+            extension_detail =
+                static_cast<uint64_t>(token.value_base_detail__sign_extended());
+            continue;
+          }
+          ret_error_message =
+              callbacks.AppendI64(token.value_base_detail__sign_extended());
+          goto parsed_a_value;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED: {
+          if (token.continued()) {
+            extension_category =
+                WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED;
+            extension_detail = vbd;
+            continue;
+          }
+          ret_error_message = callbacks.AppendU64(vbd);
+          goto parsed_a_value;
+        }
+      }
+
+      if (token.value_major() == WUFFS_CBOR__TOKEN_VALUE_MAJOR) {
+        uint64_t value_minor = token.value_minor();
+        if (value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__MINUS_1_MINUS_X) {
+          if (token_len == 9) {
+            ret_error_message = callbacks.AppendMinus1MinusX(
+                wuffs_base__load_u64be__no_bounds_check(token_ptr + 1));
+            goto parsed_a_value;
+          }
+        } else if (value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__SIMPLE_VALUE) {
+          ret_error_message =
+              callbacks.AppendCborSimpleValue(static_cast<uint8_t>(
+                  value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK));
+          goto parsed_a_value;
+        } else if (value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__TAG) {
+          if (token.continued()) {
+            extension_category = EXT_CAT__CBOR_TAG;
+            extension_detail =
+                value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK;
+            continue;
+          }
+          ret_error_message = callbacks.AppendCborTag(
+              value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK);
+          if (!ret_error_message.empty()) {
+            goto done;
+          }
+          continue;
+        }
+      }
+
+    fail:
+      ret_error_message =
+          "wuffs_aux::CborDecoder: internal error: unexpected token";
+      goto done;
+
+    parsed_a_value:
+      if (!ret_error_message.empty() || (depth == 0)) {
+        goto done;
+      }
+    }
+  } while (false);
+
+done:
+  DecodeCborResult result(
+      std::move(ret_error_message),
+      wuffs_base__u64__sat_add(io_buf->meta.pos, cursor_index));
+  callbacks.Done(result, input, *io_buf);
+  return result;
+}
+
+}  // namespace wuffs_aux
+
+#endif  // !defined(WUFFS_CONFIG__MODULES) ||
+        // defined(WUFFS_CONFIG__MODULE__AUX__CBOR)
+
+// ---------------- Auxiliary - JSON
+
+#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__JSON)
+
+#include <utility>
+
+namespace wuffs_aux {
+
+DecodeJsonResult::DecodeJsonResult(std::string&& error_message0,
+                                   uint64_t cursor_position0)
+    : error_message(std::move(error_message0)),
+      cursor_position(cursor_position0) {}
+
+std::string  //
+DecodeJsonCallbacks::AppendByteString(std::string&& val) {
+  return "wuffs_aux::DecodeJson: unexpected JSON byte string";
+}
+
+void  //
+DecodeJsonCallbacks::Done(DecodeJsonResult& result,
+                          sync_io::Input& input,
+                          IOBuffer& buffer) {}
+
+const char DecodeJson_BadJsonPointer[] =
+    "wuffs_aux::DecodeJson: bad JSON Pointer";
+const char DecodeJson_NoMatch[] = "wuffs_aux::DecodeJson: no match";
+
+// --------
+
+#define WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN                       \
+  while (tok_buf.meta.ri >= tok_buf.meta.wi) {                           \
+    if (tok_status.repr == nullptr) {                                    \
+    } else if (tok_status.repr == wuffs_base__suspension__short_write) { \
+      tok_buf.compact();                                                 \
+    } else if (tok_status.repr == wuffs_base__suspension__short_read) {  \
+      if (!io_error_message.empty()) {                                   \
+        ret_error_message = std::move(io_error_message);                 \
+        goto done;                                                       \
+      } else if (cursor_index != io_buf->meta.ri) {                      \
+        ret_error_message =                                              \
+            "wuffs_aux::DecodeJson: internal error: bad cursor_index";   \
+        goto done;                                                       \
+      } else if (io_buf->meta.closed) {                                  \
+        ret_error_message =                                              \
+            "wuffs_aux::DecodeJson: internal error: io_buf is closed";   \
+        goto done;                                                       \
+      }                                                                  \
+      io_buf->compact();                                                 \
+      if (io_buf->meta.wi >= io_buf->data.len) {                         \
+        ret_error_message =                                              \
+            "wuffs_aux::DecodeJson: internal error: io_buf is full";     \
+        goto done;                                                       \
+      }                                                                  \
+      cursor_index = io_buf->meta.ri;                                    \
+      io_error_message = input.CopyIn(io_buf);                           \
+    } else {                                                             \
+      ret_error_message = tok_status.message();                          \
+      goto done;                                                         \
+    }                                                                    \
+    if (WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {      \
+      ret_error_message =                                                \
+          "wuffs_aux::DecodeJson: internal error: bad WORKBUF_LEN";      \
+      goto done;                                                         \
+    }                                                                    \
+    wuffs_base__slice_u8 work_buf = wuffs_base__empty_slice_u8();        \
+    tok_status = dec->decode_tokens(&tok_buf, io_buf, work_buf);         \
+  }                                                                      \
+  wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++];         \
+  uint64_t token_len = token.length();                                   \
+  if ((io_buf->meta.ri < cursor_index) ||                                \
+      ((io_buf->meta.ri - cursor_index) < token_len)) {                  \
+    ret_error_message =                                                  \
+        "wuffs_aux::DecodeJson: internal error: bad token indexes";      \
+    goto done;                                                           \
+  }                                                                      \
+  uint8_t* token_ptr = io_buf->data.ptr + cursor_index;                  \
+  (void)(token_ptr);                                                     \
+  cursor_index += token_len
+
+// --------
+
+namespace {
+
+// DecodeJson_SplitJsonPointer returns ("bar", 8) for ("/foo/bar/b~1z/qux", 5,
+// etc). It returns a 0 size_t when s has invalid JSON Pointer syntax.
+//
+// The string returned is unescaped. If calling it again, this time with i=8,
+// the "b~1z" substring would be returned as "b/z".
+std::pair<std::string, size_t>  //
+DecodeJson_SplitJsonPointer(std::string& s,
+                            size_t i,
+                            bool allow_tilde_r_tilde_n) {
+  std::string fragment;
+  while (i < s.size()) {
+    char c = s[i];
+    if (c == '/') {
+      break;
+    } else if (c != '~') {
+      fragment.push_back(c);
+      i++;
+      continue;
+    }
+    i++;
+    if (i >= s.size()) {
+      return std::make_pair(std::string(), 0);
+    }
+    c = s[i];
+    if (c == '0') {
+      fragment.push_back('~');
+      i++;
+      continue;
+    } else if (c == '1') {
+      fragment.push_back('/');
+      i++;
+      continue;
+    } else if (allow_tilde_r_tilde_n) {
+      if (c == 'r') {
+        fragment.push_back('\r');
+        i++;
+        continue;
+      } else if (c == 'n') {
+        fragment.push_back('\n');
+        i++;
+        continue;
+      }
+    }
+    return std::make_pair(std::string(), 0);
+  }
+  return std::make_pair(std::move(fragment), i);
+}
+
+std::string  //
+DecodeJson_DecodeBackslashX(std::string& str,
+                            uint8_t* token_ptr,
+                            size_t token_len) {
+  wuffs_base__slice_u8 encoded =
+      wuffs_base__make_slice_u8(token_ptr, token_len);
+  while (encoded.len > 0) {
+    uint8_t decoded[64];
+    constexpr bool src_closed = true;
+    wuffs_base__transform__output o = wuffs_base__base_16__decode4(
+        wuffs_base__make_slice_u8(&decoded[0], sizeof decoded), encoded,
+        src_closed, WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);
+    if (o.status.is_error()) {
+      return o.status.message();
+    } else if ((o.num_dst > (sizeof decoded)) || (o.num_src > encoded.len)) {
+      return "wuffs_aux::DecodeJson: internal error: inconsistent base16 "
+             "decoding";
+    }
+    str.append(  // Convert from (uint8_t*).
+        static_cast<const char*>(static_cast<void*>(&decoded[0])), o.num_dst);
+    encoded.ptr += o.num_src;
+    encoded.len -= o.num_src;
+  }
+  return "";
+}
+
+// --------
+
+std::string  //
+DecodeJson_WalkJsonPointerFragment(wuffs_base__token_buffer& tok_buf,
+                                   wuffs_base__status& tok_status,
+                                   wuffs_json__decoder::unique_ptr& dec,
+                                   wuffs_base__io_buffer* io_buf,
+                                   std::string& io_error_message,
+                                   size_t& cursor_index,
+                                   sync_io::Input& input,
+                                   std::string& json_pointer_fragment) {
+  std::string ret_error_message;
+  while (true) {
+    WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+    int64_t vbc = token.value_base_category();
+    uint64_t vbd = token.value_base_detail();
+    if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
+      continue;
+    } else if ((vbc != WUFFS_BASE__TOKEN__VBC__STRUCTURE) ||
+               !(vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH)) {
+      return DecodeJson_NoMatch;
+    } else if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST) {
+      goto do_list;
+    }
+    goto do_dict;
+  }
+
+do_dict:
+  // Alternate between these two things:
+  //  1. Decode the next dict key (a string). If it matches the fragment, we're
+  //    done (success). If we've reached the dict's end (VBD__STRUCTURE__POP)
+  //    so that there was no next dict key, we're done (failure).
+  //  2. Otherwise, skip the next dict value.
+  while (true) {
+    for (std::string str; true;) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      switch (vbc) {
+        case WUFFS_BASE__TOKEN__VBC__FILLER:
+          continue;
+
+        case WUFFS_BASE__TOKEN__VBC__STRUCTURE:
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+            goto fail;
+          }
+          return DecodeJson_NoMatch;
+
+        case WUFFS_BASE__TOKEN__VBC__STRING: {
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
+            // No-op.
+          } else if (vbd &
+                     WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
+            const char* ptr =  // Convert from (uint8_t*).
+                static_cast<const char*>(static_cast<void*>(token_ptr));
+            str.append(ptr, token_len);
+          } else if (
+              vbd &
+              WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {
+            ret_error_message =
+                DecodeJson_DecodeBackslashX(str, token_ptr, token_len);
+            if (!ret_error_message.empty()) {
+              goto done;
+            }
+          } else {
+            goto fail;
+          }
+          break;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
+          uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
+          size_t n = wuffs_base__utf_8__encode(
+              wuffs_base__make_slice_u8(
+                  &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
+              static_cast<uint32_t>(vbd));
+          const char* ptr =  // Convert from (uint8_t*).
+              static_cast<const char*>(static_cast<void*>(&u[0]));
+          str.append(ptr, n);
+          break;
+        }
+
+        default:
+          goto fail;
+      }
+
+      if (token.continued()) {
+        continue;
+      }
+      if (str == json_pointer_fragment) {
+        return "";
+      }
+      goto skip_the_next_dict_value;
+    }
+
+  skip_the_next_dict_value:
+    for (uint32_t skip_depth = 0; true;) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
+        continue;
+      } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
+        if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+          skip_depth++;
+          continue;
+        }
+        skip_depth--;
+      }
+
+      if (skip_depth == 0) {
+        break;
+      }
+    }  // skip_the_next_dict_value
+  }    // do_dict
+
+do_list:
+  do {
+    wuffs_base__result_u64 result_u64 = wuffs_base__parse_number_u64(
+        wuffs_base__make_slice_u8(
+            static_cast<uint8_t*>(static_cast<void*>(
+                const_cast<char*>(json_pointer_fragment.data()))),
+            json_pointer_fragment.size()),
+        WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
+    if (!result_u64.status.is_ok()) {
+      return DecodeJson_NoMatch;
+    }
+    uint64_t remaining = result_u64.value;
+    if (remaining == 0) {
+      goto check_that_a_value_follows;
+    }
+    for (uint32_t skip_depth = 0; true;) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
+        continue;
+      } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
+        if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+          skip_depth++;
+          continue;
+        }
+        if (skip_depth == 0) {
+          return DecodeJson_NoMatch;
+        }
+        skip_depth--;
+      }
+
+      if (skip_depth > 0) {
+        continue;
+      }
+      remaining--;
+      if (remaining == 0) {
+        goto check_that_a_value_follows;
+      }
+    }
+  } while (false);  // do_list
+
+check_that_a_value_follows:
+  while (true) {
+    WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+    int64_t vbc = token.value_base_category();
+    uint64_t vbd = token.value_base_detail();
+    if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
+      continue;
+    }
+
+    // Undo the last part of WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN, so that
+    // we're only peeking at the next token.
+    tok_buf.meta.ri--;
+    cursor_index -= token_len;
+
+    if ((vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) &&
+        (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP)) {
+      return DecodeJson_NoMatch;
+    }
+    return "";
+  }  // check_that_a_value_follows
+
+fail:
+  return "wuffs_aux::DecodeJson: internal error: unexpected token";
+done:
+  return ret_error_message;
+}
+
+}  // namespace
+
+// --------
+
+DecodeJsonResult  //
+DecodeJson(DecodeJsonCallbacks& callbacks,
+           sync_io::Input& input,
+           wuffs_base__slice_u32 quirks,
+           std::string json_pointer) {
+  // Prepare the wuffs_base__io_buffer and the resultant error_message.
+  wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
+  wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
+  std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);
+  if (!io_buf) {
+    fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[4096]);
+    fallback_io_buf = wuffs_base__ptr_u8__writer(fallback_io_array.get(), 4096);
+    io_buf = &fallback_io_buf;
+  }
+  size_t cursor_index = 0;
+  std::string ret_error_message;
+  std::string io_error_message;
+
+  do {
+    // Prepare the low-level JSON decoder.
+    wuffs_json__decoder::unique_ptr dec = wuffs_json__decoder::alloc();
+    if (!dec) {
+      ret_error_message = "wuffs_aux::DecodeJson: out of memory";
+      goto done;
+    }
+    bool allow_tilde_r_tilde_n = false;
+    for (size_t i = 0; i < quirks.len; i++) {
+      dec->set_quirk_enabled(quirks.ptr[i], true);
+      if (quirks.ptr[i] ==
+          WUFFS_JSON__QUIRK_JSON_POINTER_ALLOW_TILDE_R_TILDE_N) {
+        allow_tilde_r_tilde_n = true;
+      }
+    }
+
+    // Prepare the wuffs_base__tok_buffer.
+    wuffs_base__token tok_array[256];
+    wuffs_base__token_buffer tok_buf =
+        wuffs_base__slice_token__writer(wuffs_base__make_slice_token(
+            &tok_array[0], (sizeof(tok_array) / sizeof(tok_array[0]))));
+    wuffs_base__status tok_status = wuffs_base__make_status(nullptr);
+
+    // Prepare other state.
+    uint32_t depth = 0;
+    std::string str;
+
+    // Walk the (optional) JSON Pointer.
+    for (size_t i = 0; i < json_pointer.size();) {
+      if (json_pointer[i] != '/') {
+        ret_error_message = DecodeJson_BadJsonPointer;
+        goto done;
+      }
+      std::pair<std::string, size_t> split = DecodeJson_SplitJsonPointer(
+          json_pointer, i + 1, allow_tilde_r_tilde_n);
+      i = std::move(split.second);
+      if (i == 0) {
+        ret_error_message = DecodeJson_BadJsonPointer;
+        goto done;
+      }
+      ret_error_message = DecodeJson_WalkJsonPointerFragment(
+          tok_buf, tok_status, dec, io_buf, io_error_message, cursor_index,
+          input, split.first);
+      if (!ret_error_message.empty()) {
+        goto done;
+      }
+    }
+
+    // Loop, doing these two things:
+    //  1. Get the next token.
+    //  2. Process that token.
+    while (true) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      switch (vbc) {
+        case WUFFS_BASE__TOKEN__VBC__FILLER:
+          continue;
+
+        case WUFFS_BASE__TOKEN__VBC__STRUCTURE: {
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+            ret_error_message = callbacks.Push(static_cast<uint32_t>(vbd));
+            if (!ret_error_message.empty()) {
+              goto done;
+            }
+            depth++;
+            continue;
+          }
+          ret_error_message = callbacks.Pop(static_cast<uint32_t>(vbd));
+          depth--;
+          goto parsed_a_value;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__STRING: {
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
+            // No-op.
+          } else if (vbd &
+                     WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
+            const char* ptr =  // Convert from (uint8_t*).
+                static_cast<const char*>(static_cast<void*>(token_ptr));
+            str.append(ptr, token_len);
+          } else if (
+              vbd &
+              WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {
+            ret_error_message =
+                DecodeJson_DecodeBackslashX(str, token_ptr, token_len);
+            if (!ret_error_message.empty()) {
+              goto done;
+            }
+          } else {
+            goto fail;
+          }
+          if (token.continued()) {
+            continue;
+          }
+          ret_error_message =
+              (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8)
+                  ? callbacks.AppendTextString(std::move(str))
+                  : callbacks.AppendByteString(std::move(str));
+          str.clear();
+          goto parsed_a_value;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
+          uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
+          size_t n = wuffs_base__utf_8__encode(
+              wuffs_base__make_slice_u8(
+                  &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
+              static_cast<uint32_t>(vbd));
+          const char* ptr =  // Convert from (uint8_t*).
+              static_cast<const char*>(static_cast<void*>(&u[0]));
+          str.append(ptr, n);
+          if (token.continued()) {
+            continue;
+          }
+          goto fail;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__LITERAL: {
+          ret_error_message =
+              (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__NULL)
+                  ? callbacks.AppendNull()
+                  : callbacks.AppendBool(vbd &
+                                         WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE);
+          goto parsed_a_value;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__NUMBER: {
+          if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT) {
+            if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED) {
+              wuffs_base__result_i64 r = wuffs_base__parse_number_i64(
+                  wuffs_base__make_slice_u8(token_ptr, token_len),
+                  WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
+              if (r.status.is_ok()) {
+                ret_error_message = callbacks.AppendI64(r.value);
+                goto parsed_a_value;
+              }
+            }
+            if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT) {
+              wuffs_base__result_f64 r = wuffs_base__parse_number_f64(
+                  wuffs_base__make_slice_u8(token_ptr, token_len),
+                  WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
+              if (r.status.is_ok()) {
+                ret_error_message = callbacks.AppendF64(r.value);
+                goto parsed_a_value;
+              }
+            }
+          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF) {
+            ret_error_message = callbacks.AppendF64(
+                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
+                    0xFFF0000000000000ul));
+            goto parsed_a_value;
+          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF) {
+            ret_error_message = callbacks.AppendF64(
+                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
+                    0x7FF0000000000000ul));
+            goto parsed_a_value;
+          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN) {
+            ret_error_message = callbacks.AppendF64(
+                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
+                    0xFFFFFFFFFFFFFFFFul));
+            goto parsed_a_value;
+          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN) {
+            ret_error_message = callbacks.AppendF64(
+                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
+                    0x7FFFFFFFFFFFFFFFul));
+            goto parsed_a_value;
+          }
+          goto fail;
+        }
+      }
+
+    fail:
+      ret_error_message =
+          "wuffs_aux::DecodeJson: internal error: unexpected token";
+      goto done;
+
+    parsed_a_value:
+      if (!ret_error_message.empty() || (depth == 0)) {
+        goto done;
+      }
+    }
+  } while (false);
+
+done:
+  DecodeJsonResult result(
+      std::move(ret_error_message),
+      wuffs_base__u64__sat_add(io_buf->meta.pos, cursor_index));
+  callbacks.Done(result, input, *io_buf);
+  return result;
+}
+
+#undef WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN
+
+}  // namespace wuffs_aux
+
+#endif  // !defined(WUFFS_CONFIG__MODULES) ||
+        // defined(WUFFS_CONFIG__MODULE__AUX__JSON)
+
+#endif  // defined(__cplusplus) && (__cplusplus >= 201103L)
+
 #endif  // WUFFS_IMPLEMENTATION
 
 #ifdef __clang__