message: more iterators, less problems

This seems like a pretty nice way to do this, since it lets us produce
the sliced version of each value rather than the somewhat janky many
pointer.
This commit is contained in:
torque 2023-08-23 22:03:25 -07:00
parent ebd3e64111
commit b101e0acd2
Signed by: torque
SSH Key Fingerprint: SHA256:nCrXefBNo6EbjNSQhv0nXmEg/VuNq3sMF5b8zETw3Tk
2 changed files with 57 additions and 15 deletions

View File

@ -15,14 +15,20 @@ pub fn main() !void {
try message.deleteHeader("My-Key3"); try message.deleteHeader("My-Key3");
var iter = try message.headerIterator(); {
defer iter.destroy(); var iter = try message.headerIterator();
defer iter.destroy();
while (try iter.next()) |pair| { while (iter.next()) |resolv| {
std.debug.print( var val_iter = try resolv.getValueIterator();
"Key: '{s}', Value: '{s}'\n", defer val_iter.destroy();
.{ pair.key, pair.value orelse "null" },
); std.debug.print("key '{s}' got: ", .{resolv.key});
while (val_iter.next()) |value| {
std.debug.print("'{s}', ", .{value});
}
std.debug.print("\n", .{});
}
} }
const subscription = try connection.subscribeSync("subject"); const subscription = try connection.subscribeSync("subject");
@ -33,13 +39,12 @@ pub fn main() !void {
defer received.destroy(); defer received.destroy();
{ {
const vals1 = try received.getAllHeaderValues("My-Key1"); var iter = try received.getHeaderValueIterator("My-Key1");
defer std.heap.raw_c_allocator.free(vals1); defer iter.destroy();
std.debug.print("For key 'My-Key1' got: ", .{});
for (vals1) |value| {
const val = std.mem.sliceTo(value, 0);
std.debug.print("'{s}', ", .{val}); std.debug.print("For key 'My-Key1' got: ", .{});
while (iter.next()) |value| {
std.debug.print("'{s}', ", .{value});
} }
std.debug.print("\n", .{}); std.debug.print("\n", .{});
} }

View File

@ -76,6 +76,10 @@ pub const Message = opaque {
}; };
} }
pub fn getHeaderValueIterator(self: *Message, key: [:0]const u8) Error!HeaderValueIterator {
return .{ .values = try self.getAllHeaderValues(key) };
}
pub fn getAllHeaderKeys(self: *Message) Error![][*:0]const u8 { pub fn getAllHeaderKeys(self: *Message) Error![][*:0]const u8 {
var keys: [*c][*c]const u8 = undefined; var keys: [*c][*c]const u8 = undefined;
var count: c_int = 0; var count: c_int = 0;
@ -93,23 +97,56 @@ pub const Message = opaque {
}; };
} }
pub const HeaderValueIterator = struct {
values: [][*:0]const u8,
index: usize = 0,
pub fn destroy(self: HeaderValueIterator) void {
std.heap.raw_c_allocator.free(self.values);
}
pub fn next(self: *HeaderValueIterator) ?[:0]const u8 {
if (self.index >= self.values.len) return null;
defer self.index += 1;
return std.mem.sliceTo(self.values[self.index], 0);
}
};
pub const HeaderIterator = struct { pub const HeaderIterator = struct {
message: *Message, message: *Message,
keys: [][*:0]const u8, keys: [][*:0]const u8,
index: usize = 0, index: usize = 0,
pub const ValueResolver = struct {
message: *Message,
key: [:0]const u8,
pub fn getValue(self: ValueResolver) Error![:0]const u8 {
// TODO: if we didn't care about the lifecycle of self.message, we
// could do catch unreachable here and make this error-free
return try self.message.getHeaderValue(self.key);
}
pub fn getValueIterator(self: ValueResolver) Error!HeaderValueIterator {
return .{
.values = try self.message.getAllHeaderValues(self.key),
};
}
};
pub fn destroy(self: *HeaderIterator) void { pub fn destroy(self: *HeaderIterator) void {
std.heap.raw_c_allocator.free(self.keys); std.heap.raw_c_allocator.free(self.keys);
} }
pub fn next(self: *HeaderIterator) Error!?struct { key: [:0]const u8, value: ?[:0]const u8 } { pub fn next(self: *HeaderIterator) ?ValueResolver {
if (self.index >= self.keys.len) return null; if (self.index >= self.keys.len) return null;
defer self.index += 1; defer self.index += 1;
const sliced = std.mem.sliceTo(self.keys[self.index], 0); const sliced = std.mem.sliceTo(self.keys[self.index], 0);
return .{ return .{
.message = self.message,
.key = sliced, .key = sliced,
.value = try self.message.getHeaderValue(sliced),
}; };
} }