~alva/zig-bare

019b27e24912e89233a56cf57e05af6c15b3eba1 — owl 6 months ago d48e6cd
port more go-bare tests
3 files changed, 68 insertions(+), 36 deletions(-)

M build.zig.zon
M src/bare.zig
M src/interop/go-bare/unmarshal_test.zig
M build.zig.zon => build.zig.zon +2 -2
@@ 4,8 4,8 @@
    .paths = .{""},
    .dependencies = .{
        .varint = .{
            .url = "https://git.sr.ht/~alva/zig-varint/archive/09078dd.tar.gz",
            .hash = "122043d671db521d5f4aa6ec2c34c5b9c7536f95704f585a9046004cbed652c23b63",
            .url = "https://git.sr.ht/~alva/zig-varint/archive/f9e5b7f.tar.gz",
            .hash = "1220136609b836df8ff707062b100395f49d6c87187c3e74312c223618ad69e9a9ab",
        },
    },
}

M src/bare.zig => src/bare.zig +27 -30
@@ 15,9 15,6 @@ pub fn decoder(allocator: mem.Allocator, reader: anytype) Decoder(@TypeOf(reader
    return Decoder(@TypeOf(reader)).init(allocator, reader);
}

pub const VarInt = varint.VarInt;
pub const VarUint = varint.VarUint;

/// Decodes BARE messages.
/// Uses an internal arena backed by the passed-in allocator.
pub fn Decoder(comptime ReaderType: type) type {


@@ 47,10 44,6 @@ pub fn Decoder(comptime ReaderType: type) type {
                .Bool => self.decodeBool(),
                .Struct => if (comptime isHashMap(T))
                    self.decodeHashMap(T)
                else if (T == VarInt)
                    self.decodeVarInt()
                else if (T == VarUint)
                    self.decodeVarUint()
                else
                    self.decodeStruct(T),
                .Enum => self.decodeEnum(T),


@@ 69,16 62,20 @@ pub fn Decoder(comptime ReaderType: type) type {
            };
        }

        fn decodeVarInt(self: *Self) !VarInt {
            return varint.decodeVarInt(self.reader);
        fn decodeVarInt(self: *Self, comptime T: type) !T {
            return @intCast(try varint.decodeVarInt(self.reader));
        }

        fn decodeVarUint(self: *Self) !VarUint {
            return varint.decodeVarUint(self.reader);
        fn decodeVarUint(self: *Self, comptime T: type) !T {
            return @intCast(try varint.decodeVarUint(self.reader));
        }

        fn decodeInt(self: *Self, comptime T: type) !T {
            return switch (@bitSizeOf(T)) {
            return if (T == usize or T == c_uint)
                self.decodeVarUint(T)
            else if (T == isize or T == c_int)
                self.decodeVarInt(T)
            else switch (@bitSizeOf(T)) {
                8, 16, 32, 64 => self.reader.readInt(T, .little),
                else => @compileError("unsupported integer type " ++ @typeName(T)),
            };


@@ 114,7 111,7 @@ pub fn Decoder(comptime ReaderType: type) type {
        }

        fn decodeEnum(self: *Self, comptime T: type) !T {
            const x: meta.Tag(T) = @intCast((try self.decodeVarUint())[0]);
            const x: meta.Tag(T) = @intCast(try self.decodeVarUint(usize));
            return meta.intToEnum(T, x);
        }



@@ 144,10 141,10 @@ pub fn Decoder(comptime ReaderType: type) type {
            if (ti.tag_type == null)
                @compileError("only tagged unions are supported");

            const tag = try self.decodeVarUint();
            const tag = try self.decodeVarUint(usize);

            inline for (ti.fields) |f| {
                if (tag[0] == @intFromEnum(@field(ti.tag_type.?, f.name))) {
                if (tag == @intFromEnum(@field(ti.tag_type.?, f.name))) {
                    const v = try self.decodeAllowVoid(f.type);
                    return @unionInit(T, f.name, v);
                }


@@ 162,10 159,10 @@ pub fn Decoder(comptime ReaderType: type) type {
            if (ti.size != .Slice)
                @compileError("slices are the only supported pointer type");

            const len = try self.decodeVarUint();
            var buf = try self.arena.allocator().alloc(ti.child, len[0]);
            const len = try self.decodeVarUint(usize);
            var buf = try self.arena.allocator().alloc(ti.child, len);

            for (0..len[0]) |i|
            for (0..len) |i|
                buf[i] = try self.decode(ti.child);

            return buf;


@@ 178,15 175,15 @@ pub fn Decoder(comptime ReaderType: type) type {
            if (comptime !isValidHashMapKeyType(K))
                @compileError("unsupported hashmap key type " ++ @typeName(K));

            const i = try self.decodeVarUint();
            const i = try self.decodeVarUint(usize);

            if (std.math.maxInt(T.Size) < i[0])
            if (std.math.maxInt(T.Size) < i)
                return DecodeError.Overflow;

            var map = T.Unmanaged{};
            try map.ensureUnusedCapacity(self.arena.allocator(), @intCast(i[0]));
            try map.ensureUnusedCapacity(self.arena.allocator(), @intCast(i));

            for (0..i[0]) |_| {
            for (0..i) |_| {
                const key = try self.decode(K);
                const val = try self.decode(V);
                _ = map.putAssumeCapacity(key, val);


@@ 245,12 242,12 @@ pub fn Encoder(comptime WriterType: type) type {
            };
        }

        fn encodeVarUint(self: *Self, value: VarUint) !void {
            return varint.encodeVarUint(self.writer, value);
        fn encodeVarUint(self: *Self, value: anytype) !void {
            return varint.encodeVarUint(self.writer, @intCast(value));
        }

        fn encodeVarInt(self: *Self, value: i64) !void {
            return varint.encodeVarInt(self.writer, value);
        fn encodeVarInt(self: *Self, value: anytype) !void {
            return varint.encodeVarInt(self.writer, @intCast(value));
        }

        fn encodeInt(self: *Self, comptime T: type, value: T) !void {


@@ 285,7 282,7 @@ pub fn Encoder(comptime WriterType: type) type {
        }

        fn encodeEnum(self: *Self, value: anytype) !void {
            try self.encodeVarUint(VarUint{@intFromEnum(value)});
            try self.encodeVarUint(@intFromEnum(value));
        }

        fn encodeOptional(self: *Self, value: anytype) !void {


@@ 311,7 308,7 @@ pub fn Encoder(comptime WriterType: type) type {
            if (ti.size != .Slice)
                @compileError("slices are the only supported pointer type");

            try self.encodeVarUint(VarUint{value.len});
            try self.encodeVarUint(value.len);

            for (value) |v|
                try self.encode(v);


@@ 324,7 321,7 @@ pub fn Encoder(comptime WriterType: type) type {
            if (comptime !isValidHashMapKeyType(K))
                @compileError("unsupported hashmap key type " ++ @typeName(K));

            try self.encodeVarUint(VarUint{value.count()});
            try self.encodeVarUint(value.count());

            var it = value.iterator();



@@ 340,7 337,7 @@ pub fn Encoder(comptime WriterType: type) type {

            if (ti.tag_type) |TT| {
                const tag = @intFromEnum(value);
                try self.encodeVarUint(VarUint{tag});
                try self.encodeVarUint(tag);

                inline for (ti.fields) |f| {
                    if (value == @field(TT, f.name))

M src/interop/go-bare/unmarshal_test.zig => src/interop/go-bare/unmarshal_test.zig +39 -4
@@ 37,14 37,14 @@ test "unmarshal value" {
        .{ payloads1[1], u16, 0xCAFE },
        .{ payloads1[2], u32, 0xDEADBEEF },
        .{ payloads1[3], u64, 0xCAFEBABEDEADBEEF },
        //.{payloads1[4], c_uint, 0xDEADBEEF },
        .{ payloads1[4], bare.VarUint, bare.VarUint{0xDEADBEEF} },
        .{ payloads1[4], c_uint, 0xDEADBEEF },
        .{ payloads1[4], usize, 0xDEADBEEF },
        .{ payloads1[5], i8, -42 },
        .{ payloads1[6], i16, -1234 },
        .{ payloads1[7], i32, -12345678 },
        .{ payloads1[8], i64, -12345678987654321 },
        //.{payloads1[9], c_int, -12345678 },
        .{ payloads1[9], bare.VarInt, bare.VarInt{-12345678} },
        .{ payloads1[9], c_int, -12345678 },
        .{ payloads1[9], isize, -12345678 },
        .{ payloads1[10], f32, 1337.42 },
        .{ payloads1[11], f64, 133713371337.42424242 },
        .{ payloads1[12][0..], bool, false },


@@ 68,3 68,38 @@ test "unmarshal value" {
        //};
    }
}

test "unmarshal optional" {
    {
        const payload = &[_]u8{0x00};
        var fbs = io.fixedBufferStream(payload);
        const reader = fbs.reader();
        var d = decoder(testing.allocator, reader);
        defer d.deinit();
        const val = try d.decode(?i32);
        try expectEqual(@as(?i32, null), val);
    }

    {
        const payload = &[_]u8{ 0x01, 0xEF, 0xBE, 0xAD, 0xDE };
        var fbs = io.fixedBufferStream(payload);
        const reader = fbs.reader();
        var d = decoder(testing.allocator, reader);
        defer d.deinit();
        const val = try d.decode(?u32);
        try expectEqual(@as(?u32, 0xDEADBEEF), val);
    }
}

test "unmarshal struct" {
    const Coordinates = struct { x: usize, y: usize, z: usize };
    const payload = &[_]u8{ 0x01, 0x02, 0x03 };
    var fbs = io.fixedBufferStream(payload);
    const reader = fbs.reader();
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const coords = try d.decode(Coordinates);
    try expectEqual(@as(usize, 1), coords.x);
    try expectEqual(@as(usize, 2), coords.y);
    try expectEqual(@as(usize, 3), coords.z);
}