Remove io_{reader,writer} C types
diff --git a/example/gifplayer/gifplayer.c b/example/gifplayer/gifplayer.c
index 212d3ba..703b968 100644
--- a/example/gifplayer/gifplayer.c
+++ b/example/gifplayer/gifplayer.c
@@ -310,11 +310,10 @@
   src.meta.ri = 0;
   src.meta.pos = 0;
   src.meta.closed = true;
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
 
   if (first_play) {
     wuffs_base__image_config ic = {0};
-    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
     if (status) {
       return status;
     }
@@ -346,7 +345,7 @@
   while (1) {
     wuffs_base__frame_config fc = {0};
     wuffs_base__status status =
-        wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+        wuffs_gif__decoder__decode_frame_config(&dec, &fc, &src);
     if (status) {
       if (status == wuffs_base__warning__end_of_data) {
         break;
@@ -371,8 +370,7 @@
       }
     }
 
-    status =
-        wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader, workbuf, NULL);
+    status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src, workbuf, NULL);
     if (status) {
       if (status == wuffs_base__warning__end_of_data) {
         break;
diff --git a/example/library/library.c b/example/library/library.c
index 8726ca3..f8e258a 100644
--- a/example/library/library.c
+++ b/example/library/library.c
@@ -93,9 +93,6 @@
   src.meta.pos = 0;
   src.meta.closed = true;
 
-  wuffs_base__io_writer dst_writer = wuffs_base__io_buffer__writer(&dst);
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-
   wuffs_gzip__decoder* dec =
       (wuffs_gzip__decoder*)(calloc(sizeof__wuffs_gzip__decoder(), 1));
   if (!dec) {
@@ -109,7 +106,7 @@
     return status;
   }
   status = wuffs_gzip__decoder__decode_io_writer(
-      dec, dst_writer, src_reader,
+      dec, &dst, &src,
       wuffs_base__make_slice_u8(work_buffer, WORK_BUFFER_SIZE));
   if (status) {
     free(dec);
diff --git a/example/zcat/zcat.c b/example/zcat/zcat.c
index c2bf06a..20d7fe4 100644
--- a/example/zcat/zcat.c
+++ b/example/zcat/zcat.c
@@ -124,8 +124,7 @@
 
     while (true) {
       status = wuffs_gzip__decoder__decode_io_writer(
-          &dec, wuffs_base__io_buffer__writer(&dst),
-          wuffs_base__io_buffer__reader(&src),
+          &dec, &dst, &src,
           wuffs_base__make_slice_u8(work_buffer, WORK_BUFFER_SIZE));
 
       if (dst.meta.wi) {
diff --git a/fuzz/c/fuzzlib/fuzzlib.c b/fuzz/c/fuzzlib/fuzzlib.c
index 03050f9..a91e1e4 100644
--- a/fuzz/c/fuzzlib/fuzzlib.c
+++ b/fuzz/c/fuzzlib/fuzzlib.c
@@ -27,7 +27,7 @@
   *intentional_segfault_ptr = 0;
 }
 
-const char* fuzz(wuffs_base__io_reader src_reader, uint32_t hash);
+const char* fuzz(wuffs_base__io_buffer* src, uint32_t hash);
 
 static const char* llvmFuzzerTestOneInput(const uint8_t* data, size_t size) {
   // Hash input as per https://en.wikipedia.org/wiki/Jenkins_hash_function
@@ -55,7 +55,7 @@
       }),
   });
 
-  const char* msg = fuzz(wuffs_base__io_buffer__reader(&src), hash);
+  const char* msg = fuzz(&src, hash);
   if (msg && strstr(msg, "internal error:")) {
     fprintf(stderr, "internal errors shouldn't occur: \"%s\"\n", msg);
     intentional_segfault();
diff --git a/fuzz/c/std/gif_fuzzer.c b/fuzz/c/std/gif_fuzzer.c
index c3ce2fd..2858c1c 100644
--- a/fuzz/c/std/gif_fuzzer.c
+++ b/fuzz/c/std/gif_fuzzer.c
@@ -48,7 +48,7 @@
 #include "../../../release/c/wuffs-unsupported-snapshot.c"
 #include "../fuzzlib/fuzzlib.c"
 
-const char* fuzz(wuffs_base__io_reader src_reader, uint32_t hash) {
+const char* fuzz(wuffs_base__io_buffer* src, uint32_t hash) {
   const char* ret = NULL;
   wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
   wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
@@ -67,7 +67,7 @@
     }
 
     wuffs_base__image_config ic = ((wuffs_base__image_config){});
-    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src);
     if (status) {
       ret = status;
       goto exit;
@@ -115,7 +115,7 @@
     bool seen_ok = false;
     while (true) {
       wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
-      status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+      status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src);
       if (status) {
         if ((status != wuffs_base__warning__end_of_data) || !seen_ok) {
           ret = status;
@@ -123,8 +123,7 @@
         goto exit;
       }
 
-      status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader, workbuf,
-                                                NULL);
+      status = wuffs_gif__decoder__decode_frame(&dec, &pb, src, workbuf, NULL);
 
       wuffs_base__rect_ie_u32 frame_rect =
           wuffs_base__frame_config__bounds(&fc);
diff --git a/fuzz/c/std/zlib_fuzzer.c b/fuzz/c/std/zlib_fuzzer.c
index ffded01..b452582 100644
--- a/fuzz/c/std/zlib_fuzzer.c
+++ b/fuzz/c/std/zlib_fuzzer.c
@@ -60,7 +60,7 @@
 uint8_t work_buffer[1];
 #endif
 
-const char* fuzz(wuffs_base__io_reader src_reader, uint32_t hash) {
+const char* fuzz(wuffs_base__io_buffer* src, uint32_t hash) {
   wuffs_zlib__decoder dec;
   const char* status = wuffs_zlib__decoder__initialize(
       &dec, sizeof dec, WUFFS_VERSION,
@@ -81,11 +81,10 @@
           .len = DST_BUFFER_SIZE,
       }),
   });
-  wuffs_base__io_writer dst_writer = wuffs_base__io_buffer__writer(&dst);
 
   while (true) {
     dst.meta.wi = 0;
-    status = wuffs_zlib__decoder__decode_io_writer(&dec, dst_writer, src_reader,
+    status = wuffs_zlib__decoder__decode_io_writer(&dec, &dst, src,
                                                    ((wuffs_base__slice_u8){
                                                        .ptr = work_buffer,
                                                        .len = WORK_BUFFER_SIZE,
diff --git a/internal/cgen/base/io-private.h b/internal/cgen/base/io-private.h
index 5bd9d22..cd42e1e 100644
--- a/internal/cgen/base/io-private.h
+++ b/internal/cgen/base/io-private.h
@@ -161,7 +161,7 @@
 }
 
 static inline wuffs_base__empty_struct  //
-wuffs_base__io_reader__set(wuffs_base__io_reader* o,
+wuffs_base__io_reader__set(wuffs_base__io_buffer** o,
                            wuffs_base__io_buffer* b,
                            uint8_t** ptr_iop_r,
                            uint8_t** ptr_io1_r,
@@ -192,7 +192,7 @@
 }
 
 static inline wuffs_base__empty_struct  //
-wuffs_base__io_writer__set(wuffs_base__io_writer* o,
+wuffs_base__io_writer__set(wuffs_base__io_buffer** o,
                            wuffs_base__io_buffer* b,
                            uint8_t** ptr_iop_w,
                            uint8_t** ptr_io1_w,
diff --git a/internal/cgen/base/io-public.h b/internal/cgen/base/io-public.h
index b17d9ab..de44683 100644
--- a/internal/cgen/base/io-public.h
+++ b/internal/cgen/base/io-public.h
@@ -18,11 +18,6 @@
 //
 // See (/doc/note/io-input-output.md).
 
-struct wuffs_base__io_buffer__struct;
-
-typedef struct wuffs_base__io_buffer__struct* wuffs_base__io_reader;
-typedef struct wuffs_base__io_buffer__struct* wuffs_base__io_writer;
-
 // wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's
 // data.
 typedef struct {
@@ -42,8 +37,8 @@
 
 #ifdef __cplusplus
   inline void compact();
-  inline wuffs_base__io_reader reader();
-  inline wuffs_base__io_writer writer();
+  inline wuffs_base__io_buffer__struct* reader();  // Deprecated.
+  inline wuffs_base__io_buffer__struct* writer();  // Deprecated.
   inline uint64_t reader_available() const;
   inline uint64_t reader_io_position() const;
   inline uint64_t writer_available() const;
@@ -96,12 +91,12 @@
   return ret;
 }
 
-static inline wuffs_base__io_reader  //
+static inline wuffs_base__io_buffer*  //
 wuffs_base__null_io_reader() {
   return NULL;
 }
 
-static inline wuffs_base__io_writer  //
+static inline wuffs_base__io_buffer*  //
 wuffs_base__null_io_writer() {
   return NULL;
 }
@@ -122,16 +117,6 @@
   buf->meta.ri = 0;
 }
 
-static inline wuffs_base__io_reader  //
-wuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {
-  return buf;
-}
-
-static inline wuffs_base__io_writer  //
-wuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {
-  return buf;
-}
-
 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;
@@ -159,14 +144,14 @@
   wuffs_base__io_buffer__compact(this);
 }
 
-inline wuffs_base__io_reader  //
+inline wuffs_base__io_buffer*  //
 wuffs_base__io_buffer__struct::reader() {
-  return wuffs_base__io_buffer__reader(this);
+  return this;
 }
 
-inline wuffs_base__io_writer  //
+inline wuffs_base__io_buffer*  //
 wuffs_base__io_buffer__struct::writer() {
-  return wuffs_base__io_buffer__writer(this);
+  return this;
 }
 
 inline uint64_t  //
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index 9de073b..18acc69 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -167,18 +167,18 @@
 	"    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 = 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 = 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" +
+	"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_buffer** 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 = 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_buffer** 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 = 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 wuffs_base__io_buffer__struct* wuffs_base__io_reader;\ntypedef struct wuffs_base__io_buffer__struct* 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  in" +
-	"line 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.c" +
-	"losed = 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  return NULL;\n}\n\nstatic inline wuffs_base__io_writer  //\nwuffs_base__null_io_writer() {\n  return NULL;\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  return buf;\n}\n\nstatic inline wuffs_base" +
-	"__io_writer  //\nwuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {\n  return buf;\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#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" +
+	"// ---------------- I/O\n//\n// See (/doc/note/io-input-output.md).\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_buffer__struct* reader();  // Deprecated.\n  inline wuffs_base__io_buffer__struct* writer();  // Deprecated.\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__i" +
+	"o_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_buffer*  //\nwuffs_base__null_io_reader() {\n  return NULL;\n}\n\nstatic inline wuffs_base__io_buffer*  //\nwuffs_base__null_io_writer() {\n  return NULL;\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 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#ifdef __cplusplus\n\ninline void  //\nwuffs_base__io_buffer__struct::compact() {\n  wuffs_base__io_buffer__compact(this);\n}\n\ninline wuffs_base__io_buffer*  //\nwuffs_base__io_buffer__struct::reader() {\n  return this;\n}\n\ninline wuffs_base__io_buffer*  //\nwuffs_base__io_buffer__struct::writer() {\n  return 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/internal/cgen/expr.go b/internal/cgen/expr.go
index 3315531..4a326c8 100644
--- a/internal/cgen/expr.go
+++ b/internal/cgen/expr.go
@@ -461,8 +461,8 @@
 	t.IDU32:      "uint32_t",
 	t.IDU64:      "uint64_t",
 	t.IDBool:     "bool",
-	t.IDIOReader: "wuffs_base__io_reader",
-	t.IDIOWriter: "wuffs_base__io_writer",
+	t.IDIOReader: "wuffs_base__io_buffer*",
+	t.IDIOWriter: "wuffs_base__io_buffer*",
 }
 
 const noSuchCOperator = " no_such_C_operator "
diff --git a/internal/cgen/statement.go b/internal/cgen/statement.go
index 6fca3e8..4de60d6 100644
--- a/internal/cgen/statement.go
+++ b/internal/cgen/statement.go
@@ -267,8 +267,8 @@
 			cTyp = "writer"
 		}
 		name := e.Ident().Str(g.tm)
-		b.printf("wuffs_base__io_%s %s%d_%s%s = %s%s;\n",
-			cTyp, oPrefix, ioBindNum, prefix, name, prefix, name)
+		b.printf("wuffs_base__io_buffer* %s%d_%s%s = %s%s;\n",
+			oPrefix, ioBindNum, prefix, name, prefix, name)
 
 		// TODO: save / restore all iop vars, not just for local IO vars? How
 		// does this work if the io_bind body advances these pointers, either
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 79bab2f..5bdbaaf 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -1276,11 +1276,6 @@
 //
 // See (/doc/note/io-input-output.md).
 
-struct wuffs_base__io_buffer__struct;
-
-typedef struct wuffs_base__io_buffer__struct* wuffs_base__io_reader;
-typedef struct wuffs_base__io_buffer__struct* wuffs_base__io_writer;
-
 // wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's
 // data.
 typedef struct {
@@ -1300,8 +1295,8 @@
 
 #ifdef __cplusplus
   inline void compact();
-  inline wuffs_base__io_reader reader();
-  inline wuffs_base__io_writer writer();
+  inline wuffs_base__io_buffer__struct* reader();  // Deprecated.
+  inline wuffs_base__io_buffer__struct* writer();  // Deprecated.
   inline uint64_t reader_available() const;
   inline uint64_t reader_io_position() const;
   inline uint64_t writer_available() const;
@@ -1354,12 +1349,12 @@
   return ret;
 }
 
-static inline wuffs_base__io_reader  //
+static inline wuffs_base__io_buffer*  //
 wuffs_base__null_io_reader() {
   return NULL;
 }
 
-static inline wuffs_base__io_writer  //
+static inline wuffs_base__io_buffer*  //
 wuffs_base__null_io_writer() {
   return NULL;
 }
@@ -1380,16 +1375,6 @@
   buf->meta.ri = 0;
 }
 
-static inline wuffs_base__io_reader  //
-wuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {
-  return buf;
-}
-
-static inline wuffs_base__io_writer  //
-wuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {
-  return buf;
-}
-
 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;
@@ -1417,14 +1402,14 @@
   wuffs_base__io_buffer__compact(this);
 }
 
-inline wuffs_base__io_reader  //
+inline wuffs_base__io_buffer*  //
 wuffs_base__io_buffer__struct::reader() {
-  return wuffs_base__io_buffer__reader(this);
+  return this;
 }
 
-inline wuffs_base__io_writer  //
+inline wuffs_base__io_buffer*  //
 wuffs_base__io_buffer__struct::writer() {
-  return wuffs_base__io_buffer__writer(this);
+  return this;
 }
 
 inline uint64_t  //
@@ -2963,8 +2948,8 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_deflate__decoder__decode_io_writer(wuffs_deflate__decoder* self,
-                                         wuffs_base__io_writer a_dst,
-                                         wuffs_base__io_reader a_src,
+                                         wuffs_base__io_buffer* a_dst,
+                                         wuffs_base__io_buffer* a_src,
                                          wuffs_base__slice_u8 a_workbuf);
 
 // ---------------- Struct Definitions
@@ -3082,8 +3067,8 @@
   }
 
   inline wuffs_base__status  //
-  decode_io_writer(wuffs_base__io_writer a_dst,
-                   wuffs_base__io_reader a_src,
+  decode_io_writer(wuffs_base__io_buffer* a_dst,
+                   wuffs_base__io_buffer* a_src,
                    wuffs_base__slice_u8 a_workbuf) {
     return wuffs_deflate__decoder__decode_io_writer(this, a_dst, a_src,
                                                     a_workbuf);
@@ -3154,8 +3139,8 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_lzw__decoder__decode_io_writer(wuffs_lzw__decoder* self,
-                                     wuffs_base__io_writer a_dst,
-                                     wuffs_base__io_reader a_src,
+                                     wuffs_base__io_buffer* a_dst,
+                                     wuffs_base__io_buffer* a_src,
                                      wuffs_base__slice_u8 a_workbuf);
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8  //
@@ -3252,8 +3237,8 @@
   }
 
   inline wuffs_base__status  //
-  decode_io_writer(wuffs_base__io_writer a_dst,
-                   wuffs_base__io_reader a_src,
+  decode_io_writer(wuffs_base__io_buffer* a_dst,
+                   wuffs_base__io_buffer* a_src,
                    wuffs_base__slice_u8 a_workbuf) {
     return wuffs_lzw__decoder__decode_io_writer(this, a_dst, a_src, a_workbuf);
   }
@@ -3376,7 +3361,7 @@
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gif__decoder__decode_image_config(wuffs_gif__decoder* self,
                                         wuffs_base__image_config* a_dst,
-                                        wuffs_base__io_reader a_src);
+                                        wuffs_base__io_buffer* a_src);
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct  //
 wuffs_gif__decoder__set_report_metadata(wuffs_gif__decoder* self,
@@ -3385,7 +3370,7 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gif__decoder__ack_metadata_chunk(wuffs_gif__decoder* self,
-                                       wuffs_base__io_reader a_src);
+                                       wuffs_base__io_buffer* a_src);
 
 WUFFS_BASE__MAYBE_STATIC uint32_t  //
 wuffs_gif__decoder__metadata_fourcc(const wuffs_gif__decoder* self);
@@ -3416,12 +3401,12 @@
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gif__decoder__decode_frame_config(wuffs_gif__decoder* self,
                                         wuffs_base__frame_config* a_dst,
-                                        wuffs_base__io_reader a_src);
+                                        wuffs_base__io_buffer* a_src);
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gif__decoder__decode_frame(wuffs_gif__decoder* self,
                                  wuffs_base__pixel_buffer* a_dst,
-                                 wuffs_base__io_reader a_src,
+                                 wuffs_base__io_buffer* a_src,
                                  wuffs_base__slice_u8 a_workbuf,
                                  wuffs_base__decode_frame_options* a_opts);
 
@@ -3603,7 +3588,7 @@
 
   inline wuffs_base__status  //
   decode_image_config(wuffs_base__image_config* a_dst,
-                      wuffs_base__io_reader a_src) {
+                      wuffs_base__io_buffer* a_src) {
     return wuffs_gif__decoder__decode_image_config(this, a_dst, a_src);
   }
 
@@ -3613,7 +3598,7 @@
   }
 
   inline wuffs_base__status  //
-  ack_metadata_chunk(wuffs_base__io_reader a_src) {
+  ack_metadata_chunk(wuffs_base__io_buffer* a_src) {
     return wuffs_gif__decoder__ack_metadata_chunk(this, a_src);
   }
 
@@ -3659,13 +3644,13 @@
 
   inline wuffs_base__status  //
   decode_frame_config(wuffs_base__frame_config* a_dst,
-                      wuffs_base__io_reader a_src) {
+                      wuffs_base__io_buffer* a_src) {
     return wuffs_gif__decoder__decode_frame_config(this, a_dst, a_src);
   }
 
   inline wuffs_base__status  //
   decode_frame(wuffs_base__pixel_buffer* a_dst,
-               wuffs_base__io_reader a_src,
+               wuffs_base__io_buffer* a_src,
                wuffs_base__slice_u8 a_workbuf,
                wuffs_base__decode_frame_options* a_opts) {
     return wuffs_gif__decoder__decode_frame(this, a_dst, a_src, a_workbuf,
@@ -3739,8 +3724,8 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gzip__decoder__decode_io_writer(wuffs_gzip__decoder* self,
-                                      wuffs_base__io_writer a_dst,
-                                      wuffs_base__io_reader a_src,
+                                      wuffs_base__io_buffer* a_dst,
+                                      wuffs_base__io_buffer* a_src,
                                       wuffs_base__slice_u8 a_workbuf);
 
 // ---------------- Struct Definitions
@@ -3827,8 +3812,8 @@
   }
 
   inline wuffs_base__status  //
-  decode_io_writer(wuffs_base__io_writer a_dst,
-                   wuffs_base__io_reader a_src,
+  decode_io_writer(wuffs_base__io_buffer* a_dst,
+                   wuffs_base__io_buffer* a_src,
                    wuffs_base__slice_u8 a_workbuf) {
     return wuffs_gzip__decoder__decode_io_writer(this, a_dst, a_src, a_workbuf);
   }
@@ -3900,8 +3885,8 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_zlib__decoder__decode_io_writer(wuffs_zlib__decoder* self,
-                                      wuffs_base__io_writer a_dst,
-                                      wuffs_base__io_reader a_src,
+                                      wuffs_base__io_buffer* a_dst,
+                                      wuffs_base__io_buffer* a_src,
                                       wuffs_base__slice_u8 a_workbuf);
 
 // ---------------- Struct Definitions
@@ -3985,8 +3970,8 @@
   }
 
   inline wuffs_base__status  //
-  decode_io_writer(wuffs_base__io_writer a_dst,
-                   wuffs_base__io_reader a_src,
+  decode_io_writer(wuffs_base__io_buffer* a_dst,
+                   wuffs_base__io_buffer* a_src,
                    wuffs_base__slice_u8 a_workbuf) {
     return wuffs_zlib__decoder__decode_io_writer(this, a_dst, a_src, a_workbuf);
   }
@@ -4626,7 +4611,7 @@
 }
 
 static inline wuffs_base__empty_struct  //
-wuffs_base__io_reader__set(wuffs_base__io_reader* o,
+wuffs_base__io_reader__set(wuffs_base__io_buffer** o,
                            wuffs_base__io_buffer* b,
                            uint8_t** ptr_iop_r,
                            uint8_t** ptr_io1_r,
@@ -4657,7 +4642,7 @@
 }
 
 static inline wuffs_base__empty_struct  //
-wuffs_base__io_writer__set(wuffs_base__io_writer* o,
+wuffs_base__io_writer__set(wuffs_base__io_buffer** o,
                            wuffs_base__io_buffer* b,
                            uint8_t** ptr_iop_w,
                            uint8_t** ptr_io1_w,
@@ -6280,20 +6265,20 @@
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__decode_blocks(wuffs_deflate__decoder* self,
-                                      wuffs_base__io_writer a_dst,
-                                      wuffs_base__io_reader a_src);
+                                      wuffs_base__io_buffer* a_dst,
+                                      wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__decode_uncompressed(wuffs_deflate__decoder* self,
-                                            wuffs_base__io_writer a_dst,
-                                            wuffs_base__io_reader a_src);
+                                            wuffs_base__io_buffer* a_dst,
+                                            wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__init_fixed_huffman(wuffs_deflate__decoder* self);
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__init_dynamic_huffman(wuffs_deflate__decoder* self,
-                                             wuffs_base__io_reader a_src);
+                                             wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__init_huff(wuffs_deflate__decoder* self,
@@ -6304,13 +6289,13 @@
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__decode_huffman_fast(wuffs_deflate__decoder* self,
-                                            wuffs_base__io_writer a_dst,
-                                            wuffs_base__io_reader a_src);
+                                            wuffs_base__io_buffer* a_dst,
+                                            wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__decode_huffman_slow(wuffs_deflate__decoder* self,
-                                            wuffs_base__io_writer a_dst,
-                                            wuffs_base__io_reader a_src);
+                                            wuffs_base__io_buffer* a_dst,
+                                            wuffs_base__io_buffer* a_src);
 
 // ---------------- Initializer Implementations
 
@@ -6385,8 +6370,8 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_deflate__decoder__decode_io_writer(wuffs_deflate__decoder* self,
-                                         wuffs_base__io_writer a_dst,
-                                         wuffs_base__io_reader a_src,
+                                         wuffs_base__io_buffer* a_dst,
+                                         wuffs_base__io_buffer* a_src,
                                          wuffs_base__slice_u8 a_workbuf) {
   if (!self) {
     return wuffs_base__error__bad_receiver;
@@ -6518,8 +6503,8 @@
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__decode_blocks(wuffs_deflate__decoder* self,
-                                      wuffs_base__io_writer a_dst,
-                                      wuffs_base__io_reader a_src) {
+                                      wuffs_base__io_buffer* a_dst,
+                                      wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint32_t v_final = 0;
@@ -6664,8 +6649,8 @@
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__decode_uncompressed(wuffs_deflate__decoder* self,
-                                            wuffs_base__io_writer a_dst,
-                                            wuffs_base__io_reader a_src) {
+                                            wuffs_base__io_buffer* a_dst,
+                                            wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint32_t v_length = 0;
@@ -6824,7 +6809,7 @@
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__init_dynamic_huffman(wuffs_deflate__decoder* self,
-                                             wuffs_base__io_reader a_src) {
+                                             wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint32_t v_bits = 0;
@@ -7330,8 +7315,8 @@
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__decode_huffman_fast(wuffs_deflate__decoder* self,
-                                            wuffs_base__io_writer a_dst,
-                                            wuffs_base__io_reader a_src) {
+                                            wuffs_base__io_buffer* a_dst,
+                                            wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint32_t v_bits = 0;
@@ -7613,8 +7598,8 @@
 
 static wuffs_base__status  //
 wuffs_deflate__decoder__decode_huffman_slow(wuffs_deflate__decoder* self,
-                                            wuffs_base__io_writer a_dst,
-                                            wuffs_base__io_reader a_src) {
+                                            wuffs_base__io_buffer* a_dst,
+                                            wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint32_t v_bits = 0;
@@ -8023,11 +8008,11 @@
 
 static wuffs_base__empty_struct  //
 wuffs_lzw__decoder__read_from(wuffs_lzw__decoder* self,
-                              wuffs_base__io_reader a_src);
+                              wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_lzw__decoder__write_to(wuffs_lzw__decoder* self,
-                             wuffs_base__io_writer a_dst);
+                             wuffs_base__io_buffer* a_dst);
 
 // ---------------- Initializer Implementations
 
@@ -8121,8 +8106,8 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_lzw__decoder__decode_io_writer(wuffs_lzw__decoder* self,
-                                     wuffs_base__io_writer a_dst,
-                                     wuffs_base__io_reader a_src,
+                                     wuffs_base__io_buffer* a_dst,
+                                     wuffs_base__io_buffer* a_src,
                                      wuffs_base__slice_u8 a_workbuf) {
   if (!self) {
     return wuffs_base__error__bad_receiver;
@@ -8221,7 +8206,7 @@
 
 static wuffs_base__empty_struct  //
 wuffs_lzw__decoder__read_from(wuffs_lzw__decoder* self,
-                              wuffs_base__io_reader a_src) {
+                              wuffs_base__io_buffer* a_src) {
   uint32_t v_clear_code = 0;
   uint32_t v_end_code = 0;
   uint32_t v_save_code = 0;
@@ -8410,7 +8395,7 @@
 
 static wuffs_base__status  //
 wuffs_lzw__decoder__write_to(wuffs_lzw__decoder* self,
-                             wuffs_base__io_writer a_dst) {
+                             wuffs_base__io_buffer* a_dst) {
   wuffs_base__status status = NULL;
 
   wuffs_base__slice_u8 v_s = {0};
@@ -8559,52 +8544,52 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__skip_frame(wuffs_gif__decoder* self,
-                               wuffs_base__io_reader a_src);
+                               wuffs_base__io_buffer* a_src);
 
 static wuffs_base__empty_struct  //
 wuffs_gif__decoder__reset_gc(wuffs_gif__decoder* self);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_up_to_id_part1(wuffs_gif__decoder* self,
-                                          wuffs_base__io_reader a_src);
+                                          wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_header(wuffs_gif__decoder* self,
-                                  wuffs_base__io_reader a_src);
+                                  wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_lsd(wuffs_gif__decoder* self,
-                               wuffs_base__io_reader a_src);
+                               wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_extension(wuffs_gif__decoder* self,
-                                     wuffs_base__io_reader a_src);
+                                     wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__skip_blocks(wuffs_gif__decoder* self,
-                                wuffs_base__io_reader a_src);
+                                wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_ae(wuffs_gif__decoder* self,
-                              wuffs_base__io_reader a_src);
+                              wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_gc(wuffs_gif__decoder* self,
-                              wuffs_base__io_reader a_src);
+                              wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_id_part0(wuffs_gif__decoder* self,
-                                    wuffs_base__io_reader a_src);
+                                    wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_id_part1(wuffs_gif__decoder* self,
                                     wuffs_base__pixel_buffer* a_dst,
-                                    wuffs_base__io_reader a_src);
+                                    wuffs_base__io_buffer* a_src);
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_id_part2(wuffs_gif__decoder* self,
                                     wuffs_base__pixel_buffer* a_dst,
-                                    wuffs_base__io_reader a_src,
+                                    wuffs_base__io_buffer* a_src,
                                     wuffs_base__slice_u8 a_workbuf);
 
 static wuffs_base__status  //
@@ -8714,7 +8699,7 @@
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gif__decoder__decode_image_config(wuffs_gif__decoder* self,
                                         wuffs_base__image_config* a_dst,
-                                        wuffs_base__io_reader a_src) {
+                                        wuffs_base__io_buffer* a_src) {
   if (!self) {
     return wuffs_base__error__bad_receiver;
   }
@@ -8827,7 +8812,7 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gif__decoder__ack_metadata_chunk(wuffs_gif__decoder* self,
-                                       wuffs_base__io_reader a_src) {
+                                       wuffs_base__io_buffer* a_src) {
   if (!self) {
     return wuffs_base__error__bad_receiver;
   }
@@ -9079,7 +9064,7 @@
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gif__decoder__decode_frame_config(wuffs_gif__decoder* self,
                                         wuffs_base__frame_config* a_dst,
-                                        wuffs_base__io_reader a_src) {
+                                        wuffs_base__io_buffer* a_src) {
   if (!self) {
     return wuffs_base__error__bad_receiver;
   }
@@ -9237,7 +9222,7 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__skip_frame(wuffs_gif__decoder* self,
-                               wuffs_base__io_reader a_src) {
+                               wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t v_flags = 0;
@@ -9338,7 +9323,7 @@
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gif__decoder__decode_frame(wuffs_gif__decoder* self,
                                  wuffs_base__pixel_buffer* a_dst,
-                                 wuffs_base__io_reader a_src,
+                                 wuffs_base__io_buffer* a_src,
                                  wuffs_base__slice_u8 a_workbuf,
                                  wuffs_base__decode_frame_options* a_opts) {
   if (!self) {
@@ -9434,7 +9419,7 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_up_to_id_part1(wuffs_gif__decoder* self,
-                                          wuffs_base__io_reader a_src) {
+                                          wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t v_block_type = 0;
@@ -9551,7 +9536,7 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_header(wuffs_gif__decoder* self,
-                                  wuffs_base__io_reader a_src) {
+                                  wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t v_c[6] = {0};
@@ -9618,7 +9603,7 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_lsd(wuffs_gif__decoder* self,
-                               wuffs_base__io_reader a_src) {
+                               wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t v_flags = 0;
@@ -9832,7 +9817,7 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_extension(wuffs_gif__decoder* self,
-                                     wuffs_base__io_reader a_src) {
+                                     wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t v_label = 0;
@@ -9926,7 +9911,7 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__skip_blocks(wuffs_gif__decoder* self,
-                                wuffs_base__io_reader a_src) {
+                                wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t v_block_size = 0;
@@ -9997,7 +9982,7 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_ae(wuffs_gif__decoder* self,
-                              wuffs_base__io_reader a_src) {
+                              wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t v_c = 0;
@@ -10249,7 +10234,7 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_gc(wuffs_gif__decoder* self,
-                              wuffs_base__io_reader a_src) {
+                              wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t v_c = 0;
@@ -10380,7 +10365,7 @@
 
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_id_part0(wuffs_gif__decoder* self,
-                                    wuffs_base__io_reader a_src) {
+                                    wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t* iop_a_src = NULL;
@@ -10551,7 +10536,7 @@
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_id_part1(wuffs_gif__decoder* self,
                                     wuffs_base__pixel_buffer* a_dst,
-                                    wuffs_base__io_reader a_src) {
+                                    wuffs_base__io_buffer* a_src) {
   wuffs_base__status status = NULL;
 
   uint8_t v_flags = 0;
@@ -10746,7 +10731,7 @@
 static wuffs_base__status  //
 wuffs_gif__decoder__decode_id_part2(wuffs_gif__decoder* self,
                                     wuffs_base__pixel_buffer* a_dst,
-                                    wuffs_base__io_reader a_src,
+                                    wuffs_base__io_buffer* a_src,
                                     wuffs_base__slice_u8 a_workbuf) {
   wuffs_base__status status = NULL;
 
@@ -10754,7 +10739,7 @@
   bool v_need_block_size = false;
   uint64_t v_n_compressed = 0;
   wuffs_base__slice_u8 v_compressed = {0};
-  wuffs_base__io_reader v_r = wuffs_base__null_io_reader();
+  wuffs_base__io_buffer* v_r = wuffs_base__null_io_reader();
   wuffs_base__io_buffer u_r WUFFS_BASE__POTENTIALLY_UNUSED =
       wuffs_base__null_io_buffer();
   uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
@@ -10851,7 +10836,7 @@
           goto exit;
         }
         {
-          wuffs_base__io_reader o_0_v_r = v_r;
+          wuffs_base__io_buffer* o_0_v_r = v_r;
           uint8_t* o_0_iop_v_r = iop_v_r;
           uint8_t* o_0_io1_v_r = io1_v_r;
           wuffs_base__io_reader__set(
@@ -11215,8 +11200,8 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gzip__decoder__decode_io_writer(wuffs_gzip__decoder* self,
-                                      wuffs_base__io_writer a_dst,
-                                      wuffs_base__io_reader a_src,
+                                      wuffs_base__io_buffer* a_dst,
+                                      wuffs_base__io_buffer* a_src,
                                       wuffs_base__slice_u8 a_workbuf) {
   if (!self) {
     return wuffs_base__error__bad_receiver;
@@ -11691,8 +11676,8 @@
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_zlib__decoder__decode_io_writer(wuffs_zlib__decoder* self,
-                                      wuffs_base__io_writer a_dst,
-                                      wuffs_base__io_reader a_src,
+                                      wuffs_base__io_buffer* a_dst,
+                                      wuffs_base__io_buffer* a_src,
                                       wuffs_base__slice_u8 a_workbuf) {
   if (!self) {
     return wuffs_base__error__bad_receiver;
diff --git a/test/c/std/deflate.c b/test/c/std/deflate.c
index b30a53b..c7ac8e9 100644
--- a/test/c/std/deflate.c
+++ b/test/c/std/deflate.c
@@ -149,14 +149,10 @@
 
   while (true) {
     wuffs_base__io_buffer limited_dst = make_limited_writer(*dst, wlimit);
-    wuffs_base__io_writer dst_writer =
-        wuffs_base__io_buffer__writer(&limited_dst);
     wuffs_base__io_buffer limited_src = make_limited_reader(*src, rlimit);
-    wuffs_base__io_reader src_reader =
-        wuffs_base__io_buffer__reader(&limited_src);
 
     status = wuffs_deflate__decoder__decode_io_writer(
-        &dec, dst_writer, src_reader, global_work_slice);
+        &dec, &limited_dst, &limited_src, global_work_slice);
 
     dst->meta.wi += limited_dst.meta.wi;
     src->meta.ri += limited_src.meta.ri;
@@ -268,9 +264,6 @@
     return status;
   }
 
-  wuffs_base__io_writer dst_writer = wuffs_base__io_buffer__writer(&got);
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-
   int i;
   for (i = 1; i < 32; i++) {
     size_t split = gt->src_offset0 + i;
@@ -291,13 +284,13 @@
     src.meta.ri = gt->src_offset0;
     src.meta.wi = split;
     const char* z0 = wuffs_deflate__decoder__decode_io_writer(
-        &dec, dst_writer, src_reader, global_work_slice);
+        &dec, &got, &src, global_work_slice);
 
     src.meta.closed = true;
     src.meta.ri = split;
     src.meta.wi = gt->src_offset1;
     const char* z1 = wuffs_deflate__decoder__decode_io_writer(
-        &dec, dst_writer, src_reader, global_work_slice);
+        &dec, &got, &src, global_work_slice);
 
     if (z0 != wuffs_base__suspension__short_read) {
       RETURN_FAIL("i=%d: z0: got \"%s\", want \"%s\"", i, z0,
@@ -332,14 +325,11 @@
   got->meta.wi = 0;
 
   wuffs_base__io_buffer limited_got = make_limited_writer(*got, wlimit);
-  wuffs_base__io_writer dst_writer =
-      wuffs_base__io_buffer__writer(&limited_got);
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(src);
 
   dec->private_impl.f_history_index = starting_history_index;
 
   const char* got_z = wuffs_deflate__decoder__decode_io_writer(
-      dec, dst_writer, src_reader, global_work_slice);
+      dec, &limited_got, src, global_work_slice);
   got->meta.wi += limited_got.meta.wi;
   if (got_z != want_z) {
     RETURN_FAIL("i=%d: starting_history_index=0x%04" PRIX32
diff --git a/test/c/std/gif.c b/test/c/std/gif.c
index d09b35b..ceae7c6 100644
--- a/test/c/std/gif.c
+++ b/test/c/std/gif.c
@@ -203,8 +203,7 @@
 
   wuffs_base__image_config ic = ((wuffs_base__image_config){});
   wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(src);
-  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src);
   if (status) {
     return status;
   }
@@ -222,15 +221,15 @@
   }
 
   while (true) {
-    status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+    status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src);
     if (status == wuffs_base__warning__end_of_data) {
       break;
     } else if (status) {
       return status;
     }
 
-    status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader,
-                                              global_work_slice, NULL);
+    status = wuffs_gif__decoder__decode_frame(&dec, &pb, src, global_work_slice,
+                                              NULL);
     if (status) {
       return status;
     }
@@ -274,8 +273,7 @@
 
   {
     wuffs_base__image_config ic = ((wuffs_base__image_config){});
-    wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
     if (status) {
       RETURN_FAIL("decode_image_config: got \"%s\"", status);
     }
@@ -323,11 +321,9 @@
   while (true) {
     num_iters++;
     wuffs_base__io_buffer limited_src = make_limited_reader(src, rlimit);
-    wuffs_base__io_reader src_reader =
-        wuffs_base__io_buffer__reader(&limited_src);
     size_t old_ri = src.meta.ri;
 
-    status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+    status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, &limited_src);
     src.meta.ri += limited_src.meta.ri;
 
     if (!status) {
@@ -349,12 +345,10 @@
   while (true) {
     num_iters++;
     wuffs_base__io_buffer limited_src = make_limited_reader(src, rlimit);
-    wuffs_base__io_reader src_reader =
-        wuffs_base__io_buffer__reader(&limited_src);
     size_t old_ri = src.meta.ri;
 
     const char* status = wuffs_gif__decoder__decode_frame(
-        &dec, &pb, src_reader, global_work_slice, NULL);
+        &dec, &pb, &limited_src, global_work_slice, NULL);
     src.meta.ri += limited_src.meta.ri;
 
     if (!status) {
@@ -483,8 +477,7 @@
     if (src.meta.ri == src.meta.wi) {
       RETURN_FAIL("decode_frame returned \"ok\" but src was exhausted");
     }
-    wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-    status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader,
+    status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
                                               global_work_slice, NULL);
     if (status != wuffs_base__warning__end_of_data) {
       RETURN_FAIL("decode_frame: got \"%s\", want \"%s\"", status,
@@ -515,9 +508,8 @@
   }
 
   wuffs_base__image_config ic = ((wuffs_base__image_config){});
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
 
-  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
   if (status) {
     RETURN_FAIL("decode_image_config: got \"%s\"", status);
   }
@@ -529,8 +521,8 @@
     RETURN_FAIL("set_from_slice: \"%s\"", status);
   }
 
-  status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader,
-                                            global_work_slice, NULL);
+  status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src, global_work_slice,
+                                            NULL);
   if (status != want_status) {
     RETURN_FAIL("decode_frame: got \"%s\", want \"%s\"", status, want_status);
   }
@@ -567,10 +559,7 @@
 
   {
     wuffs_base__io_buffer limited_src = make_limited_reader(src, 700);
-    wuffs_base__io_reader src_reader =
-        wuffs_base__io_buffer__reader(&limited_src);
-
-    status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, src_reader);
+    status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, &limited_src);
     src.meta.ri += limited_src.meta.ri;
     if (status != wuffs_base__suspension__short_read) {
       RETURN_FAIL("decode_frame_config: got \"%s\", want \"%s\"", status,
@@ -583,9 +572,7 @@
   // wuffs_base__error__interleaved_coroutine_calls.
 
   {
-    wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-
-    status = wuffs_gif__decoder__decode_image_config(&dec, NULL, src_reader);
+    status = wuffs_gif__decoder__decode_image_config(&dec, NULL, &src);
     if (status != wuffs_base__error__interleaved_coroutine_calls) {
       RETURN_FAIL("decode_image_config: got \"%s\", want \"%s\"", status,
                   wuffs_base__error__interleaved_coroutine_calls);
@@ -615,14 +602,12 @@
     RETURN_FAIL("initialize: \"%s\"", status);
   }
 
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-
-  status = wuffs_gif__decoder__decode_image_config(&dec, NULL, src_reader);
+  status = wuffs_gif__decoder__decode_image_config(&dec, NULL, &src);
   if (status) {
     RETURN_FAIL("decode_image_config: got \"%s\"", status);
   }
 
-  status = wuffs_gif__decoder__decode_image_config(&dec, NULL, src_reader);
+  status = wuffs_gif__decoder__decode_image_config(&dec, NULL, &src);
   if (status != wuffs_base__error__bad_call_sequence) {
     RETURN_FAIL("decode_image_config: got \"%s\", want \"%s\"", status,
                 wuffs_base__error__bad_call_sequence);
@@ -653,9 +638,8 @@
   }
 
   wuffs_base__image_config ic = ((wuffs_base__image_config){});
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
 
-  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
   if (status) {
     RETURN_FAIL("decode_image_config: got \"%s\"", status);
   }
@@ -676,7 +660,7 @@
   uint32_t i;
   for (i = 0; i < want_num_frames; i++) {
     wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
-    status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+    status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, &src);
     if (status) {
       RETURN_FAIL("decode_frame_config #%" PRIu32 ": got \"%s\"", i, status);
     }
@@ -694,7 +678,7 @@
       }
     }
 
-    status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader,
+    status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
                                               global_work_slice, NULL);
     if (status) {
       RETURN_FAIL("decode_frame #%" PRIu32 ": got \"%s\"", i, status);
@@ -711,7 +695,7 @@
   // There should be no more frames, no matter how many times we call
   // decode_frame.
   for (i = 0; i < 3; i++) {
-    status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader,
+    status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
                                               global_work_slice, NULL);
     if (status != wuffs_base__warning__end_of_data) {
       RETURN_FAIL("decode_frame: got \"%s\", want \"%s\"", status,
@@ -795,8 +779,7 @@
         &dec, wuffs_gif__quirk_delay_num_decoded_frames, q);
 
     while (true) {
-      status = wuffs_gif__decoder__decode_frame_config(
-          &dec, NULL, wuffs_base__io_buffer__reader(&src));
+      status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, &src);
       if (status) {
         break;
       }
@@ -837,8 +820,7 @@
         &dec, wuffs_gif__quirk_reject_empty_palette, q);
 
     wuffs_base__image_config ic = ((wuffs_base__image_config){});
-    status = wuffs_gif__decoder__decode_image_config(
-        &dec, &ic, wuffs_base__io_buffer__reader(&src));
+    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
     if (status) {
       RETURN_FAIL("q=%d: decode_image_config: \"%s\"", q, status);
     }
@@ -852,9 +834,8 @@
 
     int i;
     for (i = 0; i < 2; i++) {
-      status = wuffs_gif__decoder__decode_frame(
-          &dec, &pb, wuffs_base__io_buffer__reader(&src), global_work_slice,
-          NULL);
+      status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
+                                                global_work_slice, NULL);
       if ((q == 1) && (i == 1)) {
         if (status != wuffs_gif__error__bad_palette) {
           RETURN_FAIL("q=%d: i=%d: decode_frame: got \"%s\", want \"%s\"", q, i,
@@ -910,8 +891,7 @@
         &dec, wuffs_gif__quirk_honor_background_color, q);
 
     wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
-    wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-    status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+    status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, &src);
     if (status) {
       RETURN_FAIL("q=%d: decode_frame_config: \"%s\"", q, status);
     }
@@ -952,8 +932,7 @@
         &dec, wuffs_gif__quirk_honor_background_color, q);
 
     wuffs_base__image_config ic = ((wuffs_base__image_config){});
-    wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
     if (status) {
       RETURN_FAIL("q=%d: decode_image_config: \"%s\"", q, status);
     }
@@ -995,8 +974,7 @@
         &dec, wuffs_gif__quirk_image_bounds_are_strict, q);
 
     wuffs_base__image_config ic = ((wuffs_base__image_config){});
-    wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
     if (status) {
       RETURN_FAIL("q=%d: decode_image_config: \"%s\"", q, status);
     }
@@ -1046,7 +1024,7 @@
     for (i = 0; true; i++) {
       wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
       {
-        status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+        status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, &src);
         if (i == WUFFS_TESTLIB_ARRAY_SIZE(want_frame_config_bounds)) {
           if (status != wuffs_base__warning__end_of_data) {
             RETURN_FAIL("q=%d: decode_frame_config #%" PRIu32 ": got \"%s\"", q,
@@ -1081,7 +1059,7 @@
           }
         }
 
-        status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader,
+        status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
                                                   global_work_slice, NULL);
         if (status) {
           RETURN_FAIL("q=%d: decode_frame #%" PRIu32 ": got \"%s\"", q, i,
@@ -1159,8 +1137,7 @@
     }
 
     wuffs_base__image_config ic = ((wuffs_base__image_config){});
-    status = wuffs_gif__decoder__decode_image_config(
-        &dec, &ic, wuffs_base__io_buffer__reader(&src));
+    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
     if (status) {
       RETURN_FAIL("q=%d: decode_image_config: \"%s\"", q, status);
     }
@@ -1172,9 +1149,8 @@
       RETURN_FAIL("q=%d: set_from_slice: \"%s\"", q, status);
     }
 
-    const char* got = wuffs_gif__decoder__decode_frame(
-        &dec, &pb, wuffs_base__io_buffer__reader(&src), global_work_slice,
-        NULL);
+    const char* got = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
+                                                       global_work_slice, NULL);
     if (got != want) {
       RETURN_FAIL("q=%d: decode_frame: got \"%s\", want \"%s\"", q, got, want);
     }
@@ -1270,9 +1246,8 @@
     RETURN_FAIL("initialize: \"%s\"", status);
   }
   wuffs_base__image_config ic = ((wuffs_base__image_config){});
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
 
-  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
   if (status != wuffs_gif__error__bad_header) {
     RETURN_FAIL("decode_image_config: got \"%s\", want \"%s\"", status,
                 wuffs_gif__error__bad_header);
@@ -1320,8 +1295,7 @@
       src.meta.ri = 0;
 
       while (true) {
-        status = wuffs_gif__decoder__decode_image_config(
-            &dec, &ic, wuffs_base__io_buffer__reader(&src));
+        status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
         if (!status) {
           break;
         } else if (status != wuffs_base__warning__metadata_reported) {
@@ -1369,8 +1343,7 @@
           got_length += n;
           src.meta.ri += n;
 
-          status = wuffs_gif__decoder__ack_metadata_chunk(
-              &dec, wuffs_base__io_buffer__reader(&src));
+          status = wuffs_gif__decoder__ack_metadata_chunk(&dec, &src);
           if (!status) {
             break;
           } else if (status != wuffs_base__warning__metadata_reported) {
@@ -1419,8 +1392,7 @@
 
       {
         wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
-        status = wuffs_gif__decoder__decode_frame_config(
-            &dec, &fc, wuffs_base__io_buffer__reader(&src));
+        status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, &src);
         if (status) {
           RETURN_FAIL("decode_frame_config (iccp=%d, xmp=%d): %s", iccp, xmp,
                       status);
@@ -1481,8 +1453,7 @@
     RETURN_FAIL("initialize: \"%s\"", status);
   }
   wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-  status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+  status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, &src);
   if (status) {
     RETURN_FAIL("decode_frame_config: \"%s\"", status);
   }
@@ -1515,8 +1486,7 @@
     RETURN_FAIL("initialize: \"%s\"", status);
   }
   wuffs_base__image_config ic = ((wuffs_base__image_config){});
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
   if (status) {
     RETURN_FAIL("decode_image_config: \"%s\"", status);
   }
@@ -1531,7 +1501,7 @@
   uint32_t i;
   for (i = 0; true; i++) {
     {
-      status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, src_reader);
+      status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, &src);
       if (i == WUFFS_TESTLIB_ARRAY_SIZE(want_num_animation_loops)) {
         if (status != wuffs_base__warning__end_of_data) {
           RETURN_FAIL("decode_frame_config #%" PRIu32 ": got \"%s\"", i,
@@ -1652,8 +1622,7 @@
   }
 
   wuffs_base__image_config ic = ((wuffs_base__image_config){});
-  status = wuffs_gif__decoder__decode_image_config(
-      &dec, &ic, wuffs_base__io_buffer__reader(&src));
+  status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
   if (status) {
     RETURN_FAIL("decode_image_config: \"%s\"", status);
   }
@@ -1675,10 +1644,8 @@
 
   while (true) {
     wuffs_base__io_buffer limited_src = make_limited_reader(src, 1);
-    wuffs_base__io_reader src_reader =
-        wuffs_base__io_buffer__reader(&limited_src);
 
-    status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader,
+    status = wuffs_gif__decoder__decode_frame(&dec, &pb, &limited_src,
                                               global_work_slice, NULL);
     src.meta.ri += limited_src.meta.ri;
 
@@ -1718,12 +1685,11 @@
   if (status) {
     RETURN_FAIL("initialize: \"%s\"", status);
   }
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
 
   wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
   if (!frame_config) {
     wuffs_base__image_config ic = ((wuffs_base__image_config){});
-    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
     if (status) {
       RETURN_FAIL("decode_image_config: \"%s\"", status);
     }
@@ -1753,9 +1719,9 @@
 
     const char* status = NULL;
     if (frame_config) {
-      status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, src_reader);
+      status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, &src);
     } else {
-      status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader,
+      status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
                                                 global_work_slice, NULL);
     }
 
@@ -1801,8 +1767,6 @@
     RETURN_FAIL("initialize: \"%s\"", status);
   }
 
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-
   if (chunked) {
     if (src.meta.wi < 50) {
       RETURN_FAIL("src is too short");
@@ -1812,7 +1776,7 @@
     src.meta.wi = 30;
     src.meta.closed = false;
 
-    status = wuffs_gif__decoder__decode_image_config(&dec, NULL, src_reader);
+    status = wuffs_gif__decoder__decode_image_config(&dec, NULL, &src);
     if (status != wuffs_base__suspension__short_read) {
       RETURN_FAIL("decode_image_config (chunked): \"%s\"", status);
     }
@@ -1829,7 +1793,7 @@
     }
   }
 
-  status = wuffs_gif__decoder__decode_image_config(&dec, NULL, src_reader);
+  status = wuffs_gif__decoder__decode_image_config(&dec, NULL, &src);
   if (status) {
     RETURN_FAIL("decode_image_config: \"%s\"", status);
   }
@@ -1840,7 +1804,7 @@
   int i;
   for (i = 0; i < 4; i++) {
     fcs[i] = ((wuffs_base__frame_config){});
-    status = wuffs_gif__decoder__decode_frame_config(&dec, &fcs[i], src_reader);
+    status = wuffs_gif__decoder__decode_frame_config(&dec, &fcs[i], &src);
     if (status) {
       RETURN_FAIL("decode_frame_config #%d: \"%s\"", i, status);
     }
@@ -1885,7 +1849,7 @@
     }
   }
 
-  status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, src_reader);
+  status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, &src);
   if (status != wuffs_base__warning__end_of_data) {
     RETURN_FAIL("decode_frame_config EOD: \"%s\"", status);
   }
@@ -1909,7 +1873,7 @@
     int j;
     for (j = i; j < 4; j++) {
       wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
-      status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+      status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, &src);
       if (status) {
         RETURN_FAIL("decode_frame_config #%d, #%d: \"%s\"", i, j, status);
       }
@@ -1929,7 +1893,7 @@
       }
     }
 
-    status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, src_reader);
+    status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, &src);
     if (status != wuffs_base__warning__end_of_data) {
       RETURN_FAIL("decode_frame_config EOD #%d: \"%s\"", i, status);
     }
diff --git a/test/c/std/gzip.c b/test/c/std/gzip.c
index 9b53bb1..89e14c8 100644
--- a/test/c/std/gzip.c
+++ b/test/c/std/gzip.c
@@ -97,14 +97,10 @@
 
   while (true) {
     wuffs_base__io_buffer limited_dst = make_limited_writer(*dst, wlimit);
-    wuffs_base__io_writer dst_writer =
-        wuffs_base__io_buffer__writer(&limited_dst);
     wuffs_base__io_buffer limited_src = make_limited_reader(*src, rlimit);
-    wuffs_base__io_reader src_reader =
-        wuffs_base__io_buffer__reader(&limited_src);
 
-    status = wuffs_gzip__decoder__decode_io_writer(&dec, dst_writer, src_reader,
-                                                   global_work_slice);
+    status = wuffs_gzip__decoder__decode_io_writer(
+        &dec, &limited_dst, &limited_src, global_work_slice);
 
     dst->meta.wi += limited_dst.meta.wi;
     src->meta.ri += limited_src.meta.ri;
@@ -152,7 +148,6 @@
     }
     wuffs_gzip__decoder__set_ignore_checksum(&dec, ignore_checksum);
     got.meta.wi = 0;
-    wuffs_base__io_writer got_writer = wuffs_base__io_buffer__writer(&got);
     src.meta.ri = 0;
 
     // Decode the src data in 1 or 2 chunks, depending on whether end_limit is
@@ -177,11 +172,8 @@
       }
 
       wuffs_base__io_buffer limited_src = make_limited_reader(src, rlimit);
-      wuffs_base__io_reader src_reader =
-          wuffs_base__io_buffer__reader(&limited_src);
-
       const char* got_z = wuffs_gzip__decoder__decode_io_writer(
-          &dec, got_writer, src_reader, global_work_slice);
+          &dec, &got, &limited_src, global_work_slice);
       src.meta.ri += limited_src.meta.ri;
       if (got_z != want_z) {
         RETURN_FAIL("end_limit=%d: got \"%s\", want \"%s\"", end_limit, got_z,
diff --git a/test/c/std/lzw.c b/test/c/std/lzw.c
index 1b6a9be..f156e8e 100644
--- a/test/c/std/lzw.c
+++ b/test/c/std/lzw.c
@@ -119,16 +119,12 @@
   while (true) {
     num_iters++;
     wuffs_base__io_buffer limited_got = make_limited_writer(got, wlimit);
-    wuffs_base__io_writer got_writer =
-        wuffs_base__io_buffer__writer(&limited_got);
     wuffs_base__io_buffer limited_src = make_limited_reader(src, rlimit);
-    wuffs_base__io_reader src_reader =
-        wuffs_base__io_buffer__reader(&limited_src);
     size_t old_wi = got.meta.wi;
     size_t old_ri = src.meta.ri;
 
-    status = wuffs_lzw__decoder__decode_io_writer(&dec, got_writer, src_reader,
-                                                  global_work_slice);
+    status = wuffs_lzw__decoder__decode_io_writer(
+        &dec, &limited_got, &limited_src, global_work_slice);
     got.meta.wi += limited_got.meta.wi;
     src.meta.ri += limited_src.meta.ri;
     if (!status) {
@@ -235,9 +231,8 @@
   }
   wuffs_lzw__decoder__set_literal_width(&dec, 7);
 
-  status = wuffs_lzw__decoder__decode_io_writer(
-      &dec, wuffs_base__io_buffer__writer(&got),
-      wuffs_base__io_buffer__reader(&src), global_work_slice);
+  status =
+      wuffs_lzw__decoder__decode_io_writer(&dec, &got, &src, global_work_slice);
   if (status != wuffs_lzw__error__bad_code) {
     RETURN_FAIL("decode: \"%s\"", status);
   }
@@ -280,9 +275,8 @@
   }
   wuffs_lzw__decoder__set_literal_width(&dec, 8);
 
-  status = wuffs_lzw__decoder__decode_io_writer(
-      &dec, wuffs_base__io_buffer__writer(&got),
-      wuffs_base__io_buffer__reader(&src), global_work_slice);
+  status =
+      wuffs_lzw__decoder__decode_io_writer(&dec, &got, &src, global_work_slice);
   if (status) {
     RETURN_FAIL("decode: \"%s\"", status);
   }
@@ -311,9 +305,8 @@
   wuffs_base__io_buffer got = ((wuffs_base__io_buffer){
       .data = global_got_slice,
   });
-  status = wuffs_lzw__decoder__decode_io_writer(
-      &dec, wuffs_base__io_buffer__writer(&got),
-      wuffs_base__io_buffer__reader(&src), global_work_slice);
+  status =
+      wuffs_lzw__decoder__decode_io_writer(&dec, &got, &src, global_work_slice);
   if (status) {
     RETURN_FAIL("decode: \"%s\"", status);
   }
@@ -394,8 +387,6 @@
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
       .data = global_src_slice,
   });
-  wuffs_base__io_writer got_writer = wuffs_base__io_buffer__writer(&got);
-  wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
 
   const char* status = read_file(&src, filename);
   if (status) {
@@ -424,7 +415,7 @@
     if (status) {
       RETURN_FAIL("initialize: \"%s\"", status);
     }
-    status = wuffs_lzw__decoder__decode_io_writer(&dec, got_writer, src_reader,
+    status = wuffs_lzw__decoder__decode_io_writer(&dec, &got, &src,
                                                   global_work_slice);
     if (status) {
       RETURN_FAIL("decode: \"%s\"", status);
diff --git a/test/c/std/zlib.c b/test/c/std/zlib.c
index e49d171..93fa7b2 100644
--- a/test/c/std/zlib.c
+++ b/test/c/std/zlib.c
@@ -97,14 +97,10 @@
 
   while (true) {
     wuffs_base__io_buffer limited_dst = make_limited_writer(*dst, wlimit);
-    wuffs_base__io_writer dst_writer =
-        wuffs_base__io_buffer__writer(&limited_dst);
     wuffs_base__io_buffer limited_src = make_limited_reader(*src, rlimit);
-    wuffs_base__io_reader src_reader =
-        wuffs_base__io_buffer__reader(&limited_src);
 
-    status = wuffs_zlib__decoder__decode_io_writer(&dec, dst_writer, src_reader,
-                                                   global_work_slice);
+    status = wuffs_zlib__decoder__decode_io_writer(
+        &dec, &limited_dst, &limited_src, global_work_slice);
 
     dst->meta.wi += limited_dst.meta.wi;
     src->meta.ri += limited_src.meta.ri;
@@ -151,7 +147,6 @@
     }
     wuffs_zlib__decoder__set_ignore_checksum(&dec, ignore_checksum);
     got.meta.wi = 0;
-    wuffs_base__io_writer got_writer = wuffs_base__io_buffer__writer(&got);
     src.meta.ri = 0;
 
     // Decode the src data in 1 or 2 chunks, depending on whether end_limit is
@@ -176,11 +171,9 @@
       }
 
       wuffs_base__io_buffer limited_src = make_limited_reader(src, rlimit);
-      wuffs_base__io_reader src_reader =
-          wuffs_base__io_buffer__reader(&limited_src);
 
       const char* got_z = wuffs_zlib__decoder__decode_io_writer(
-          &dec, got_writer, src_reader, global_work_slice);
+          &dec, &got, &limited_src, global_work_slice);
       src.meta.ri += limited_src.meta.ri;
       if (got_z != want_z) {
         RETURN_FAIL("end_limit=%d: got \"%s\", want \"%s\"", end_limit, got_z,