base: compact returns the change in writer length
diff --git a/internal/cgen/base/io-public.h b/internal/cgen/base/io-public.h
index c879f3b..5f6ae61 100644
--- a/internal/cgen/base/io-public.h
+++ b/internal/cgen/base/io-public.h
@@ -31,8 +31,8 @@
 
 #ifdef __cplusplus
   inline bool is_valid() const;
-  inline void compact();
-  inline void compact_retaining(uint64_t history_retain_length);
+  inline size_t compact();
+  inline size_t compact_retaining(uint64_t history_retain_length);
   inline size_t reader_length() const;
   inline uint8_t* reader_pointer() const;
   inline uint64_t reader_position() const;
@@ -151,11 +151,14 @@
 
 // wuffs_base__io_buffer__compact moves any written but unread bytes to the
 // start of the buffer.
-static inline void  //
+//
+// It returns the increase in the writer length: how much meta.wi fell by.
+static inline size_t  //
 wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
   if (!buf || (buf->meta.ri == 0)) {
-    return;
+    return 0;
   }
+  size_t old_ri = buf->meta.ri;
   buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);
   size_t new_wi = buf->meta.wi - buf->meta.ri;
   if (new_wi != 0) {
@@ -163,6 +166,7 @@
   }
   buf->meta.wi = new_wi;
   buf->meta.ri = 0;
+  return old_ri;
 }
 
 // wuffs_base__io_buffer__compact_retaining moves any written but unread bytes
@@ -171,6 +175,8 @@
 // It is therefore a no-op if history_retain_length is UINT64_MAX. A
 // postcondition is that buf->meta.ri == H.
 //
+// It returns the increase in the writer length: how much meta.wi fell by.
+//
 // wuffs_base__io_buffer__compact_retaining(0) is equivalent to
 // wuffs_base__io_buffer__compact().
 //
@@ -184,16 +190,16 @@
 //
 // Then, depending on history_retain_length, the resultant buf would be:
 //
-// HRL = 0     defgh?????    ri = 0    wi = 5    pos = 903
-// HRL = 1     cdefgh????    ri = 1    wi = 6    pos = 902
-// HRL = 2     bcdefgh???    ri = 2    wi = 7    pos = 901
-// HRL = 3     abcdefgh??    ri = 3    wi = 8    pos = 900
-// HRL = 4+    abcdefgh??    ri = 3    wi = 8    pos = 900
-static inline void  //
+// HRL = 0     defgh?????    ri = 0    wi = 5    pos = 903    return = 3
+// HRL = 1     cdefgh????    ri = 1    wi = 6    pos = 902    return = 2
+// HRL = 2     bcdefgh???    ri = 2    wi = 7    pos = 901    return = 1
+// HRL = 3     abcdefgh??    ri = 3    wi = 8    pos = 900    return = 0
+// HRL = 4+    abcdefgh??    ri = 3    wi = 8    pos = 900    return = 0
+static inline size_t  //
 wuffs_base__io_buffer__compact_retaining(wuffs_base__io_buffer* buf,
                                          uint64_t history_retain_length) {
   if (!buf || (buf->meta.ri == 0)) {
-    return;
+    return 0;
   }
   size_t old_ri = buf->meta.ri;
   size_t new_ri = (size_t)(wuffs_base__u64__min(old_ri, history_retain_length));
@@ -205,6 +211,7 @@
   }
   buf->meta.wi = new_wi;
   buf->meta.ri = new_ri;
+  return memmove_start;
 }
 
 static inline size_t  //
@@ -260,14 +267,14 @@
   return wuffs_base__io_buffer__is_valid(this);
 }
 
-inline void  //
+inline size_t  //
 wuffs_base__io_buffer::compact() {
-  wuffs_base__io_buffer__compact(this);
+  return wuffs_base__io_buffer__compact(this);
 }
 
-inline void  //
+inline size_t  //
 wuffs_base__io_buffer::compact_retaining(uint64_t history_retain_length) {
-  wuffs_base__io_buffer__compact_retaining(this, history_retain_length);
+  return wuffs_base__io_buffer__compact_retaining(this, history_retain_length);
 }
 
 inline size_t  //
diff --git a/internal/cgen/base/token-public.h b/internal/cgen/base/token-public.h
index f4d6551..1ed6f88 100644
--- a/internal/cgen/base/token-public.h
+++ b/internal/cgen/base/token-public.h
@@ -340,8 +340,8 @@
 
 #ifdef __cplusplus
   inline bool is_valid() const;
-  inline void compact();
-  inline void compact_retaining(uint64_t history_retain_length);
+  inline size_t compact();
+  inline size_t compact_retaining(uint64_t history_retain_length);
   inline uint64_t reader_length() const;
   inline wuffs_base__token* reader_pointer() const;
   inline wuffs_base__slice_token reader_slice() const;
@@ -436,11 +436,14 @@
 
 // wuffs_base__token_buffer__compact moves any written but unread tokens to the
 // start of the buffer.
-static inline void  //
+//
+// It returns the increase in the writer length: how much meta.wi fell by.
+static inline size_t  //
 wuffs_base__token_buffer__compact(wuffs_base__token_buffer* buf) {
   if (!buf || (buf->meta.ri == 0)) {
-    return;
+    return 0;
   }
+  size_t old_ri = buf->meta.ri;
   buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);
   size_t new_wi = buf->meta.wi - buf->meta.ri;
   if (new_wi != 0) {
@@ -449,6 +452,7 @@
   }
   buf->meta.wi = new_wi;
   buf->meta.ri = 0;
+  return old_ri;
 }
 
 // wuffs_base__token_buffer__compact_retaining moves any written but unread
@@ -457,6 +461,8 @@
 // history_retain_length). It is therefore a no-op if history_retain_length is
 // UINT64_MAX. A postcondition is that buf->meta.ri == H.
 //
+// It returns the increase in the writer length: how much meta.wi fell by.
+//
 // wuffs_base__token_buffer__compact_retaining(0) is equivalent to
 // wuffs_base__token_buffer__compact().
 //
@@ -470,16 +476,16 @@
 //
 // Then, depending on history_retain_length, the resultant buf would be:
 //
-// HRL = 0     defgh?????    ri = 0    wi = 5    pos = 903
-// HRL = 1     cdefgh????    ri = 1    wi = 6    pos = 902
-// HRL = 2     bcdefgh???    ri = 2    wi = 7    pos = 901
-// HRL = 3     abcdefgh??    ri = 3    wi = 8    pos = 900
-// HRL = 4+    abcdefgh??    ri = 3    wi = 8    pos = 900
-static inline void  //
+// HRL = 0     defgh?????    ri = 0    wi = 5    pos = 903    return = 3
+// HRL = 1     cdefgh????    ri = 1    wi = 6    pos = 902    return = 2
+// HRL = 2     bcdefgh???    ri = 2    wi = 7    pos = 901    return = 1
+// HRL = 3     abcdefgh??    ri = 3    wi = 8    pos = 900    return = 0
+// HRL = 4+    abcdefgh??    ri = 3    wi = 8    pos = 900    return = 0
+static inline size_t  //
 wuffs_base__token_buffer__compact_retaining(wuffs_base__token_buffer* buf,
                                             uint64_t history_retain_length) {
   if (!buf || (buf->meta.ri == 0)) {
-    return;
+    return 0;
   }
   size_t old_ri = buf->meta.ri;
   size_t new_ri = (size_t)(wuffs_base__u64__min(old_ri, history_retain_length));
@@ -492,6 +498,7 @@
   }
   buf->meta.wi = new_wi;
   buf->meta.ri = new_ri;
+  return memmove_start;
 }
 
 static inline uint64_t  //
@@ -547,14 +554,15 @@
   return wuffs_base__token_buffer__is_valid(this);
 }
 
-inline void  //
+inline size_t  //
 wuffs_base__token_buffer::compact() {
-  wuffs_base__token_buffer__compact(this);
+  return wuffs_base__token_buffer__compact(this);
 }
 
-inline void  //
+inline size_t  //
 wuffs_base__token_buffer::compact_retaining(uint64_t history_retain_length) {
-  wuffs_base__token_buffer__compact_retaining(this, history_retain_length);
+  return wuffs_base__token_buffer__compact_retaining(this,
+                                                     history_retain_length);
 }
 
 inline uint64_t  //
diff --git a/internal/cgen/drop-in/stb.c b/internal/cgen/drop-in/stb.c
index 9742eeb..96487bf 100644
--- a/internal/cgen/drop-in/stb.c
+++ b/internal/cgen/drop-in/stb.c
@@ -169,9 +169,7 @@
       return NULL;
     }
 
-    size_t wl = wuffs_base__io_buffer__writer_length(srcbuf);
-    wuffs_base__io_buffer__compact(srcbuf);
-    if (wl >= wuffs_base__io_buffer__writer_length(srcbuf)) {
+    if (wuffs_base__io_buffer__compact(srcbuf) <= 0) {
       wuffs_drop_in__stb__g_failure_reason = "I/O buffer is too small";
       return NULL;
     }
@@ -238,9 +236,7 @@
       return NULL;
     }
 
-    size_t wl = wuffs_base__io_buffer__writer_length(srcbuf);
-    wuffs_base__io_buffer__compact(srcbuf);
-    if (wl >= wuffs_base__io_buffer__writer_length(srcbuf)) {
+    if (wuffs_base__io_buffer__compact(srcbuf) <= 0) {
       free(workbuf_ptr);
       free(pixbuf_ptr);
       wuffs_drop_in__stb__g_failure_reason = "I/O buffer is too small";
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 1eae7f9..e2c3b7a 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -3116,8 +3116,8 @@
 
 #ifdef __cplusplus
   inline bool is_valid() const;
-  inline void compact();
-  inline void compact_retaining(uint64_t history_retain_length);
+  inline size_t compact();
+  inline size_t compact_retaining(uint64_t history_retain_length);
   inline size_t reader_length() const;
   inline uint8_t* reader_pointer() const;
   inline uint64_t reader_position() const;
@@ -3236,11 +3236,14 @@
 
 // wuffs_base__io_buffer__compact moves any written but unread bytes to the
 // start of the buffer.
-static inline void  //
+//
+// It returns the increase in the writer length: how much meta.wi fell by.
+static inline size_t  //
 wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
   if (!buf || (buf->meta.ri == 0)) {
-    return;
+    return 0;
   }
+  size_t old_ri = buf->meta.ri;
   buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);
   size_t new_wi = buf->meta.wi - buf->meta.ri;
   if (new_wi != 0) {
@@ -3248,6 +3251,7 @@
   }
   buf->meta.wi = new_wi;
   buf->meta.ri = 0;
+  return old_ri;
 }
 
 // wuffs_base__io_buffer__compact_retaining moves any written but unread bytes
@@ -3256,6 +3260,8 @@
 // It is therefore a no-op if history_retain_length is UINT64_MAX. A
 // postcondition is that buf->meta.ri == H.
 //
+// It returns the increase in the writer length: how much meta.wi fell by.
+//
 // wuffs_base__io_buffer__compact_retaining(0) is equivalent to
 // wuffs_base__io_buffer__compact().
 //
@@ -3269,16 +3275,16 @@
 //
 // Then, depending on history_retain_length, the resultant buf would be:
 //
-// HRL = 0     defgh?????    ri = 0    wi = 5    pos = 903
-// HRL = 1     cdefgh????    ri = 1    wi = 6    pos = 902
-// HRL = 2     bcdefgh???    ri = 2    wi = 7    pos = 901
-// HRL = 3     abcdefgh??    ri = 3    wi = 8    pos = 900
-// HRL = 4+    abcdefgh??    ri = 3    wi = 8    pos = 900
-static inline void  //
+// HRL = 0     defgh?????    ri = 0    wi = 5    pos = 903    return = 3
+// HRL = 1     cdefgh????    ri = 1    wi = 6    pos = 902    return = 2
+// HRL = 2     bcdefgh???    ri = 2    wi = 7    pos = 901    return = 1
+// HRL = 3     abcdefgh??    ri = 3    wi = 8    pos = 900    return = 0
+// HRL = 4+    abcdefgh??    ri = 3    wi = 8    pos = 900    return = 0
+static inline size_t  //
 wuffs_base__io_buffer__compact_retaining(wuffs_base__io_buffer* buf,
                                          uint64_t history_retain_length) {
   if (!buf || (buf->meta.ri == 0)) {
-    return;
+    return 0;
   }
   size_t old_ri = buf->meta.ri;
   size_t new_ri = (size_t)(wuffs_base__u64__min(old_ri, history_retain_length));
@@ -3290,6 +3296,7 @@
   }
   buf->meta.wi = new_wi;
   buf->meta.ri = new_ri;
+  return memmove_start;
 }
 
 static inline size_t  //
@@ -3345,14 +3352,14 @@
   return wuffs_base__io_buffer__is_valid(this);
 }
 
-inline void  //
+inline size_t  //
 wuffs_base__io_buffer::compact() {
-  wuffs_base__io_buffer__compact(this);
+  return wuffs_base__io_buffer__compact(this);
 }
 
-inline void  //
+inline size_t  //
 wuffs_base__io_buffer::compact_retaining(uint64_t history_retain_length) {
-  wuffs_base__io_buffer__compact_retaining(this, history_retain_length);
+  return wuffs_base__io_buffer__compact_retaining(this, history_retain_length);
 }
 
 inline size_t  //
@@ -3729,8 +3736,8 @@
 
 #ifdef __cplusplus
   inline bool is_valid() const;
-  inline void compact();
-  inline void compact_retaining(uint64_t history_retain_length);
+  inline size_t compact();
+  inline size_t compact_retaining(uint64_t history_retain_length);
   inline uint64_t reader_length() const;
   inline wuffs_base__token* reader_pointer() const;
   inline wuffs_base__slice_token reader_slice() const;
@@ -3825,11 +3832,14 @@
 
 // wuffs_base__token_buffer__compact moves any written but unread tokens to the
 // start of the buffer.
-static inline void  //
+//
+// It returns the increase in the writer length: how much meta.wi fell by.
+static inline size_t  //
 wuffs_base__token_buffer__compact(wuffs_base__token_buffer* buf) {
   if (!buf || (buf->meta.ri == 0)) {
-    return;
+    return 0;
   }
+  size_t old_ri = buf->meta.ri;
   buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);
   size_t new_wi = buf->meta.wi - buf->meta.ri;
   if (new_wi != 0) {
@@ -3838,6 +3848,7 @@
   }
   buf->meta.wi = new_wi;
   buf->meta.ri = 0;
+  return old_ri;
 }
 
 // wuffs_base__token_buffer__compact_retaining moves any written but unread
@@ -3846,6 +3857,8 @@
 // history_retain_length). It is therefore a no-op if history_retain_length is
 // UINT64_MAX. A postcondition is that buf->meta.ri == H.
 //
+// It returns the increase in the writer length: how much meta.wi fell by.
+//
 // wuffs_base__token_buffer__compact_retaining(0) is equivalent to
 // wuffs_base__token_buffer__compact().
 //
@@ -3859,16 +3872,16 @@
 //
 // Then, depending on history_retain_length, the resultant buf would be:
 //
-// HRL = 0     defgh?????    ri = 0    wi = 5    pos = 903
-// HRL = 1     cdefgh????    ri = 1    wi = 6    pos = 902
-// HRL = 2     bcdefgh???    ri = 2    wi = 7    pos = 901
-// HRL = 3     abcdefgh??    ri = 3    wi = 8    pos = 900
-// HRL = 4+    abcdefgh??    ri = 3    wi = 8    pos = 900
-static inline void  //
+// HRL = 0     defgh?????    ri = 0    wi = 5    pos = 903    return = 3
+// HRL = 1     cdefgh????    ri = 1    wi = 6    pos = 902    return = 2
+// HRL = 2     bcdefgh???    ri = 2    wi = 7    pos = 901    return = 1
+// HRL = 3     abcdefgh??    ri = 3    wi = 8    pos = 900    return = 0
+// HRL = 4+    abcdefgh??    ri = 3    wi = 8    pos = 900    return = 0
+static inline size_t  //
 wuffs_base__token_buffer__compact_retaining(wuffs_base__token_buffer* buf,
                                             uint64_t history_retain_length) {
   if (!buf || (buf->meta.ri == 0)) {
-    return;
+    return 0;
   }
   size_t old_ri = buf->meta.ri;
   size_t new_ri = (size_t)(wuffs_base__u64__min(old_ri, history_retain_length));
@@ -3881,6 +3894,7 @@
   }
   buf->meta.wi = new_wi;
   buf->meta.ri = new_ri;
+  return memmove_start;
 }
 
 static inline uint64_t  //
@@ -3936,14 +3950,15 @@
   return wuffs_base__token_buffer__is_valid(this);
 }
 
-inline void  //
+inline size_t  //
 wuffs_base__token_buffer::compact() {
-  wuffs_base__token_buffer__compact(this);
+  return wuffs_base__token_buffer__compact(this);
 }
 
-inline void  //
+inline size_t  //
 wuffs_base__token_buffer::compact_retaining(uint64_t history_retain_length) {
-  wuffs_base__token_buffer__compact_retaining(this, history_retain_length);
+  return wuffs_base__token_buffer__compact_retaining(this,
+                                                     history_retain_length);
 }
 
 inline uint64_t  //
@@ -87662,9 +87677,7 @@
       return NULL;
     }
 
-    size_t wl = wuffs_base__io_buffer__writer_length(srcbuf);
-    wuffs_base__io_buffer__compact(srcbuf);
-    if (wl >= wuffs_base__io_buffer__writer_length(srcbuf)) {
+    if (wuffs_base__io_buffer__compact(srcbuf) <= 0) {
       wuffs_drop_in__stb__g_failure_reason = "I/O buffer is too small";
       return NULL;
     }
@@ -87731,9 +87744,7 @@
       return NULL;
     }
 
-    size_t wl = wuffs_base__io_buffer__writer_length(srcbuf);
-    wuffs_base__io_buffer__compact(srcbuf);
-    if (wl >= wuffs_base__io_buffer__writer_length(srcbuf)) {
+    if (wuffs_base__io_buffer__compact(srcbuf) <= 0) {
       free(workbuf_ptr);
       free(pixbuf_ptr);
       wuffs_drop_in__stb__g_failure_reason = "I/O buffer is too small";