Expected type 'const [2]u8' but only when using parameterized index

version 0.15.2

Say I have a stream of n bytes. I want to take some of those bytes and convert them into a larger integer.

pub fn main() !void {
    const byte_array = [_]u8{
        0x48,
        0x1f,
        0xDE,
        0xAD,
        0xBE,
        0xEF,
    };

    print("{d}\n", .{gimme(u16, &byte_array)});
}

pub fn gimme(comptime T: type, buffer: []const u8) T {
    const start = 0;
    const end = start + @sizeOf(T);
    return std.mem.readInt(u16, buffer[start..end], .little);
}

This code above will do that.

However, when we parameterize the start like so:

const std = @import("std");
// ...

    print("{d}\n", .{gimme(u16, &byte_array, 1)});
}

pub fn gimme(comptime T: type, buffer: []const u8, start: usize) T {
    const end = start + @sizeOf(T);
    return std.mem.readInt(u16, buffer[start..end], .little);
}

we get this error:

src/main.zig:18:39: error: expected type '*const [2]u8', found '[]const u8'
    return std.mem.readInt(u16, buffer[start..end], .little);
                                ~~~~~~^~~~~~~~~~~~
/usr/local/share/zig/lib/std/mem.zig:1814: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 {

Why does the first set of code seem to be the correct type but the second does not?

when you slice with a comptime known length zig will actually produce a pointer to an array instead of a slice.

When you make the start a parameter the difference between start and end, the length, becomes runtime known.

You can get around this by slicing twice, first with the runtime known start, then again with a comptime knwon 0 start:
buffer[start..][0..end]

4 Likes

Okay, so it was because the lengths I was using were comptime known. That makes sense considering the slicing happens then

But I tried the work around you sent but I still get an error so I think I’m still not understanding

src/main.zig:18:48: error: expected type '*const [2]u8', found '[]const u8'
    return std.mem.readInt(u16, buffer[start..][0..end], .little);
                                ~~~~~~~~~~~~~~~^~~~~~~~
/usr/local/share/zig/lib/std/mem.zig:1814: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 {

End should just be @szeOf(T) now, since the first slicing applies the start offset, the second is now just the length.

since ends value was a calculation involving start it also become runtime known.

1 Like

right right right

Because you’d have like {0 , 1 , 2, 3, 4} be {1, 2, 3, 4 } and then {1, 2}

With that we’re getting our 8008.

Thaank you <3