Reading integers from dynamic address

I’ve got a project where I’m parsing headers from a binary file. So far I’ve been reading from static addresses like so:

        self.page_size = std.mem.readInt(u16, buf[16..18], .big);
        self.file_change_counter = std.mem.readInt(u32, buf[24..28], .big);
        self.num_pages = std.mem.readInt(u32, buf[28..32], .big);

This has worked well. However now I need to parse a dynamic number of integers into a buffer, which I am doing like so:

        while (i < self.page_header.num_cells) : (i += 1) {
            const slice_start = start_idx + i * 2;
            const slice_end = slice_start + 2;
            cells[i] = std.mem.readInt(u16, self.page_buf[slice_start..slice_end], .big);
        }

However this yields to a type error that I don’t really understand:

src/db.zig:63:58: error: expected type '*const [2]u8', found '[]u8'
            cells[i] = std.mem.readInt(u16, self.page_buf[slice_start..slice_end], .big);
                                            ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/home/axelmagn/.zvm/master/lib/std/mem.zig:1797:49: note: parameter type declared here
pub inline fn readInt(comptime T: type, buffer: *const [@divExact(@typeInfo(T).int.bits, 8)]u8, endian: Endian) T {
                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I don’t understand:

  1. Why does this work for literal indices but not variable indices?
  2. Is it possible to coerce a slice into *const [2]u8?
  3. If so, how?

I believe you could do:

const slice = self.page_buf[slice_start..slice_end];
cells[i] = std.mem.readInt(u16, slice[0..2], .big);

Another option:

std.mem.readInt(u16, &.{ slice[0], slice[1] }, .big);

I think the issue relates to the slice length being known at compile time, and slice_start is only known at runtime.

slice[start..][..2] also works

3 Likes

readInt takes a pointer to an array to enforce at compile time the length of the data. When slicing with comp-time known length, it actually returns a pointer to an array instead of a slice

2 Likes

Thanks. that makes a lot of sense in retrospect.