forked from lalinsky/msgpack.zig
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbinary.zig
More file actions
135 lines (112 loc) · 4.52 KB
/
Copy pathbinary.zig
File metadata and controls
135 lines (112 loc) · 4.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
const std = @import("std");
const hdrs = @import("headers.zig");
const isOptional = @import("utils.zig").isOptional;
const NonOptional = @import("utils.zig").NonOptional;
const maybePackNull = @import("null.zig").maybePackNull;
const maybeUnpackNull = @import("null.zig").maybeUnpackNull;
const packIntValue = @import("int.zig").packIntValue;
const unpackIntValue = @import("int.zig").unpackIntValue;
const unpackShortIntValue = @import("int.zig").unpackShortIntValue;
pub fn sizeOfPackedBinaryHeader(len: usize) !usize {
if (len <= std.math.maxInt(u8)) {
return 1 + @sizeOf(u8);
} else if (len <= std.math.maxInt(u16)) {
return 1 + @sizeOf(u16);
} else if (len <= std.math.maxInt(u32)) {
return 1 + @sizeOf(u32);
} else {
return error.BinaryTooLong;
}
}
pub fn sizeOfPackedBinary(len: usize) !usize {
return try sizeOfPackedBinaryHeader(len) + len;
}
pub fn packBinaryHeader(writer: *std.Io.Writer, len: usize) !void {
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.BIN16);
try packIntValue(writer, u16, @intCast(len));
} else if (len <= std.math.maxInt(u32)) {
try writer.writeByte(hdrs.BIN32);
try packIntValue(writer, u32, @intCast(len));
} else {
return error.BinaryTooLong;
}
}
pub fn unpackBinaryHeader(reader: *std.Io.Reader, comptime MaybeOptionalType: type) !MaybeOptionalType {
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),
hdrs.STR32 => return try unpackIntValue(reader, u32, Type),
else => return maybeUnpackNull(header, MaybeOptionalType),
}
}
pub fn packBinary(writer: *std.Io.Writer, comptime T: type, value_or_maybe_null: T) !void {
const value = try maybePackNull(writer, T, value_or_maybe_null) orelse return;
try packBinaryHeader(writer, value.len);
try writer.writeAll(value);
}
pub fn unpackBinary(reader: *std.Io.Reader, allocator: std.mem.Allocator) ![]u8 {
const len = try unpackBinaryHeader(reader, u32);
const data = try allocator.alloc(u8, len);
errdefer allocator.free(data);
try reader.readSliceAll(data);
return data;
}
pub fn unpackBinaryInto(reader: *std.Io.Reader, buf: []u8) ![]u8 {
const len = try unpackBinaryHeader(reader, u32);
if (len > buf.len) {
return error.NoSpaceLeft;
}
const data = buf[0..len];
try reader.readSliceAll(data);
return data;
}
pub const Binary = struct {
data: []const u8,
pub fn msgpackWrite(self: Binary, packer: anytype) !void {
try packer.writeBinary(self.data);
}
pub fn msgpackRead(unpacker: anytype) !Binary {
const data = try unpacker.readBinary();
return Binary{ .data = data };
}
};
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_bin_abc, writer.buffered());
}
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);
try packBinary(&writer, ?[]const u8, null);
try std.testing.expectEqualSlices(u8, &packed_null, writer.buffered());
}
test "sizeOfPackedBinary" {
try std.testing.expectEqual(2, sizeOfPackedBinary(0));
}