aboutsummaryrefslogtreecommitdiff
path: root/src/proto/row_description.zig
diff options
context:
space:
mode:
authorMartin Ashby <martin@ashbysoft.com>2023-09-28 10:54:58 +0100
committerMartin Ashby <martin@ashbysoft.com>2023-09-28 10:54:58 +0100
commit35494bc81b59165ee9264cd1004bb05a120279a3 (patch)
tree8d11946f8fc20e1f254301100e860f28bade5ee0 /src/proto/row_description.zig
parent0c063d42430077881e563120ebfcf92c2cecf463 (diff)
downloadpgz-35494bc81b59165ee9264cd1004bb05a120279a3.tar.gz
pgz-35494bc81b59165ee9264cd1004bb05a120279a3.tar.bz2
pgz-35494bc81b59165ee9264cd1004bb05a120279a3.tar.xz
pgz-35494bc81b59165ee9264cd1004bb05a120279a3.zip
Reduce allocations, the message takes ownership of the bytes read from
the stream and is responsible for deallocating, rather than copying them to their own storage.
Diffstat (limited to 'src/proto/row_description.zig')
-rw-r--r--src/proto/row_description.zig35
1 files changed, 18 insertions, 17 deletions
diff --git a/src/proto/row_description.zig b/src/proto/row_description.zig
index b8105e2..ff17716 100644
--- a/src/proto/row_description.zig
+++ b/src/proto/row_description.zig
@@ -11,7 +11,7 @@ pub const Tag: u8 = 'T';
const RowDescription = @This();
buf: ?[]const u8 = null, // owned
-fields: ?[]Field = null, // owned
+fields: []Field, // owned
pub const Field = struct {
name: []const u8,
@@ -23,19 +23,18 @@ pub const Field = struct {
format_code: FormatCode,
};
-pub fn read(a: std.mem.Allocator, b: []const u8) !RowDescription {
- var res: RowDescription = undefined;
- res.buf = try a.dupe(u8, b);
- errdefer res.deinit(a);
- var fbs = std.io.fixedBufferStream(res.buf.?);
+pub fn read(a: std.mem.Allocator, buf: []const u8) !RowDescription {
+ errdefer a.free(buf);
+ var fbs = std.io.fixedBufferStream(buf);
var reader = fbs.reader();
const n_fields = try reader.readIntBig(u16);
- res.fields = try a.alloc(Field, n_fields);
+ var fields = try a.alloc(Field, n_fields);
+ errdefer a.free(fields);
for (0..n_fields) |i| {
const name_start = fbs.pos;
try reader.skipUntilDelimiterOrEof(0);
const name_end = fbs.pos - 1;
- const name = res.buf.?[name_start..name_end];
+ const name = buf[name_start..name_end];
const field = Field{
.name = name,
.table_oid = try reader.readIntBig(u32),
@@ -45,9 +44,12 @@ pub fn read(a: std.mem.Allocator, b: []const u8) !RowDescription {
.data_type_modifier = try reader.readIntBig(u32),
.format_code = enum_from_int(FormatCode, try reader.readIntBig(u16)) orelse return ProtocolError.InvalidFormatCode,
};
- res.fields.?[i] = field;
+ fields[i] = field;
}
- return res;
+ return .{
+ .buf = buf,
+ .fields = fields,
+ };
}
pub fn write(self: RowDescription, a: std.mem.Allocator, stream_writer: anytype) !void {
@@ -57,8 +59,8 @@ pub fn write(self: RowDescription, a: std.mem.Allocator, stream_writer: anytype)
var cw = std.io.countingWriter(al.writer());
var writer = cw.writer();
try writer.writeIntBig(u32, 0); // length placeholder
- try writer.writeIntBig(u16, @as(u16, @intCast(self.fields.?.len)));
- for (self.fields.?) |field| {
+ try writer.writeIntBig(u16, @as(u16, @intCast(self.fields.len)));
+ for (self.fields) |field| {
try writer.writeAll(field.name);
try writer.writeByte(0);
try writer.writeIntBig(u32, field.table_oid);
@@ -73,7 +75,7 @@ pub fn write(self: RowDescription, a: std.mem.Allocator, stream_writer: anytype)
}
pub fn deinit(self: *RowDescription, a: std.mem.Allocator) void {
- if (self.fields != null) a.free(self.fields.?);
+ a.free(self.fields);
if (self.buf != null) a.free(self.buf.?);
}
@@ -125,12 +127,11 @@ test "round trip" {
try std.testing.expectEqual(Tag, tag);
const len = try reader.readIntBig(u32);
const buf = try allocator.alloc(u8, len - 4);
- defer allocator.free(buf);
try reader.readNoEof(buf);
var sm2 = try RowDescription.read(allocator, buf);
defer sm2.deinit(allocator);
- try std.testing.expectEqualDeep(f0, sm2.fields.?[0]);
- try std.testing.expectEqualDeep(f1, sm2.fields.?[1]);
- try std.testing.expectEqualDeep(f2, sm2.fields.?[2]);
+ try std.testing.expectEqualDeep(f0, sm2.fields[0]);
+ try std.testing.expectEqualDeep(f1, sm2.fields[1]);
+ try std.testing.expectEqualDeep(f2, sm2.fields[2]);
}