Skip to content

Commit e9f6062

Browse files
committed
Change msgpack to use API similar to std.json
1 parent a9b5497 commit e9f6062

File tree

5 files changed

+45
-21
lines changed

5 files changed

+45
-21
lines changed

lib/msgpack/README.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ const Message = struct {
1414
var buffer = std.ArrayList(u8).init(allocator);
1515
defer buffer.deinit();
1616
17-
try msgpack.encode(buffer.writer(), Message, .{
17+
try msgpack.encode(Message{
1818
.name = "John",
1919
.age = 20,
20-
});
20+
}, buffer.writer());
2121
22-
var stream = std.io.fixedBufferStream(buffer.items);
23-
const message = try decode(stream.reader(), allocator, Message);
24-
defer allocator.free(message.name);
22+
const decoded = try msgpack.decodeFromSlice(Message, allocator, buffer.items);
23+
defer decoded.deinit();
24+
25+
std.debug.assert(std.mem.eql(u8, decoded.name, "John"));
26+
std.debug.assert(decoded.age == 20);
2527
```
2628

2729
Change the default format from using field names to field indexes:

lib/msgpack/msgpack.zig

+28-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const std = @import("std");
22
const Allocator = std.mem.Allocator;
3+
const ArenaAllocator = std.heap.ArenaAllocator;
34

45
const NoAllocator = @import("utils.zig").NoAllocator;
56

@@ -245,18 +246,40 @@ pub fn unpacker(reader: anytype, allocator: ?Allocator) Unpacker(@TypeOf(reader)
245246
return Unpacker(@TypeOf(reader)).init(reader, allocator orelse NoAllocator.allocator());
246247
}
247248

248-
pub fn unpackerNoAlloc(reader: anytype) Unpacker(@TypeOf(reader)) {
249-
return Unpacker(@TypeOf(reader)).init(reader, NoAllocator.allocator());
249+
pub fn encode(value: anytype, writer: anytype) !void {
250+
return try packer(writer).write(@TypeOf(value), value);
250251
}
251252

252-
pub fn encode(writer: anytype, comptime T: type, value: T) !void {
253-
return try packer(writer).write(T, value);
253+
pub const Decoded = std.json.Parsed;
254+
255+
pub fn decode(comptime T: type, allocator: Allocator, reader: anytype) !Decoded(T) {
256+
var parsed = Decoded(T){
257+
.arena = try allocator.create(ArenaAllocator),
258+
.value = undefined,
259+
};
260+
errdefer allocator.destroy(parsed.arena);
261+
parsed.arena.* = ArenaAllocator.init(allocator);
262+
errdefer parsed.arena.deinit();
263+
264+
parsed.value = try decodeLeaky(T, parsed.arena.allocator(), reader);
265+
266+
return parsed;
254267
}
255268

256-
pub fn decode(reader: anytype, allocator: ?Allocator, comptime T: type) !T {
269+
pub fn decodeLeaky(comptime T: type, allocator: ?Allocator, reader: anytype) !T {
257270
return try unpacker(reader, allocator).read(T);
258271
}
259272

273+
pub fn decodeFromSlice(comptime T: type, allocator: Allocator, data: []const u8) !Decoded(T) {
274+
var stream = std.io.fixedBufferStream(data);
275+
return try decode(T, allocator, stream.reader());
276+
}
277+
278+
pub fn decodeFromSliceLeaky(comptime T: type, allocator: ?Allocator, data: []const u8) !T {
279+
var stream = std.io.fixedBufferStream(data);
280+
return try decodeLeaky(T, allocator, stream.reader());
281+
}
282+
260283
test {
261284
_ = std.testing.refAllDecls(@This());
262285
}

src/Oplog.zig

+3-3
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,10 @@ pub fn write(self: *Self, changes: []const Change) !u64 {
211211
var bufferred_writer = std.io.bufferedWriter(file.writer());
212212
const writer = bufferred_writer.writer();
213213

214-
try msgpack.encode(writer, Transaction, .{
214+
try msgpack.encode(Transaction{
215215
.id = commit_id,
216216
.changes = changes,
217-
});
217+
}, writer);
218218

219219
try bufferred_writer.flush();
220220

@@ -341,7 +341,7 @@ pub const OplogFileIterator = struct {
341341
pub fn next(self: *OplogFileIterator) !?Transaction {
342342
_ = self.arena.reset(.retain_capacity);
343343

344-
return msgpack.decode(self.buffered_reader.reader(), self.arena.allocator(), Transaction) catch |err| {
344+
return msgpack.decodeLeaky(Transaction, self.arena.allocator(), self.buffered_reader.reader()) catch |err| {
345345
if (err == error.EndOfStream) {
346346
return null;
347347
}

src/filefmt.zig

+5-5
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ pub fn readSegmentFile(dir: fs.Dir, id: SegmentId, segment: *FileSegment) !void
384384
var fixed_buffer_stream = std.io.fixedBufferStream(raw_data[0..]);
385385
const reader = fixed_buffer_stream.reader();
386386

387-
const unpacker = msgpack.unpackerNoAlloc(reader);
387+
const unpacker = msgpack.unpacker(reader, null);
388388

389389
const header = try unpacker.read(SegmentFileHeader);
390390

@@ -513,8 +513,8 @@ pub fn writeIndexFile(dir: std.fs.Dir, segments: []const SegmentId) !void {
513513
var buffered_writer = std.io.bufferedWriter(file.file.writer());
514514
const writer = buffered_writer.writer();
515515

516-
try msgpack.encode(writer, IndexFileHeader, .{});
517-
try msgpack.encode(writer, []const SegmentId, segments);
516+
try msgpack.encode(IndexFileHeader{}, writer);
517+
try msgpack.encode(segments, writer);
518518

519519
try buffered_writer.flush();
520520

@@ -537,12 +537,12 @@ pub fn readIndexFile(dir: std.fs.Dir, allocator: std.mem.Allocator) ![]SegmentId
537537
var buffered_reader = std.io.bufferedReader(file.reader());
538538
const reader = buffered_reader.reader();
539539

540-
const header = try msgpack.decode(reader, allocator, IndexFileHeader);
540+
const header = try msgpack.decodeLeaky(IndexFileHeader, null, reader);
541541
if (header.magic != index_header_magic_v1) {
542542
return error.InvalidIndexfile;
543543
}
544544

545-
return try msgpack.decode(reader, allocator, []SegmentId);
545+
return try msgpack.decodeLeaky([]SegmentId, allocator, reader);
546546
}
547547

548548
test "readIndexFile/writeIndexFile" {

src/server.zig

+2-3
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ fn writeResponse(value: anytype, req: *httpz.Request, res: *httpz.Response) !voi
160160
.json => try res.json(value, .{}),
161161
.msgpack => {
162162
res.header("content-type", "application/vnd.msgpack");
163-
try msgpack.encode(res.writer(), @TypeOf(value), value);
163+
try msgpack.encode(value, res.writer());
164164
},
165165
}
166166
}
@@ -192,8 +192,7 @@ fn getRequestBody(comptime T: type, req: *httpz.Request, res: *httpz.Response) !
192192
};
193193
},
194194
.msgpack => {
195-
var stream = std.io.fixedBufferStream(content);
196-
return msgpack.decode(stream.reader(), req.arena, T) catch {
195+
return msgpack.decodeFromSliceLeaky(T, req.arena, content) catch {
197196
res.status = 400;
198197
try writeResponse(.{ .status = "invalid body" }, req, res);
199198
return null;

0 commit comments

Comments
 (0)