uyha/mzg
A MessagePack library for Zig
mzg
is a MessagePack library for Zig with no allocations, and the API favors
the streaming usage.
Run the following command to add this project as a dependency
zig fetch --save git+https://github.com/uyha/mzg.git#v0.0.3
In your build.zig
, add the following
const mzg = b.dependency("mzg", .{
.target = target,
.optimize = optimize,
});
// Replace `exe` with your actual library or executable
exe.root_module.addImport("mzg", mzg.module("mzg"));
pack
for packing Zig values using a writer
packWithOptions
is like pack
but accepts a mzg.PackOptions
parameter to
control the packing behavior.unpack
for unpacking a MessagePack message into a Zig objectmzg.adapter
namespace to help with packing
and unpacking common container types.There are a set of pack*
and unpack*
functions that translate between a
precise set of Zig types and MessagePack. These functions can be used when
implementing custom packing and unpacking.
All examples live in examples directory.
Converting a byte slice to MessagePack and back
pub fn main() !void {
const allocator = std.heap.page_allocator;
var buffer: std.ArrayListUnmanaged(u8) = .empty;
defer buffer.deinit(allocator);
try mzg.pack(
"a string with some characters for demonstration purpose",
buffer.writer(allocator),
);
var string: []const u8 = undefined;
const size = try mzg.unpack(buffer.items, &string);
std.debug.print("Consumed {} bytes\n", .{size});
std.debug.print("string: {s}\n", .{string});
}
const std = @import("std");
const mzg = @import("mzg");
Certain types can be packed and unpacked by default (refer to Mapping for more details)
pub fn main() !void {
const allocator = std.heap.page_allocator;
var buffer: std.ArrayListUnmanaged(u8) = .empty;
defer buffer.deinit(allocator);
try mzg.pack(
Targets{ .position = .init(2000), .velocity = .init(10) },
buffer.writer(allocator),
);
var targets: Targets = undefined;
const size = try mzg.unpack(buffer.items, &targets);
std.debug.print("Consumed {} bytes\n", .{size});
std.debug.print("Targets: {}\n", .{targets});
}
const Position = enum(i32) {
_,
pub fn init(raw: std.meta.Tag(@This())) @This() {
return @enumFromInt(raw);
}
};
const Velocity = enum(i32) {
_,
pub fn init(raw: std.meta.Tag(@This())) @This() {
return @enumFromInt(raw);
}
};
const Targets = struct {
position: Position,
velocity: Velocity,
};
const std = @import("std");
const mzg = @import("mzg");
const adapter = mzg.adapter;
Many container types in the std
library cannot be packed or unpacked by
default, but the adapter functions make it easy to work with these types.
pub fn main() !void {
const allocator = std.heap.page_allocator;
var buffer: std.ArrayListUnmanaged(u8) = .empty;
defer buffer.deinit(allocator);
var in: std.ArrayListUnmanaged(u32) = .empty;
defer in.deinit(allocator);
try in.append(allocator, 42);
try in.append(allocator, 75);
try mzg.pack(adapter.packArray(&in), buffer.writer(allocator));
var out: std.ArrayListUnmanaged(u32) = .empty;
defer out.deinit(allocator);
const size = try mzg.unpack(
buffer.items,
adapter.unpackArray(&out, allocator),
);
std.debug.print("Consumed {} bytes\n", .{size});
std.debug.print("out: {any}\n", .{out.items});
}
const std = @import("std");
const mzg = @import("mzg");
const adapter = mzg.adapter;
Zig Type | MessagePack |
---|---|
void , null |
nil |
bool |
bool |
integers (<=64 bits) | int |
floats (<=64 bits) | float |
?T |
nil if value is null , pack according to T otherwise |
enums | int |
enum literals | str |
tagged unions | array of 2 elements: int and the value of the union |
packed structs | int |
structs and tuples | array of fields in the order they are declared |
[N] , [] , [:X] , and @Vec of u8 |
str |
[N] , [] , [:X] , and @Vec of T |
array of T |
Ext |
ext |
Timestamp |
Timestamp |
*T |
T |
MessagePack | Compatible Zig Type |
---|---|
nil |
void , ?T |
bool |
bool |
int |
integers, enums |
float |
floats |
str |
[]const u8 |
bin |
[]const u8 |
array |
The length can be read into integers |
map |
The length can be read into integers |
ext |
Ext |
Timestamp |
Timestamp |
When an enum/union/struct has an mzgPack
function with the signature being
one of
pub fn mzgPack(self: *@This(), writer: anytype) !void
pub fn mzgPack(self: *@This(), options: mzg.PackOptions, writer: anytype) !void
The function will be called when the mzg.pack
function is used.
When an enum/union/struct has an mzgUnpack
function with the signature being
pub fn mzgUnpack(self: @This(), buffer: []const u8) UnpackError!usize
The function will be called when the mzg.unpack
function is used.