std/lzw: add "#truncated input" error
name old speed new speed delta
wuffs_gif_decode_1k_bw/clang11 659MB/s ± 0% 748MB/s ± 0% +13.43% (p=0.008 n=5+5)
wuffs_gif_decode_1k_color_full_init/clang11 182MB/s ± 0% 178MB/s ± 0% -2.17% (p=0.008 n=5+5)
wuffs_gif_decode_1k_color_part_init/clang11 223MB/s ± 0% 219MB/s ± 0% -2.00% (p=0.008 n=5+5)
wuffs_gif_decode_10k_bgra/clang11 799MB/s ± 0% 795MB/s ± 0% -0.52% (p=0.008 n=5+5)
wuffs_gif_decode_10k_indexed/clang11 211MB/s ± 0% 210MB/s ± 0% -0.47% (p=0.008 n=5+5)
wuffs_gif_decode_20k/clang11 250MB/s ± 1% 254MB/s ± 0% +1.75% (p=0.008 n=5+5)
wuffs_gif_decode_100k_artificial/clang11 581MB/s ± 0% 568MB/s ± 0% -2.09% (p=0.008 n=5+5)
wuffs_gif_decode_100k_realistic/clang11 221MB/s ± 0% 221MB/s ± 0% ~ (p=0.690 n=5+5)
wuffs_gif_decode_1000k_full_init/clang11 222MB/s ± 0% 224MB/s ± 0% +0.65% (p=0.008 n=5+5)
wuffs_gif_decode_1000k_part_init/clang11 223MB/s ± 0% 224MB/s ± 0% +0.58% (p=0.008 n=5+5)
wuffs_gif_decode_anim_screencap/clang11 1.28GB/s ± 0% 1.30GB/s ± 0% +1.45% (p=0.008 n=5+5)
wuffs_gif_decode_1k_bw/gcc10 595MB/s ± 0% 642MB/s ± 0% +7.91% (p=0.008 n=5+5)
wuffs_gif_decode_1k_color_full_init/gcc10 168MB/s ± 0% 169MB/s ± 0% +0.36% (p=0.008 n=5+5)
wuffs_gif_decode_1k_color_part_init/gcc10 202MB/s ± 0% 203MB/s ± 0% +0.46% (p=0.008 n=5+5)
wuffs_gif_decode_10k_bgra/gcc10 790MB/s ± 0% 798MB/s ± 0% +1.04% (p=0.008 n=5+5)
wuffs_gif_decode_10k_indexed/gcc10 208MB/s ± 0% 210MB/s ± 0% +1.00% (p=0.008 n=5+5)
wuffs_gif_decode_20k/gcc10 258MB/s ± 0% 266MB/s ± 0% +3.08% (p=0.008 n=5+5)
wuffs_gif_decode_100k_artificial/gcc10 566MB/s ± 0% 577MB/s ± 0% +1.83% (p=0.008 n=5+5)
wuffs_gif_decode_100k_realistic/gcc10 220MB/s ± 0% 227MB/s ± 0% +3.03% (p=0.008 n=5+5)
wuffs_gif_decode_1000k_full_init/gcc10 223MB/s ± 0% 231MB/s ± 0% +3.23% (p=0.008 n=5+5)
wuffs_gif_decode_1000k_part_init/gcc10 224MB/s ± 0% 231MB/s ± 0% +3.14% (p=0.008 n=5+5)
wuffs_gif_decode_anim_screencap/gcc10 1.30GB/s ± 0% 1.32GB/s ± 0% +1.70% (p=0.008 n=5+5)
wuffs_lzw_decode_20k/clang11 294MB/s ± 0% 321MB/s ± 0% +9.11% (p=0.008 n=5+5)
wuffs_lzw_decode_100k/clang11 533MB/s ± 0% 560MB/s ± 0% +5.13% (p=0.008 n=5+5)
wuffs_lzw_decode_20k/gcc10 271MB/s ± 0% 272MB/s ± 0% +0.55% (p=0.008 n=5+5)
wuffs_lzw_decode_100k/gcc10 527MB/s ± 0% 521MB/s ± 0% -1.31% (p=0.008 n=5+5)
Updates #96
diff --git a/doc/changelog.md b/doc/changelog.md
index bf6f0ca..fbb05c2 100644
--- a/doc/changelog.md
+++ b/doc/changelog.md
@@ -1,6 +1,13 @@
# Changelog
+## Work In Progress
+
+For a *closed* `io_reader`, the standard library now returns `"#truncated
+input"` instead of `"$short read"`. Importantly, this is an error, not a
+suspension.
+
+
## 2023-01-26 version 0.3.0
The headline feature is that we have a production quality PNG decoder. It's
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 27c69b5..547c368 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -7843,6 +7843,7 @@
// ---------------- Status Codes
extern const char wuffs_lzw__error__bad_code[];
+extern const char wuffs_lzw__error__truncated_input[];
// ---------------- Public Consts
@@ -30680,6 +30681,7 @@
// ---------------- Status Codes Implementations
const char wuffs_lzw__error__bad_code[] = "#lzw: bad code";
+const char wuffs_lzw__error__truncated_input[] = "#lzw: truncated input";
const char wuffs_lzw__error__internal_error_inconsistent_i_o[] = "#lzw: internal error: inconsistent I/O";
// ---------------- Private Consts
@@ -30902,6 +30904,9 @@
status = wuffs_base__make_status(wuffs_base__suspension__short_read);
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
} else if (self->private_impl.f_read_from_return_value == 3) {
+ status = wuffs_base__make_status(wuffs_lzw__error__truncated_input);
+ goto exit;
+ } else if (self->private_impl.f_read_from_return_value == 4) {
status = wuffs_base__make_status(wuffs_lzw__error__bad_code);
goto exit;
} else {
@@ -30977,7 +30982,11 @@
iop_a_src += ((31 - v_n_bits) >> 3);
v_n_bits |= 24;
} else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
- self->private_impl.f_read_from_return_value = 2;
+ if (a_src && a_src->meta.closed) {
+ self->private_impl.f_read_from_return_value = 3;
+ } else {
+ self->private_impl.f_read_from_return_value = 2;
+ }
goto label__0__break;
} else {
v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
@@ -30985,14 +30994,18 @@
v_n_bits += 8;
if (v_n_bits >= v_width) {
} else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
- self->private_impl.f_read_from_return_value = 2;
+ if (a_src && a_src->meta.closed) {
+ self->private_impl.f_read_from_return_value = 3;
+ } else {
+ self->private_impl.f_read_from_return_value = 2;
+ }
goto label__0__break;
} else {
v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
iop_a_src += 1;
v_n_bits += 8;
if (v_n_bits < v_width) {
- self->private_impl.f_read_from_return_value = 4;
+ self->private_impl.f_read_from_return_value = 5;
goto label__0__break;
}
}
@@ -31070,7 +31083,7 @@
v_prev_code = v_code;
}
} else {
- self->private_impl.f_read_from_return_value = 3;
+ self->private_impl.f_read_from_return_value = 4;
goto label__0__break;
}
if (v_output_wi > 4095) {
@@ -31085,7 +31098,7 @@
if (iop_a_src > io1_a_src) {
iop_a_src--;
} else {
- self->private_impl.f_read_from_return_value = 4;
+ self->private_impl.f_read_from_return_value = 5;
goto label__2__break;
}
}
diff --git a/std/lzw/decode_lzw.wuffs b/std/lzw/decode_lzw.wuffs
index b653eb7..b193900 100644
--- a/std/lzw/decode_lzw.wuffs
+++ b/std/lzw/decode_lzw.wuffs
@@ -13,6 +13,7 @@
// limitations under the License.
pub status "#bad code"
+pub status "#truncated input"
pri status "#internal error: inconsistent I/O"
@@ -119,6 +120,8 @@
} else if this.read_from_return_value == 2 {
yield? base."$short read"
} else if this.read_from_return_value == 3 {
+ return "#truncated input"
+ } else if this.read_from_return_value == 4 {
return "#bad code"
} else {
return "#internal error: inconsistent I/O"
@@ -167,7 +170,11 @@
assert width <= n_bits via "a <= b: a <= c; c <= b"(c: 12)
assert n_bits >= width via "a >= b: b <= a"()
} else if args.src.length() <= 0 {
- this.read_from_return_value = 2
+ if args.src.is_closed() {
+ this.read_from_return_value = 3
+ } else {
+ this.read_from_return_value = 2
+ }
break
} else {
bits |= args.src.peek_u8_as_u32() << n_bits
@@ -176,7 +183,11 @@
if n_bits >= width {
// No-op.
} else if args.src.length() <= 0 {
- this.read_from_return_value = 2
+ if args.src.is_closed() {
+ this.read_from_return_value = 3
+ } else {
+ this.read_from_return_value = 2
+ }
break
} else {
bits |= args.src.peek_u8_as_u32() << n_bits
@@ -188,7 +199,7 @@
// This if condition is always false, but for some unknown
// reason, removing it worsens the benchmarks slightly.
if n_bits < width {
- this.read_from_return_value = 4
+ this.read_from_return_value = 5
break
}
}
@@ -297,7 +308,7 @@
}
} else {
- this.read_from_return_value = 3
+ this.read_from_return_value = 4
break
}
@@ -319,7 +330,7 @@
if args.src.can_undo_byte() {
args.src.undo_byte!()
} else {
- this.read_from_return_value = 4
+ this.read_from_return_value = 5
break
}
} endwhile
diff --git a/test/c/std/lzw.c b/test/c/std/lzw.c
index 6cfcd31..a18faaa 100644
--- a/test/c/std/lzw.c
+++ b/test/c/std/lzw.c
@@ -80,6 +80,35 @@
}
const char* //
+test_wuffs_lzw_decode_truncated_input() {
+ CHECK_FOCUS(__func__);
+
+ wuffs_base__io_buffer have = wuffs_base__ptr_u8__writer(g_have_array_u8, 1);
+ wuffs_base__io_buffer src =
+ wuffs_base__ptr_u8__reader(g_src_array_u8, 0, false);
+ wuffs_lzw__decoder dec;
+ CHECK_STATUS("initialize",
+ wuffs_lzw__decoder__initialize(
+ &dec, sizeof dec, WUFFS_VERSION,
+ WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
+
+ wuffs_base__status status =
+ wuffs_lzw__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_base__suspension__short_read) {
+ RETURN_FAIL("closed=false: have \"%s\", want \"%s\"", status.repr,
+ wuffs_base__suspension__short_read);
+ }
+
+ src.meta.closed = true;
+ status = wuffs_lzw__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
+ if (status.repr != wuffs_lzw__error__truncated_input) {
+ RETURN_FAIL("closed=true: have \"%s\", want \"%s\"", status.repr,
+ wuffs_lzw__error__truncated_input);
+ }
+ return NULL;
+}
+
+const char* //
do_test_wuffs_lzw_decode(const char* src_filename,
uint64_t src_size,
const char* want_filename,
@@ -444,6 +473,7 @@
test_wuffs_lzw_decode_output_bad,
test_wuffs_lzw_decode_output_empty,
test_wuffs_lzw_decode_pi,
+ test_wuffs_lzw_decode_truncated_input,
test_wuffs_lzw_decode_width_0,
test_wuffs_lzw_decode_width_1,