Remove unused limit/mark I/O fields

name                                             old speed     new speed     delta

wuffs_deflate_decode_1k_full_init/clang5         146MB/s ± 0%  149MB/s ± 1%  +2.33%  (p=0.000 n=9+10)
wuffs_deflate_decode_1k_part_init/clang5         180MB/s ± 0%  183MB/s ± 0%  +1.46%  (p=0.000 n=10+10)
wuffs_deflate_decode_10k_full_init/clang5        229MB/s ± 0%  244MB/s ± 0%  +6.53%  (p=0.000 n=9+10)
wuffs_deflate_decode_10k_part_init/clang5        236MB/s ± 1%  251MB/s ± 0%  +6.38%  (p=0.000 n=10+10)
wuffs_deflate_decode_100k_just_one_read/clang5   266MB/s ± 0%  278MB/s ± 1%  +4.75%  (p=0.000 n=9+10)
wuffs_deflate_decode_100k_many_big_reads/clang5  224MB/s ± 0%  238MB/s ± 0%  +6.03%  (p=0.000 n=10+10)

wuffs_deflate_decode_1k_full_init/gcc7           151MB/s ± 2%  151MB/s ± 0%    ~     (p=0.965 n=10+8)
wuffs_deflate_decode_1k_part_init/gcc7           187MB/s ± 1%  188MB/s ± 0%  +0.57%  (p=0.001 n=10+9)
wuffs_deflate_decode_10k_full_init/gcc7          261MB/s ± 1%  259MB/s ± 1%  -0.91%  (p=0.000 n=10+10)
wuffs_deflate_decode_10k_part_init/gcc7          269MB/s ± 0%  268MB/s ± 0%  -0.65%  (p=0.000 n=10+9)
wuffs_deflate_decode_100k_just_one_read/gcc7     314MB/s ± 0%  312MB/s ± 0%  -0.49%  (p=0.000 n=10+10)
wuffs_deflate_decode_100k_many_big_reads/gcc7    249MB/s ± 0%  247MB/s ± 0%  -1.08%  (p=0.000 n=10+10)
diff --git a/internal/cgen/base/io-private.h b/internal/cgen/base/io-private.h
index 3de0a0c..aa2feab 100644
--- a/internal/cgen/base/io-private.h
+++ b/internal/cgen/base/io-private.h
@@ -32,20 +32,6 @@
   return wuffs_base__make_slice_u8(NULL, 0);
 }
 
-// TODO: wuffs_base__io_reader__is_eof is no longer used by Wuffs per se, but
-// it might be handy to programs that use Wuffs. Either delete it, or promote
-// it to the public API.
-//
-// If making this function public (i.e. moving it to base-header.h), it also
-// needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.
-
-static inline bool  //
-wuffs_base__io_reader__is_eof(wuffs_base__io_reader o) {
-  wuffs_base__io_buffer* buf = o.private_impl.buf;
-  return buf && buf->meta.closed &&
-         (buf->data.ptr + buf->meta.wi == o.private_impl.limit);
-}
-
 static inline uint32_t  //
 wuffs_base__io_writer__copy_n_from_history(uint8_t** ptr_iop_w,
                                            uint8_t* io0_w,
@@ -187,8 +173,6 @@
   b->meta.closed = false;
 
   o->private_impl.buf = b;
-  o->private_impl.mark = data.ptr;
-  o->private_impl.limit = data.ptr + data.len;
   *ptr_iop_r = data.ptr;
   *ptr_io1_r = data.ptr + data.len;
 
@@ -220,8 +204,6 @@
   b->meta.closed = false;
 
   o->private_impl.buf = b;
-  o->private_impl.mark = data.ptr;
-  o->private_impl.limit = data.ptr + data.len;
   *ptr_iop_w = data.ptr;
   *ptr_io1_w = data.ptr + data.len;
 
diff --git a/internal/cgen/base/io-public.h b/internal/cgen/base/io-public.h
index 39cf0dc..4372fb3 100644
--- a/internal/cgen/base/io-public.h
+++ b/internal/cgen/base/io-public.h
@@ -25,11 +25,6 @@
   // compatibility or safety guarantee if you do so.
   struct {
     struct wuffs_base__io_buffer__struct* buf;
-    // The bounds values are typically NULL, when created by the Wuffs public
-    // API. NULL means that the callee substitutes the implicit bounds derived
-    // from buf.
-    uint8_t* mark;
-    uint8_t* limit;
   } private_impl;
 } wuffs_base__io_reader;
 
@@ -38,11 +33,6 @@
   // compatibility or safety guarantee if you do so.
   struct {
     struct wuffs_base__io_buffer__struct* buf;
-    // The bounds values are typically NULL, when created by the Wuffs public
-    // API. NULL means that the callee substitutes the implicit bounds derived
-    // from buf.
-    uint8_t* mark;
-    uint8_t* limit;
   } private_impl;
 } wuffs_base__io_writer;
 
@@ -123,8 +113,6 @@
 wuffs_base__null_io_reader() {
   wuffs_base__io_reader ret;
   ret.private_impl.buf = NULL;
-  ret.private_impl.mark = NULL;
-  ret.private_impl.limit = NULL;
   return ret;
 }
 
@@ -132,8 +120,6 @@
 wuffs_base__null_io_writer() {
   wuffs_base__io_writer ret;
   ret.private_impl.buf = NULL;
-  ret.private_impl.mark = NULL;
-  ret.private_impl.limit = NULL;
   return ret;
 }
 
@@ -157,8 +143,6 @@
 wuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {
   wuffs_base__io_reader ret;
   ret.private_impl.buf = buf;
-  ret.private_impl.mark = NULL;
-  ret.private_impl.limit = NULL;
   return ret;
 }
 
@@ -166,8 +150,6 @@
 wuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {
   wuffs_base__io_writer ret;
   ret.private_impl.buf = buf;
-  ret.private_impl.mark = NULL;
-  ret.private_impl.limit = NULL;
   return ret;
 }
 
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index f122f14..2efa261 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -163,24 +163,23 @@
 	""
 
 const baseIOPrivateH = "" +
-	"// ---------------- I/O\n\nstatic inline uint64_t  //\nwuffs_base__io__count_since(uint64_t mark, uint64_t index) {\n  if (index >= mark) {\n    return index - mark;\n  }\n  return 0;\n}\n\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__io__since(uint64_t mark, uint64_t index, uint8_t* ptr) {\n  if (index >= mark) {\n    return wuffs_base__make_slice_u8(ptr + mark, index - mark);\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n// TODO: wuffs_base__io_reader__is_eof is no longer used by Wuffs per se, but\n// it might be handy to programs that use Wuffs. Either delete it, or promote\n// it to the public API.\n//\n// If making this function public (i.e. moving it to base-header.h), it also\n// needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.\n\nstatic inline bool  //\nwuffs_base__io_reader__is_eof(wuffs_base__io_reader o) {\n  wuffs_base__io_buffer* buf = o.private_impl.buf;\n  return buf && buf->meta.closed &&\n         (buf->data.ptr + buf->meta.wi == o.private_impl.limit);\n}\n\nstatic inline uint32_t  //\nwuf" +
-	"fs_base__io_writer__copy_n_from_history(uint8_t** ptr_iop_w,\n                                           uint8_t* io0_w,\n                                           uint8_t* io1_w,\n                                           uint32_t length,\n                                           uint32_t distance) {\n  if (!distance) {\n    return 0;\n  }\n  uint8_t* p = *ptr_iop_w;\n  if ((size_t)(p - io0_w) < (size_t)(distance)) {\n    return 0;\n  }\n  uint8_t* q = p - distance;\n  size_t n = (size_t)(io1_w - p);\n  if ((size_t)(length) > n) {\n    length = (uint32_t)(n);\n  } else {\n    n = (size_t)(length);\n  }\n  // TODO: unrolling by 3 seems best for the std/deflate benchmarks, but that\n  // is mostly because 3 is the minimum length for the deflate format. This\n  // function implementation shouldn't overfit to that one format. Perhaps the\n  // copy_n_from_history Wuffs method should also take an unroll hint argument,\n  // and the cgen can look if that argument is the constant expression '3'.\n  //\n  // See also wuffs_base__io_writ" +
-	"er__copy_n_from_history_fast below.\n  //\n  // Alternatively, or additionally, have a sloppy_copy_n_from_history method\n  // that copies 8 bytes at a time, possibly writing more than length bytes?\n  for (; n >= 3; n -= 3) {\n    *p++ = *q++;\n    *p++ = *q++;\n    *p++ = *q++;\n  }\n  for (; n; n--) {\n    *p++ = *q++;\n  }\n  *ptr_iop_w = p;\n  return length;\n}\n\n// wuffs_base__io_writer__copy_n_from_history_fast is like the\n// wuffs_base__io_writer__copy_n_from_history function above, but has stronger\n// pre-conditions. The caller needs to prove that:\n//  - distance >  0\n//  - distance <= (*ptr_iop_w - io0_w)\n//  - length   <= (io1_w      - *ptr_iop_w)\nstatic inline uint32_t  //\nwuffs_base__io_writer__copy_n_from_history_fast(uint8_t** ptr_iop_w,\n                                                uint8_t* io0_w,\n                                                uint8_t* io1_w,\n                                                uint32_t length,\n                                                uint32_t distance) {\n  uint8_t* p =" +
-	" *ptr_iop_w;\n  uint8_t* q = p - distance;\n  uint32_t n = length;\n  for (; n >= 3; n -= 3) {\n    *p++ = *q++;\n    *p++ = *q++;\n    *p++ = *q++;\n  }\n  for (; n; n--) {\n    *p++ = *q++;\n  }\n  *ptr_iop_w = p;\n  return length;\n}\n\nstatic inline uint32_t  //\nwuffs_base__io_writer__copy_n_from_reader(uint8_t** ptr_iop_w,\n                                          uint8_t* io1_w,\n                                          uint32_t length,\n                                          uint8_t** ptr_iop_r,\n                                          uint8_t* io1_r) {\n  uint8_t* iop_w = *ptr_iop_w;\n  size_t n = length;\n  if (n > ((size_t)(io1_w - iop_w))) {\n    n = (size_t)(io1_w - iop_w);\n  }\n  uint8_t* iop_r = *ptr_iop_r;\n  if (n > ((size_t)(io1_r - iop_r))) {\n    n = (size_t)(io1_r - iop_r);\n  }\n  if (n > 0) {\n    memmove(iop_w, iop_r, n);\n    *ptr_iop_w += n;\n    *ptr_iop_r += n;\n  }\n  return (uint32_t)(n);\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_writer__copy_from_slice(uint8_t** ptr_iop_w,\n                             " +
-	"          uint8_t* io1_w,\n                                       wuffs_base__slice_u8 src) {\n  uint8_t* iop_w = *ptr_iop_w;\n  size_t n = src.len;\n  if (n > ((size_t)(io1_w - iop_w))) {\n    n = (size_t)(io1_w - iop_w);\n  }\n  if (n > 0) {\n    memmove(iop_w, src.ptr, n);\n    *ptr_iop_w += n;\n  }\n  return (uint64_t)(n);\n}\n\nstatic inline uint32_t  //\nwuffs_base__io_writer__copy_n_from_slice(uint8_t** ptr_iop_w,\n                                         uint8_t* io1_w,\n                                         uint32_t length,\n                                         wuffs_base__slice_u8 src) {\n  uint8_t* iop_w = *ptr_iop_w;\n  size_t n = src.len;\n  if (n > length) {\n    n = length;\n  }\n  if (n > ((size_t)(io1_w - iop_w))) {\n    n = (size_t)(io1_w - iop_w);\n  }\n  if (n > 0) {\n    memmove(iop_w, src.ptr, n);\n    *ptr_iop_w += n;\n  }\n  return (uint32_t)(n);\n}\n\nstatic inline wuffs_base__empty_struct  //\nwuffs_base__io_reader__set(wuffs_base__io_reader* o,\n                           wuffs_base__io_buffer* b,\n             " +
-	"              uint8_t** ptr_iop_r,\n                           uint8_t** ptr_io1_r,\n                           wuffs_base__slice_u8 data) {\n  b->data = data;\n  b->meta.wi = data.len;\n  b->meta.ri = 0;\n  b->meta.pos = 0;\n  b->meta.closed = false;\n\n  o->private_impl.buf = b;\n  o->private_impl.mark = data.ptr;\n  o->private_impl.limit = data.ptr + data.len;\n  *ptr_iop_r = data.ptr;\n  *ptr_io1_r = data.ptr + data.len;\n\n  wuffs_base__empty_struct ret;\n  ret.private_impl = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__io_reader__take(uint8_t** ptr_iop_r, uint8_t* io1_r, uint64_t n) {\n  if (n <= ((size_t)(io1_r - *ptr_iop_r))) {\n    uint8_t* p = *ptr_iop_r;\n    *ptr_iop_r += n;\n    return wuffs_base__make_slice_u8(p, n);\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline wuffs_base__empty_struct  //\nwuffs_base__io_writer__set(wuffs_base__io_writer* o,\n                           wuffs_base__io_buffer* b,\n                           uint8_t** ptr_iop_w,\n                           u" +
-	"int8_t** ptr_io1_w,\n                           wuffs_base__slice_u8 data) {\n  b->data = data;\n  b->meta.wi = 0;\n  b->meta.ri = 0;\n  b->meta.pos = 0;\n  b->meta.closed = false;\n\n  o->private_impl.buf = b;\n  o->private_impl.mark = data.ptr;\n  o->private_impl.limit = data.ptr + data.len;\n  *ptr_iop_w = data.ptr;\n  *ptr_io1_w = data.ptr + data.len;\n\n  wuffs_base__empty_struct ret;\n  ret.private_impl = 0;\n  return ret;\n}\n\n" +
+	"// ---------------- I/O\n\nstatic inline uint64_t  //\nwuffs_base__io__count_since(uint64_t mark, uint64_t index) {\n  if (index >= mark) {\n    return index - mark;\n  }\n  return 0;\n}\n\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__io__since(uint64_t mark, uint64_t index, uint8_t* ptr) {\n  if (index >= mark) {\n    return wuffs_base__make_slice_u8(ptr + mark, index - mark);\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline uint32_t  //\nwuffs_base__io_writer__copy_n_from_history(uint8_t** ptr_iop_w,\n                                           uint8_t* io0_w,\n                                           uint8_t* io1_w,\n                                           uint32_t length,\n                                           uint32_t distance) {\n  if (!distance) {\n    return 0;\n  }\n  uint8_t* p = *ptr_iop_w;\n  if ((size_t)(p - io0_w) < (size_t)(distance)) {\n    return 0;\n  }\n  uint8_t* q = p - distance;\n  size_t n = (size_t)(io1_w - p);\n  if ((size_t)(length) > n) {\n    length = (uint32_t)(n);\n  } else {\n" +
+	"    n = (size_t)(length);\n  }\n  // TODO: unrolling by 3 seems best for the std/deflate benchmarks, but that\n  // is mostly because 3 is the minimum length for the deflate format. This\n  // function implementation shouldn't overfit to that one format. Perhaps the\n  // copy_n_from_history Wuffs method should also take an unroll hint argument,\n  // and the cgen can look if that argument is the constant expression '3'.\n  //\n  // See also wuffs_base__io_writer__copy_n_from_history_fast below.\n  //\n  // Alternatively, or additionally, have a sloppy_copy_n_from_history method\n  // that copies 8 bytes at a time, possibly writing more than length bytes?\n  for (; n >= 3; n -= 3) {\n    *p++ = *q++;\n    *p++ = *q++;\n    *p++ = *q++;\n  }\n  for (; n; n--) {\n    *p++ = *q++;\n  }\n  *ptr_iop_w = p;\n  return length;\n}\n\n// wuffs_base__io_writer__copy_n_from_history_fast is like the\n// wuffs_base__io_writer__copy_n_from_history function above, but has stronger\n// pre-conditions. The caller needs to prove that:\n//  - distance >  " +
+	"0\n//  - distance <= (*ptr_iop_w - io0_w)\n//  - length   <= (io1_w      - *ptr_iop_w)\nstatic inline uint32_t  //\nwuffs_base__io_writer__copy_n_from_history_fast(uint8_t** ptr_iop_w,\n                                                uint8_t* io0_w,\n                                                uint8_t* io1_w,\n                                                uint32_t length,\n                                                uint32_t distance) {\n  uint8_t* p = *ptr_iop_w;\n  uint8_t* q = p - distance;\n  uint32_t n = length;\n  for (; n >= 3; n -= 3) {\n    *p++ = *q++;\n    *p++ = *q++;\n    *p++ = *q++;\n  }\n  for (; n; n--) {\n    *p++ = *q++;\n  }\n  *ptr_iop_w = p;\n  return length;\n}\n\nstatic inline uint32_t  //\nwuffs_base__io_writer__copy_n_from_reader(uint8_t** ptr_iop_w,\n                                          uint8_t* io1_w,\n                                          uint32_t length,\n                                          uint8_t** ptr_iop_r,\n                                          uint8_t* io1_r) {\n  uint8_t* i" +
+	"op_w = *ptr_iop_w;\n  size_t n = length;\n  if (n > ((size_t)(io1_w - iop_w))) {\n    n = (size_t)(io1_w - iop_w);\n  }\n  uint8_t* iop_r = *ptr_iop_r;\n  if (n > ((size_t)(io1_r - iop_r))) {\n    n = (size_t)(io1_r - iop_r);\n  }\n  if (n > 0) {\n    memmove(iop_w, iop_r, n);\n    *ptr_iop_w += n;\n    *ptr_iop_r += n;\n  }\n  return (uint32_t)(n);\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_writer__copy_from_slice(uint8_t** ptr_iop_w,\n                                       uint8_t* io1_w,\n                                       wuffs_base__slice_u8 src) {\n  uint8_t* iop_w = *ptr_iop_w;\n  size_t n = src.len;\n  if (n > ((size_t)(io1_w - iop_w))) {\n    n = (size_t)(io1_w - iop_w);\n  }\n  if (n > 0) {\n    memmove(iop_w, src.ptr, n);\n    *ptr_iop_w += n;\n  }\n  return (uint64_t)(n);\n}\n\nstatic inline uint32_t  //\nwuffs_base__io_writer__copy_n_from_slice(uint8_t** ptr_iop_w,\n                                         uint8_t* io1_w,\n                                         uint32_t length,\n                                         w" +
+	"uffs_base__slice_u8 src) {\n  uint8_t* iop_w = *ptr_iop_w;\n  size_t n = src.len;\n  if (n > length) {\n    n = length;\n  }\n  if (n > ((size_t)(io1_w - iop_w))) {\n    n = (size_t)(io1_w - iop_w);\n  }\n  if (n > 0) {\n    memmove(iop_w, src.ptr, n);\n    *ptr_iop_w += n;\n  }\n  return (uint32_t)(n);\n}\n\nstatic inline wuffs_base__empty_struct  //\nwuffs_base__io_reader__set(wuffs_base__io_reader* o,\n                           wuffs_base__io_buffer* b,\n                           uint8_t** ptr_iop_r,\n                           uint8_t** ptr_io1_r,\n                           wuffs_base__slice_u8 data) {\n  b->data = data;\n  b->meta.wi = data.len;\n  b->meta.ri = 0;\n  b->meta.pos = 0;\n  b->meta.closed = false;\n\n  o->private_impl.buf = b;\n  *ptr_iop_r = data.ptr;\n  *ptr_io1_r = data.ptr + data.len;\n\n  wuffs_base__empty_struct ret;\n  ret.private_impl = 0;\n  return ret;\n}\n\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__io_reader__take(uint8_t** ptr_iop_r, uint8_t* io1_r, uint64_t n) {\n  if (n <= ((size_t)(io1_r - *ptr_iop_r))" +
+	") {\n    uint8_t* p = *ptr_iop_r;\n    *ptr_iop_r += n;\n    return wuffs_base__make_slice_u8(p, n);\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline wuffs_base__empty_struct  //\nwuffs_base__io_writer__set(wuffs_base__io_writer* o,\n                           wuffs_base__io_buffer* b,\n                           uint8_t** ptr_iop_w,\n                           uint8_t** ptr_io1_w,\n                           wuffs_base__slice_u8 data) {\n  b->data = data;\n  b->meta.wi = 0;\n  b->meta.ri = 0;\n  b->meta.pos = 0;\n  b->meta.closed = false;\n\n  o->private_impl.buf = b;\n  *ptr_iop_w = data.ptr;\n  *ptr_io1_w = data.ptr + data.len;\n\n  wuffs_base__empty_struct ret;\n  ret.private_impl = 0;\n  return ret;\n}\n\n" +
 	"" +
 	"// ---------------- I/O (Utility)\n\n#define wuffs_base__utility__null_io_reader wuffs_base__null_io_reader\n#define wuffs_base__utility__null_io_writer wuffs_base__null_io_writer\n" +
 	""
 
 const baseIOPublicH = "" +
-	"// ---------------- I/O\n//\n// See (/doc/note/io-input-output.md).\n\nstruct wuffs_base__io_buffer__struct;\n\ntypedef struct {\n  // Do not access the private_impl's fields directly. There is no API/ABI\n  // compatibility or safety guarantee if you do so.\n  struct {\n    struct wuffs_base__io_buffer__struct* buf;\n    // The bounds values are typically NULL, when created by the Wuffs public\n    // API. NULL means that the callee substitutes the implicit bounds derived\n    // from buf.\n    uint8_t* mark;\n    uint8_t* limit;\n  } private_impl;\n} wuffs_base__io_reader;\n\ntypedef struct {\n  // Do not access the private_impl's fields directly. There is no API/ABI\n  // compatibility or safety guarantee if you do so.\n  struct {\n    struct wuffs_base__io_buffer__struct* buf;\n    // The bounds values are typically NULL, when created by the Wuffs public\n    // API. NULL means that the callee substitutes the implicit bounds derived\n    // from buf.\n    uint8_t* mark;\n    uint8_t* limit;\n  } private_impl;\n} wuffs_base__io_writer;" +
-	"\n\n// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's\n// data.\ntypedef struct {\n  size_t wi;     // Write index. Invariant: wi <= len.\n  size_t ri;     // Read  index. Invariant: ri <= wi.\n  uint64_t pos;  // Position of the buffer start relative to the stream start.\n  bool closed;   // No further writes are expected.\n} wuffs_base__io_buffer_meta;\n\n// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length) plus\n// additional metadata.\n//\n// A value with all fields zero is a valid, empty buffer.\ntypedef struct wuffs_base__io_buffer__struct {\n  wuffs_base__slice_u8 data;\n  wuffs_base__io_buffer_meta meta;\n\n#ifdef __cplusplus\n  inline void compact();\n  inline wuffs_base__io_reader reader();\n  inline wuffs_base__io_writer writer();\n  inline uint64_t reader_available() const;\n  inline uint64_t reader_io_position() const;\n  inline uint64_t writer_available() const;\n  inline uint64_t writer_io_position() const;\n#endif  // __cplusplus\n\n} wuffs_base__io_buffer;\n\nstatic inline wuf" +
-	"fs_base__io_buffer  //\nwuffs_base__make_io_buffer(wuffs_base__slice_u8 data,\n                           wuffs_base__io_buffer_meta meta) {\n  wuffs_base__io_buffer ret;\n  ret.data = data;\n  ret.meta = meta;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta  //\nwuffs_base__make_io_buffer_meta(size_t wi,\n                                size_t ri,\n                                uint64_t pos,\n                                bool closed) {\n  wuffs_base__io_buffer_meta ret;\n  ret.wi = wi;\n  ret.ri = ri;\n  ret.pos = pos;\n  ret.closed = closed;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer  //\nwuffs_base__null_io_buffer() {\n  wuffs_base__io_buffer ret;\n  ret.data.ptr = NULL;\n  ret.data.len = 0;\n  ret.meta.wi = 0;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = false;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta  //\nwuffs_base__null_io_buffer_meta() {\n  wuffs_base__io_buffer_meta ret;\n  ret.wi = 0;\n  ret.ri = 0;\n  ret.pos = 0;\n  ret.closed = false;\n  return ret;\n}\n\nstatic inline " +
-	"wuffs_base__io_reader  //\nwuffs_base__null_io_reader() {\n  wuffs_base__io_reader ret;\n  ret.private_impl.buf = NULL;\n  ret.private_impl.mark = NULL;\n  ret.private_impl.limit = NULL;\n  return ret;\n}\n\nstatic inline wuffs_base__io_writer  //\nwuffs_base__null_io_writer() {\n  wuffs_base__io_writer ret;\n  ret.private_impl.buf = NULL;\n  ret.private_impl.mark = NULL;\n  ret.private_impl.limit = NULL;\n  return ret;\n}\n\n// wuffs_base__io_buffer__compact moves any written but unread bytes to the\n// start of the buffer.\nstatic inline void  //\nwuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {\n  if (!buf || (buf->meta.ri == 0)) {\n    return;\n  }\n  buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);\n  size_t n = buf->meta.wi - buf->meta.ri;\n  if (n != 0) {\n    memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri, n);\n  }\n  buf->meta.wi = n;\n  buf->meta.ri = 0;\n}\n\nstatic inline wuffs_base__io_reader  //\nwuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {\n  wuffs_base__io_reader ret;\n  ret.p" +
-	"rivate_impl.buf = buf;\n  ret.private_impl.mark = NULL;\n  ret.private_impl.limit = NULL;\n  return ret;\n}\n\nstatic inline wuffs_base__io_writer  //\nwuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {\n  wuffs_base__io_writer ret;\n  ret.private_impl.buf = buf;\n  ret.private_impl.mark = NULL;\n  ret.private_impl.limit = NULL;\n  return ret;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__reader_available(const wuffs_base__io_buffer* buf) {\n  return buf ? buf->meta.wi - buf->meta.ri : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__writer_available(const wuffs_base__io_buffer* buf) {\n  return buf ? buf->data.len - buf->meta.wi : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;\n}\n\n#ifde" +
-	"f __cplusplus\n\ninline void  //\nwuffs_base__io_buffer__struct::compact() {\n  wuffs_base__io_buffer__compact(this);\n}\n\ninline wuffs_base__io_reader  //\nwuffs_base__io_buffer__struct::reader() {\n  return wuffs_base__io_buffer__reader(this);\n}\n\ninline wuffs_base__io_writer  //\nwuffs_base__io_buffer__struct::writer() {\n  return wuffs_base__io_buffer__writer(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer__struct::reader_available() const {\n  return wuffs_base__io_buffer__reader_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer__struct::reader_io_position() const {\n  return wuffs_base__io_buffer__reader_io_position(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer__struct::writer_available() const {\n  return wuffs_base__io_buffer__writer_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer__struct::writer_io_position() const {\n  return wuffs_base__io_buffer__writer_io_position(this);\n}\n\n#endif  // __cplusplus\n" +
+	"// ---------------- I/O\n//\n// See (/doc/note/io-input-output.md).\n\nstruct wuffs_base__io_buffer__struct;\n\ntypedef struct {\n  // Do not access the private_impl's fields directly. There is no API/ABI\n  // compatibility or safety guarantee if you do so.\n  struct {\n    struct wuffs_base__io_buffer__struct* buf;\n  } private_impl;\n} wuffs_base__io_reader;\n\ntypedef struct {\n  // Do not access the private_impl's fields directly. There is no API/ABI\n  // compatibility or safety guarantee if you do so.\n  struct {\n    struct wuffs_base__io_buffer__struct* buf;\n  } private_impl;\n} wuffs_base__io_writer;\n\n// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's\n// data.\ntypedef struct {\n  size_t wi;     // Write index. Invariant: wi <= len.\n  size_t ri;     // Read  index. Invariant: ri <= wi.\n  uint64_t pos;  // Position of the buffer start relative to the stream start.\n  bool closed;   // No further writes are expected.\n} wuffs_base__io_buffer_meta;\n\n// wuffs_base__io_buffer is a 1-dimensional buffer " +
+	"(a pointer and length) plus\n// additional metadata.\n//\n// A value with all fields zero is a valid, empty buffer.\ntypedef struct wuffs_base__io_buffer__struct {\n  wuffs_base__slice_u8 data;\n  wuffs_base__io_buffer_meta meta;\n\n#ifdef __cplusplus\n  inline void compact();\n  inline wuffs_base__io_reader reader();\n  inline wuffs_base__io_writer writer();\n  inline uint64_t reader_available() const;\n  inline uint64_t reader_io_position() const;\n  inline uint64_t writer_available() const;\n  inline uint64_t writer_io_position() const;\n#endif  // __cplusplus\n\n} wuffs_base__io_buffer;\n\nstatic inline wuffs_base__io_buffer  //\nwuffs_base__make_io_buffer(wuffs_base__slice_u8 data,\n                           wuffs_base__io_buffer_meta meta) {\n  wuffs_base__io_buffer ret;\n  ret.data = data;\n  ret.meta = meta;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta  //\nwuffs_base__make_io_buffer_meta(size_t wi,\n                                size_t ri,\n                                uint64_t pos,\n                          " +
+	"      bool closed) {\n  wuffs_base__io_buffer_meta ret;\n  ret.wi = wi;\n  ret.ri = ri;\n  ret.pos = pos;\n  ret.closed = closed;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer  //\nwuffs_base__null_io_buffer() {\n  wuffs_base__io_buffer ret;\n  ret.data.ptr = NULL;\n  ret.data.len = 0;\n  ret.meta.wi = 0;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = false;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta  //\nwuffs_base__null_io_buffer_meta() {\n  wuffs_base__io_buffer_meta ret;\n  ret.wi = 0;\n  ret.ri = 0;\n  ret.pos = 0;\n  ret.closed = false;\n  return ret;\n}\n\nstatic inline wuffs_base__io_reader  //\nwuffs_base__null_io_reader() {\n  wuffs_base__io_reader ret;\n  ret.private_impl.buf = NULL;\n  return ret;\n}\n\nstatic inline wuffs_base__io_writer  //\nwuffs_base__null_io_writer() {\n  wuffs_base__io_writer ret;\n  ret.private_impl.buf = NULL;\n  return ret;\n}\n\n// wuffs_base__io_buffer__compact moves any written but unread bytes to the\n// start of the buffer.\nstatic inline void  //\nwuffs_base__io_buffer" +
+	"__compact(wuffs_base__io_buffer* buf) {\n  if (!buf || (buf->meta.ri == 0)) {\n    return;\n  }\n  buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);\n  size_t n = buf->meta.wi - buf->meta.ri;\n  if (n != 0) {\n    memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri, n);\n  }\n  buf->meta.wi = n;\n  buf->meta.ri = 0;\n}\n\nstatic inline wuffs_base__io_reader  //\nwuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {\n  wuffs_base__io_reader ret;\n  ret.private_impl.buf = buf;\n  return ret;\n}\n\nstatic inline wuffs_base__io_writer  //\nwuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {\n  wuffs_base__io_writer ret;\n  ret.private_impl.buf = buf;\n  return ret;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__reader_available(const wuffs_base__io_buffer* buf) {\n  return buf ? buf->meta.wi - buf->meta.ri : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;\n}\n\nstat" +
+	"ic inline uint64_t  //\nwuffs_base__io_buffer__writer_available(const wuffs_base__io_buffer* buf) {\n  return buf ? buf->data.len - buf->meta.wi : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;\n}\n\n#ifdef __cplusplus\n\ninline void  //\nwuffs_base__io_buffer__struct::compact() {\n  wuffs_base__io_buffer__compact(this);\n}\n\ninline wuffs_base__io_reader  //\nwuffs_base__io_buffer__struct::reader() {\n  return wuffs_base__io_buffer__reader(this);\n}\n\ninline wuffs_base__io_writer  //\nwuffs_base__io_buffer__struct::writer() {\n  return wuffs_base__io_buffer__writer(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer__struct::reader_available() const {\n  return wuffs_base__io_buffer__reader_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer__struct::reader_io_position() const {\n  return wuffs_base__io_buffer__reader_io_position(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer__" +
+	"struct::writer_available() const {\n  return wuffs_base__io_buffer__writer_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer__struct::writer_io_position() const {\n  return wuffs_base__io_buffer__writer_io_position(this);\n}\n\n#endif  // __cplusplus\n" +
 	""
 
 const baseRangePrivateH = "" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 63e0e42..a9beb7d 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -1283,11 +1283,6 @@
   // compatibility or safety guarantee if you do so.
   struct {
     struct wuffs_base__io_buffer__struct* buf;
-    // The bounds values are typically NULL, when created by the Wuffs public
-    // API. NULL means that the callee substitutes the implicit bounds derived
-    // from buf.
-    uint8_t* mark;
-    uint8_t* limit;
   } private_impl;
 } wuffs_base__io_reader;
 
@@ -1296,11 +1291,6 @@
   // compatibility or safety guarantee if you do so.
   struct {
     struct wuffs_base__io_buffer__struct* buf;
-    // The bounds values are typically NULL, when created by the Wuffs public
-    // API. NULL means that the callee substitutes the implicit bounds derived
-    // from buf.
-    uint8_t* mark;
-    uint8_t* limit;
   } private_impl;
 } wuffs_base__io_writer;
 
@@ -1381,8 +1371,6 @@
 wuffs_base__null_io_reader() {
   wuffs_base__io_reader ret;
   ret.private_impl.buf = NULL;
-  ret.private_impl.mark = NULL;
-  ret.private_impl.limit = NULL;
   return ret;
 }
 
@@ -1390,8 +1378,6 @@
 wuffs_base__null_io_writer() {
   wuffs_base__io_writer ret;
   ret.private_impl.buf = NULL;
-  ret.private_impl.mark = NULL;
-  ret.private_impl.limit = NULL;
   return ret;
 }
 
@@ -1415,8 +1401,6 @@
 wuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {
   wuffs_base__io_reader ret;
   ret.private_impl.buf = buf;
-  ret.private_impl.mark = NULL;
-  ret.private_impl.limit = NULL;
   return ret;
 }
 
@@ -1424,8 +1408,6 @@
 wuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {
   wuffs_base__io_writer ret;
   ret.private_impl.buf = buf;
-  ret.private_impl.mark = NULL;
-  ret.private_impl.limit = NULL;
   return ret;
 }
 
@@ -4536,20 +4518,6 @@
   return wuffs_base__make_slice_u8(NULL, 0);
 }
 
-// TODO: wuffs_base__io_reader__is_eof is no longer used by Wuffs per se, but
-// it might be handy to programs that use Wuffs. Either delete it, or promote
-// it to the public API.
-//
-// If making this function public (i.e. moving it to base-header.h), it also
-// needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.
-
-static inline bool  //
-wuffs_base__io_reader__is_eof(wuffs_base__io_reader o) {
-  wuffs_base__io_buffer* buf = o.private_impl.buf;
-  return buf && buf->meta.closed &&
-         (buf->data.ptr + buf->meta.wi == o.private_impl.limit);
-}
-
 static inline uint32_t  //
 wuffs_base__io_writer__copy_n_from_history(uint8_t** ptr_iop_w,
                                            uint8_t* io0_w,
@@ -4691,8 +4659,6 @@
   b->meta.closed = false;
 
   o->private_impl.buf = b;
-  o->private_impl.mark = data.ptr;
-  o->private_impl.limit = data.ptr + data.len;
   *ptr_iop_r = data.ptr;
   *ptr_io1_r = data.ptr + data.len;
 
@@ -4724,8 +4690,6 @@
   b->meta.closed = false;
 
   o->private_impl.buf = b;
-  o->private_impl.mark = data.ptr;
-  o->private_impl.limit = data.ptr + data.len;
   *ptr_iop_w = data.ptr;
   *ptr_io1_w = data.ptr + data.len;