@@ 7,6 7,7 @@ use io;
export type reader = struct {
src: io::handle,
+ nextchunk: bool,
};
// Creates a new PNG decoder. Reads and verifies the PNG magic before returning
@@ 24,6 25,7 @@ export fn newreader(src: io::handle) (reader | error) = {
};
return reader {
src = src,
+ nextchunk = true,
};
};
@@ 37,7 39,7 @@ export fn newreader(src: io::handle) (reader | error) = {
export type chunk_reader = struct {
vtable: io::stream,
- src: io::handle,
+ src: *reader,
length: size,
ctype: u32,
crc: crc32::state,
@@ 52,6 54,8 @@ export type chunk_reader = struct {
// chunk, but instead will pass it to [[new_chunk_decoder]] to get a
// chunk-type-aware decoder and read from this instead.
export fn nextchunk(src: *reader) (chunk_reader | io::EOF | error) = {
+ assert(src.nextchunk,
+ "Must finish previous chunk before calling nextchunk again");
let buf: [8]u8 = [0...];
match (io::readall(src.src, buf[..])?) {
case io::EOF =>
@@ 59,13 63,14 @@ export fn nextchunk(src: *reader) (chunk_reader | io::EOF | error) = {
case size =>
yield;
};
+ src.nextchunk = false;
const length = endian::begetu32(buf[..4]);
const ctype = endian::begetu32(buf[4..]);
const crc = crc32::crc32(&crc32::ieee_table);
hash::write(&crc, buf[4..]);
return chunk_reader {
vtable = &chunk_reader_vtable,
- src = src.src,
+ src = src,
length = length,
ctype = ctype,
crc = crc,
@@ 134,12 139,13 @@ fn chunk_read(st: *io::stream, buf: []u8) (size | io::EOF | io::error) = {
if (st.length == 0) {
let ckbuf: [4]u8 = [0...];
- match (io::readall(st.src, ckbuf[..])?) {
+ match (io::readall(st.src.src, ckbuf[..])?) {
case io::EOF =>
return wraperror(invalid);
case size =>
yield;
};
+ st.src.nextchunk = true;
const want = endian::begetu32(ckbuf);
const have = crc32::sum32(&st.crc);
if (want != have) {
@@ 154,7 160,7 @@ fn chunk_read(st: *io::stream, buf: []u8) (size | io::EOF | io::error) = {
yield st.length;
};
- const z = match (io::read(st.src, buf[..max])?) {
+ const z = match (io::read(st.src.src, buf[..max])?) {
case io::EOF =>
// Missing checksum
return wraperror(invalid);