~alva/zig-bare

929c1c4e04117a91df896c0b2ca58152362b8968 — ugla 1 year, 5 months ago cd34c08
Put allocator param first, seems more idiomatic
5 files changed, 60 insertions(+), 65 deletions(-)

M README.md
M src/bare.zig
M src/benchmark.zig
M src/main.zig
M src/test.zig
M README.md => README.md +1 -1
@@ 52,7 52,7 @@ try e.encode(x);

try fbs.seekTo(0);

var d = decoder(reader, allocator);
var d = decoder(allocator, reader);
defer d.deinit();

const y = try d.decode(Bar);

M src/bare.zig => src/bare.zig +16 -16
@@ 6,8 6,8 @@ const meta = std.meta;

pub const DecodeError = error{ Overflow, InvalidUnion };

pub fn decoder(reader: anytype, allocator: mem.Allocator) Decoder(@TypeOf(reader)) {
    return Decoder(@TypeOf(reader)).init(reader, allocator);
pub fn decoder(allocator: mem.Allocator, reader: anytype) Decoder(@TypeOf(reader)) {
    return Decoder(@TypeOf(reader)).init(allocator, reader);
}

/// Decodes BARE messages.


@@ 19,7 19,7 @@ pub fn Decoder(comptime ReaderType: type) type {
        const Self = @This();

        /// Call `deinit` when done.
        pub fn init(reader: ReaderType, allocator: mem.Allocator) Self {
        pub fn init(allocator: mem.Allocator, reader: ReaderType) Self {
            return .{
                .arena = std.heap.ArenaAllocator.init(allocator),
                .reader = reader,


@@ 405,7 405,7 @@ fn isValidHashMapKeyType(comptime T: type) bool {
test "read variable uint" {
    var fbs = io.fixedBufferStream("\x2a");
    var reader = fbs.reader();
    var d = Decoder(@TypeOf(reader)).init(reader, std.testing.allocator);
    var d = decoder(std.testing.allocator, reader);
    const x = try d.decodeVarUint();
    try std.testing.expectEqual(x, 42);
    fbs = io.fixedBufferStream("\x80\x02");


@@ 417,7 417,7 @@ test "read variable uint overflow 1" {
    const buf = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02";
    var fbs = io.fixedBufferStream(buf);
    var reader = fbs.reader();
    var d = Decoder(@TypeOf(reader)).init(reader, std.testing.allocator);
    var d = decoder(std.testing.allocator, reader);
    const x = d.decodeVarUint();
    try std.testing.expectError(DecodeError.Overflow, x);
}


@@ 426,7 426,7 @@ test "read variable uint overflow 2" {
    const buf = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00";
    var fbs = io.fixedBufferStream(buf);
    var reader = fbs.reader();
    var d = Decoder(@TypeOf(reader)).init(reader, std.testing.allocator);
    var d = decoder(std.testing.allocator, reader);
    const x = d.decodeVarUint();
    try std.testing.expectError(DecodeError.Overflow, x);
}


@@ 435,7 435,7 @@ test "write variable uint" {
    var buf: [4]u8 = undefined;
    var fbs = io.fixedBufferStream(&buf);
    var writer = fbs.writer();
    var e = Encoder(@TypeOf(writer)).init(writer);
    var e = encoder(writer);
    try e.encodeVarUint(42);
    try std.testing.expectEqual(fbs.getWritten()[0], 42);
    try e.encodeVarUint(0x100);


@@ 447,7 447,7 @@ test "write variable int" {
    var buf: [4]u8 = undefined;
    var fbs = io.fixedBufferStream(&buf);
    var writer = fbs.writer();
    var e = Encoder(@TypeOf(writer)).init(writer);
    var e = encoder(writer);
    try e.encodeVarInt(42);
    try std.testing.expectEqual(fbs.getWritten()[0], 42 << 1);
}


@@ 457,9 457,9 @@ test "round trip variable uint" {
    var fbs = io.fixedBufferStream(&buf);
    var reader = fbs.reader();
    var writer = fbs.writer();
    var e = Encoder(@TypeOf(writer)).init(writer);
    var e = encoder(writer);
    try e.encodeVarUint(0x10000);
    var d = Decoder(@TypeOf(reader)).init(reader, std.testing.allocator);
    var d = decoder(std.testing.allocator, reader);
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decodeVarUint();
    try std.testing.expectEqual(res, 0x10000);


@@ 470,9 470,9 @@ test "round trip variable int 1" {
    var fbs = io.fixedBufferStream(&buf);
    var reader = fbs.reader();
    var writer = fbs.writer();
    var e = Encoder(@TypeOf(writer)).init(writer);
    var e = encoder(writer);
    try e.encodeVarInt(-0x10000);
    var d = Decoder(@TypeOf(reader)).init(reader, std.testing.allocator);
    var d = decoder(std.testing.allocator, reader);
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decodeVarInt();
    try std.testing.expectEqual(res, -0x10000);


@@ 483,9 483,9 @@ test "round trip variable int 2" {
    var fbs = io.fixedBufferStream(&buf);
    var reader = fbs.reader();
    var writer = fbs.writer();
    var e = Encoder(@TypeOf(writer)).init(writer);
    var e = encoder(writer);
    try e.encodeVarInt(0x10000);
    var d = Decoder(@TypeOf(reader)).init(reader, std.testing.allocator);
    var d = decoder(std.testing.allocator, reader);
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decodeVarInt();
    try std.testing.expectEqual(res, 0x10000);


@@ 500,9 500,9 @@ test "round trip union with void member" {
    var fbs = io.fixedBufferStream(&buf);
    var reader = fbs.reader();
    var writer = fbs.writer();
    var e = Encoder(@TypeOf(writer)).init(writer);
    var e = encoder(writer);
    try e.encode(U{ .Hello = 123 });
    var d = Decoder(@TypeOf(reader)).init(reader, std.testing.allocator);
    var d = decoder(std.testing.allocator, reader);
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decode(U);
    try std.testing.expectEqual(res, U{ .Hello = 123 });

M src/benchmark.zig => src/benchmark.zig +2 -2
@@ 25,12 25,12 @@ fn benchmarkRead(allocator: std.mem.Allocator, iterations: usize) !u64 {
    const start = timer.lap();
    var fbs = io.fixedBufferStream("\x00\x00\x28\x42\x2b\x00");
    var fbs_reader = fbs.reader();
    var bd = bare.Decoder.init(allocator);
    var bd = bare.decoder(allocator, fbs_reader);

    var i = iterations;

    while (i != 0) : (i -= 1) {
        const res = try bd.decode(Foo, fbs_reader);
        const res = try bd.decode(Foo);
        mem.doNotOptimizeAway(&res);
        try fbs.seekTo(0);
    }

M src/main.zig => src/main.zig +1 -3
@@ 3,8 3,6 @@ const fs = std.fs;
const io = std.io;
const assert = std.debug.assert;
const bare = @import("bare");
const Decoder = bare.Decoder;
const Encoder = bare.Encoder;
const decoder = bare.decoder;
const encoder = bare.encoder;



@@ 39,7 37,7 @@ pub fn main() !void {
    var e = encoder(writer);
    try e.encode(x);
    try fbs.seekTo(0);
    var d = decoder(reader, allocator);
    var d = decoder(allocator, reader);
    defer d.deinit();
    const y = try d.decode(Bar);
    std.log.info("x: {}", .{x});

M src/test.zig => src/test.zig +40 -43
@@ 5,11 5,8 @@ const mem = std.mem;
const testing = std.testing;

const bare = @import("bare.zig");
const Decoder = bare.Decoder;
const Encoder = bare.Encoder;
const decoder = bare.decoder;
const encoder = bare.encoder;
const DecodeError = bare.DecodeError;

const expect = testing.expect;
const expectEqual = testing.expectEqual;


@@ 30,7 27,7 @@ test "read u8" {
    inline for (cases) |pair| {
        var fbs = io.fixedBufferStream(pair[0]);
        var reader = fbs.reader();
        var d = decoder(reader, testing.allocator);
        var d = decoder(testing.allocator, reader);
        defer d.deinit();
        try expectEqual(@as(u8, pair[1]), try d.decode(u8));
    }


@@ 39,7 36,7 @@ test "read u8" {
test "read bool" {
    var fbs = io.fixedBufferStream("\x00");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    try expectEqual(d.decode(bool), false);
    fbs = io.fixedBufferStream("\xff");


@@ 57,7 54,7 @@ test "read struct 1" {

    var fbs = io.fixedBufferStream("\x00\x00\x28\x42\x2a\xaa");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode(Foo);
    try expectEqual(res.a, 42.0);


@@ 74,7 71,7 @@ test "read struct 2" {

    var fbs = io.fixedBufferStream("\x00\x00\x28\x42\x2a\x00");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode(Foo);
    try expectEqual(res.a, 42.0);


@@ 91,7 88,7 @@ test "read struct 3" {

    var fbs = io.fixedBufferStream("\x00\x00\x28\x42\x2b\x00");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode(Foo);
    try expectEqual(res.a, 42.0);


@@ 108,7 105,7 @@ test "read struct 4" {

    var fbs = io.fixedBufferStream("\x00\x00\x29\x42\x2b\x00");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode(Foo);
    try expectEqual(res.a, 42.25);


@@ 125,7 122,7 @@ test "read struct 5" {

    var fbs = io.fixedBufferStream("\x00\x00\x00\x00\x00\x00");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode(Foo);
    try expectEqual(res.a, 0.0);


@@ 142,7 139,7 @@ test "read struct 6" {

    var fbs = io.fixedBufferStream("\xff\xff\xff\xff\xff\xff");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode(Foo);
    try expect(math.isNan(res.a));


@@ 157,7 154,7 @@ test "read struct with void members" {
        \\  var reader = fbs.reader();
        \\  const Foo = struct { a: u8, b: void };
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  _ = try d.decode(Foo);
        \\}
    , "unsupported type void");


@@ 171,7 168,7 @@ test "read enum" {
    };
    var fbs = io.fixedBufferStream("\x02");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    var res = try d.decode(Foo);
    try expectEqual(res, .a);


@@ 193,14 190,14 @@ test "read invalid enum value" {
    };
    var fbs = io.fixedBufferStream("\x03");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    try expectError(error.InvalidEnumTag, d.decode(Foo));
}

test "read optional u8 value" {
    var fbs = io.fixedBufferStream("\x01\x2a");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode(?u8);
    try expectEqual(res, 42);


@@ 209,7 206,7 @@ test "read optional u8 value" {
test "read optional u8 null" {
    var fbs = io.fixedBufferStream("\x00");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode(?u8);
    try expectEqual(res, null);


@@ 218,7 215,7 @@ test "read optional u8 null" {
test "read u8 array" {
    var fbs = io.fixedBufferStream("\x01\x02\x03\x04");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode([4]u8);
    const expected = [4]u8{ 1, 2, 3, 4 };


@@ 228,7 225,7 @@ test "read u8 array" {
test "read u8 slice" {
    var fbs = io.fixedBufferStream("\x04\x01\x02\x03\x04");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode([]const u8);
    const expected = [_]u8{ 1, 2, 3, 4 };


@@ 238,7 235,7 @@ test "read u8 slice" {
test "read 0-length slice" {
    var fbs = io.fixedBufferStream("\x00");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode([]const u8);
    defer testing.allocator.free(res);


@@ 249,7 246,7 @@ test "read 0-length slice" {
test "read map[u8]u8" {
    var fbs = io.fixedBufferStream("\x02\x01\x02\x03\x04");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const map = try d.decode(std.AutoHashMap(u8, u8));
    try expectEqual(map.get(1) orelse unreachable, 2);


@@ 259,7 256,7 @@ test "read map[u8]u8" {
test "read map[u8]u8 with 0 items" {
    var fbs = io.fixedBufferStream("\x00");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const map = try d.decode(std.AutoHashMap(u8, u8));
    try expectEqual(map.count(), 0);


@@ 268,7 265,7 @@ test "read map[u8]u8 with 0 items" {
test "read map[string]u8" {
    var fbs = io.fixedBufferStream("\x02\x04zomg\x04\x03lol\x02");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const T = std.StringHashMap(u8);
    const map = try d.decode(T);


@@ 279,7 276,7 @@ test "read map[string]u8" {
test "read map overflow" {
    var fbs = io.fixedBufferStream("\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x04zomg\x04\x03lol\x02");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const T = std.StringHashMap(u8);
    const map = d.decode(T);


@@ 293,7 290,7 @@ test "read map[u8]void" {
        \\  var reader = fbs.reader();
        \\  const HM = std.AutoHashMap(u8, void);
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  _ = try d.decode(HM);
        \\}
    , "unsupported type void");


@@ 303,7 300,7 @@ test "read tagged union" {
    const Foo = union(enum) { a: i64, b: bool, c: u8 };
    var fbs = io.fixedBufferStream("\x02\x2a");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    const res = try d.decode(Foo);
    try expectEqual(Foo{ .c = 42 }, res);


@@ 316,7 313,7 @@ test "read untagged union" {
        \\  var fbs = io.fixedBufferStream("lol");
        \\  var reader = fbs.reader();
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  _ = try d.decode(Foo);
        \\}
    , "only tagged unions are supported");


@@ 328,7 325,7 @@ test "read void" {
        \\  var fbs = io.fixedBufferStream("lol");
        \\  var reader = fbs.reader();
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  _ = try d.decode(void);
        \\}
    , "unsupported type void");


@@ 340,7 337,7 @@ test "read unsupported integer type" {
        \\  var fbs = io.fixedBufferStream("lol");
        \\  var reader = fbs.reader();
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  _ = try d.decode(u7);
        \\}
    , "unsupported integer type u7");


@@ 352,7 349,7 @@ test "read unsupported float type" {
        \\  var fbs = io.fixedBufferStream("lol");
        \\  var reader = fbs.reader();
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  _ = try d.decode(f16);
        \\}
    , "unsupported float type f16");


@@ 364,7 361,7 @@ test "read unsupported pointer type" {
        \\  var fbs = io.fixedBufferStream("lol");
        \\  var reader = fbs.reader();
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  _ = try d.decode(*u8);
        \\}
    , "slices are the only supported pointer type");


@@ 675,7 672,7 @@ test "round trip u8" {
    const x: u8 = 42;
    var e = encoder(writer);
    try e.encode(x);
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decode(u8);


@@ 696,7 693,7 @@ test "round trip struct" {
    var writer = fbs.writer();
    var e = encoder(writer);
    try e.encode(foo);
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decode(Foo);


@@ 716,7 713,7 @@ test "round trip enum" {
    var writer = fbs.writer();
    var e = encoder(writer);
    try e.encode(Foo.c);
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decode(Foo);


@@ 731,7 728,7 @@ test "round trip i64 array" {
    const arr = [_]i64{ -1, 1, math.maxInt(i64), math.minInt(i64) };
    var e = encoder(writer);
    try e.encode(arr);
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decode(@TypeOf(arr));


@@ 750,7 747,7 @@ test "round trip i32 slice" {
    const slajs: []const i32 = &expected;

    try e.encode(slajs);
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decode([]const i32);


@@ 771,7 768,7 @@ test "round trip tagged union" {

    var e = encoder(writer);
    try e.encode(foo);
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decode(Foo);


@@ 793,7 790,7 @@ test "round trip tagged union with void member active" {

    var e = encoder(writer);
    try e.encode(foo);
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    fbs = io.fixedBufferStream(fbs.getWritten());
    const res = try d.decode(Foo);


@@ 805,7 802,7 @@ test "invalid union returns error" {
    const Foo = union(enum) { a: i64, b: bool, c: u8 };
    var fbs = io.fixedBufferStream("\x09\x2a");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    const res = d.decode(Foo);
    try expectError(error.InvalidUnion, res);
}


@@ 813,7 810,7 @@ test "invalid union returns error" {
test "bare.Decoder frees its memory" {
    var fbs = io.fixedBufferStream("\x02\x01\x02\x03\x04");
    var reader = fbs.reader();
    var d = decoder(reader, testing.allocator);
    var d = decoder(testing.allocator, reader);
    defer d.deinit();
    _ = try d.decode(std.AutoHashMap(u8, u8));
    fbs = io.fixedBufferStream("\x04\x01\x02\x03\x04");


@@ 827,7 824,7 @@ test "invariant: fixed-length array must have length > 0 (read)" {
        \\  var fbs = io.fixedBufferStream("lol");
        \\  var reader = fbs.reader();
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  try d.decode([0]u8);
        \\}
    , "array length must be at least 1");


@@ 853,7 850,7 @@ test "invariant: structs must have at least 1 field (read)" {
        \\  var fbs = io.fixedBufferStream("lol");
        \\  var reader = fbs.reader();
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  try d.decode(Foo);
        \\}
    , "structs must have 1 or more fields");


@@ 879,7 876,7 @@ test "invariant: unions must have at least 1 field (read)" {
        \\  var fbs = io.fixedBufferStream("lol");
        \\  var reader = fbs.reader();
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  _ = try d.decode(Foo{});
        \\}
    , "union initializer must initialize one field");


@@ 924,7 921,7 @@ test "invariant: enum values must be unique" {
        \\  var fbs = io.fixedBufferStream(&buf);
        \\  var reader = fbs.reader();
        \\  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
        \\  var d = Decoder(@TypeOf(reader)).init(reader, gpa.allocator());
        \\  var d = decoder(gpa.allocator(), reader);
        \\  _ = try d.decode(Foo);
        \\}
    , "enum tag value 1 already taken");