Zig 0.15.1 migration: LimitedReader

I have a pattern where I have a stream which produces length-prefixed data. The parsing is rather complicated, so I use a LimitedReader and read until EndOfStream to know when I should stop parsing.

How can I accomplish similar behavior in Zig 0.15.1?

Here is the (admitidly complicated) code snippet:

pub fn readPDOBitLengths(
    port: *Port,
    station_address: u16,
    direction: pdi.Direction,
    recv_timeout_us: u32,
    eeprom_timeout_us: u32,
) !u32 {
    const catagory = try findCatagoryFP(
        port,
        station_address,
        switch (direction) {
            .input => .TXPDO,
            .output => .RXPDO,
        },
        recv_timeout_us,
        eeprom_timeout_us,
    ) orelse return 0;

    // entries are 8 bytes, pdo header is 8 bytes, so
    // this should be a multiple of eight.
    if (catagory.byte_length % 8 != 0) return error.InvalidSII;

    var stream = SIIStream.init(
        port,
        station_address,
        catagory.word_address,
        recv_timeout_us,
        eeprom_timeout_us,
        &.{},
    );
    // ^^^ new zig 0.15.1 reader is at &stream.reader
    var limited_reader = std.io.limitedReader(stream.reader(), catagory.byte_length);
    const reader = limited_reader.reader();

    const State = enum {
        pdo_header,
        entries,
        entries_skip,
    };
    var pdo_header: PDO.Header = undefined;
    var entries_remaining: u8 = 0;
    var total_bit_length: u32 = 0;
    state: switch (State.pdo_header) {
        .pdo_header => {
            assert(entries_remaining == 0);
            pdo_header = wire.packFromECatReader(PDO.Header, reader) catch |err| switch (err) {
                error.EndOfStream => return total_bit_length, // <<<<<<<<<-----------------------EndOfStream here!
                error.LinkError => return error.LinkError,
                error.Timeout => return error.Timeout,
            };
            if (pdo_header.n_entries > PDO.max_entries) return error.InvalidSII;
            entries_remaining = pdo_header.n_entries;
            if (pdo_header.isUsed()) continue :state .entries else continue :state .entries_skip;
        },
        .entries => {
            if (entries_remaining == 0) continue :state .pdo_header;
            const entry = wire.packFromECatReader(PDO.Entry, reader) catch return error.InvalidSII;
            entries_remaining -= 1;
            total_bit_length += entry.bit_length;
            continue :state .entries;
        },
        .entries_skip => {
            if (entries_remaining == 0) continue :state .pdo_header;
            _ = wire.packFromECatReader(PDO.Entry, reader) catch return error.InvalidSII;
            entries_remaining -= 1;
            continue :state .entries_skip;
        },
    }
}

I had falsely assumed that limited reader no longer existed.

I just need this:

var limited = std.Io.Reader.limited(&stream.reader, .limited(catagory.byte_length), &.{});
const reader = &limited.interface;
1 Like