From 4c5b06112192a02462aa9ede6045c9a442b3e81e Mon Sep 17 00:00:00 2001 From: banteg <4562643+banteg@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:49:43 +0400 Subject: [PATCH] fix: use msgpack binary headers --- src/any.zig | 9 +++++---- src/binary.zig | 33 ++++++++++++++++++++------------- src/msgpack.zig | 10 +++++++++- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/any.zig b/src/any.zig index e35ccaa..3581aef 100644 --- a/src/any.zig +++ b/src/any.zig @@ -22,6 +22,7 @@ const sizeOfPackedString = @import("string.zig").sizeOfPackedString; const packString = @import("string.zig").packString; const unpackString = @import("string.zig").unpackString; const String = @import("string.zig").String; +const Binary = @import("binary.zig").Binary; const sizeOfPackedArray = @import("array.zig").sizeOfPackedArray; const packArray = @import("array.zig").packArray; @@ -367,11 +368,11 @@ test "packAny/unpackAny: String struct" { test "packAny/unpackAny: Binary struct" { var buffer: [64]u8 = undefined; var writer = std.Io.Writer.fixed(&buffer); - const str = String{ .data = "\x01\x02\x03\x04" }; - try packAny(&writer, str); + const binary = Binary{ .data = "\x01\x02\x03\x04" }; + try packAny(&writer, binary); var reader = std.Io.Reader.fixed(writer.buffered()); - const result = try unpackAny(&reader, std.testing.allocator, String); + const result = try unpackAny(&reader, std.testing.allocator, Binary); defer std.testing.allocator.free(result.data); - try std.testing.expectEqualStrings("\x01\x02\x03\x04", result.data); + try std.testing.expectEqualSlices(u8, "\x01\x02\x03\x04", result.data); } diff --git a/src/binary.zig b/src/binary.zig index 3d1e454..d5aa17c 100644 --- a/src/binary.zig +++ b/src/binary.zig @@ -12,9 +12,7 @@ const unpackIntValue = @import("int.zig").unpackIntValue; const unpackShortIntValue = @import("int.zig").unpackShortIntValue; pub fn sizeOfPackedBinaryHeader(len: usize) !usize { - if (len <= hdrs.FIXSTR_MAX - hdrs.FIXSTR_MIN) { - return 1; - } else if (len <= std.math.maxInt(u8)) { + if (len <= std.math.maxInt(u8)) { return 1 + @sizeOf(u8); } else if (len <= std.math.maxInt(u16)) { return 1 + @sizeOf(u16); @@ -30,16 +28,14 @@ pub fn sizeOfPackedBinary(len: usize) !usize { } pub fn packBinaryHeader(writer: *std.Io.Writer, len: usize) !void { - if (len <= hdrs.FIXSTR_MAX - hdrs.FIXSTR_MIN) { - try writer.writeByte(hdrs.FIXSTR_MIN + @as(u8, @intCast(len))); - } else if (len <= std.math.maxInt(u8)) { - try writer.writeByte(hdrs.STR8); + if (len <= std.math.maxInt(u8)) { + try writer.writeByte(hdrs.BIN8); try packIntValue(writer, u8, @intCast(len)); } else if (len <= std.math.maxInt(u16)) { - try writer.writeByte(hdrs.STR16); + try writer.writeByte(hdrs.BIN16); try packIntValue(writer, u16, @intCast(len)); } else if (len <= std.math.maxInt(u32)) { - try writer.writeByte(hdrs.STR32); + try writer.writeByte(hdrs.BIN32); try packIntValue(writer, u32, @intCast(len)); } else { return error.BinaryTooLong; @@ -50,6 +46,9 @@ pub fn unpackBinaryHeader(reader: *std.Io.Reader, comptime MaybeOptionalType: ty const Type = NonOptional(MaybeOptionalType); const header = try reader.takeByte(); switch (header) { + hdrs.BIN8 => return try unpackIntValue(reader, u8, Type), + hdrs.BIN16 => return try unpackIntValue(reader, u16, Type), + hdrs.BIN32 => return try unpackIntValue(reader, u32, Type), hdrs.FIXSTR_MIN...hdrs.FIXSTR_MAX => return try unpackShortIntValue(header, hdrs.FIXSTR_MIN, hdrs.FIXSTR_MAX, Type), hdrs.STR8 => return try unpackIntValue(reader, u8, Type), hdrs.STR16 => return try unpackIntValue(reader, u16, Type), @@ -89,7 +88,7 @@ pub fn unpackBinaryInto(reader: *std.Io.Reader, buf: []u8) ![]u8 { pub const Binary = struct { data: []const u8, - pub fn msgpackWrite(self: *Binary, packer: anytype) !void { + pub fn msgpackWrite(self: Binary, packer: anytype) !void { try packer.writeBinary(self.data); } @@ -101,21 +100,29 @@ pub const Binary = struct { const packed_null = [_]u8{0xc0}; const packed_abc = [_]u8{ 0xa3, 0x61, 0x62, 0x63 }; +const packed_bin_abc = [_]u8{ 0xc4, 0x03, 0x61, 0x62, 0x63 }; test "packBinary: abc" { var buffer: [16]u8 = undefined; var writer = std.Io.Writer.fixed(&buffer); try packBinary(&writer, []const u8, "abc"); - try std.testing.expectEqualSlices(u8, &packed_abc, writer.buffered()); + try std.testing.expectEqualSlices(u8, &packed_bin_abc, writer.buffered()); } -test "unpackBinary: abc" { +test "unpackBinary: abc from string header" { var reader = std.Io.Reader.fixed(&packed_abc); const data = try unpackBinary(&reader, std.testing.allocator); defer std.testing.allocator.free(data); try std.testing.expectEqualSlices(u8, "abc", data); } +test "unpackBinary: abc bin8" { + var reader = std.Io.Reader.fixed(&packed_bin_abc); + const data = try unpackBinary(&reader, std.testing.allocator); + defer std.testing.allocator.free(data); + try std.testing.expectEqualSlices(u8, "abc", data); +} + test "packBinary: null" { var buffer: [16]u8 = undefined; var writer = std.Io.Writer.fixed(&buffer); @@ -124,5 +131,5 @@ test "packBinary: null" { } test "sizeOfPackedBinary" { - try std.testing.expectEqual(1, sizeOfPackedBinary(0)); + try std.testing.expectEqual(2, sizeOfPackedBinary(0)); } diff --git a/src/msgpack.zig b/src/msgpack.zig index 4257bd0..804f931 100644 --- a/src/msgpack.zig +++ b/src/msgpack.zig @@ -197,7 +197,7 @@ pub const Unpacker = struct { } pub fn readBinary(self: Unpacker) ![]const u8 { - return unpackString(self.reader, self.allocator); + return unpackBinary(self.reader, self.allocator); } pub fn readBinaryInto(self: Unpacker, buffer: []u8) ![]const u8 { @@ -364,3 +364,11 @@ test "encode/decode enum" { try std.testing.expectEqual(@as(?Status, .pending), decoded.value); } } + +test "unpacker readBinary reads bin8" { + const packed_bin_abc = [_]u8{ 0xc4, 0x03, 0x61, 0x62, 0x63 }; + var reader = std.Io.Reader.fixed(&packed_bin_abc); + const value = try unpacker(&reader, std.testing.allocator).readBinary(); + defer std.testing.allocator.free(value); + try std.testing.expectEqualSlices(u8, "abc", value); +}