@@ 14,9 14,8 @@ pub fn NetStringParser(comptime ReaderType: type) type {
const Error = ReaderType.Error;
const Reader = std.io.Reader(*@This(), Error, read);
- /// Aligns reader at beginning of next netstring. Returns true if
- /// another netstring was found, false if not.
- pub fn next(self: *@This()) !bool {
+ /// Moves input to beginning of next netstring and returns a Reader for it.
+ pub fn next(self: *@This()) !?Reader {
var r = self.child_reader.reader();
// move stream to end of current netstring
if (self.child_reader.bytes_read < self.end) {
@@ 27,16 26,16 @@ pub fn NetStringParser(comptime ReaderType: type) type {
if (size_str) |s| {
const size = try std.fmt.parseUnsigned(usize, s, 10);
self.end = self.child_reader.bytes_read + size + 1;
- return true;
+ return self.reader();
} else {
- return false;
+ return null;
}
}
/// Reads bytes from the current netstring returning number of bytes read.
/// If the number of bytes read is 0 it means the stream reached the end
/// of the current netstring.
- pub fn read(self: *@This(), buf: []u8) Error!usize {
+ fn read(self: *@This(), buf: []u8) Error!usize {
// read until one byte before end because of tailing comma
if (self.child_reader.bytes_read + 1 >= self.end) {
return 0;
@@ 51,7 50,7 @@ pub fn NetStringParser(comptime ReaderType: type) type {
/// Returns a std.io.Reader for the current netstring. Calling `next()`
/// on this parser will move the reader onto the next netstring. This
/// must be done before the first netstring can be read.
- pub fn reader(self: *@This()) Reader {
+ fn reader(self: *@This()) Reader {
return .{ .context = self };
}
};
@@ 66,77 65,73 @@ test "parse empty input stream" {
var p = netStringParser(input.reader());
var msg: [1024]u8 = undefined;
try testing.expectEqual(@intCast(usize, 0), try p.reader().read(&msg));
- try testing.expectEqual(false, try p.next());
+ try testing.expectEqual(try p.next(), null);
}
test "parse single netstring" {
var input = std.io.fixedBufferStream("5:hello,");
var p = netStringParser(input.reader());
var msg: [1024]u8 = undefined;
- const r = p.reader();
- try testing.expectEqual(true, try p.next());
+ const r = (try p.next()).?;
const bytes = try r.read(&msg);
try testing.expectEqual(@intCast(usize, 5), bytes);
try testing.expectEqualSlices(u8, "hello", msg[0..bytes]);
try testing.expectEqual(@intCast(usize, 0), try r.read(&msg));
- try testing.expectEqual(false, try p.next());
+ try testing.expectEqual(try p.next(), null);
}
test "parse multiple netstrings" {
var input = std.io.fixedBufferStream("5:hello,1:,,7: world!,");
var p = netStringParser(input.reader());
var msg: [1024]u8 = undefined;
- const r = p.reader();
- try testing.expectEqual(true, try p.next());
{
+ const r = (try p.next()).?;
const bytes = try r.read(&msg);
try testing.expectEqual(@intCast(usize, 5), bytes);
try testing.expectEqualSlices(u8, "hello", msg[0..bytes]);
try testing.expectEqual(@intCast(usize, 0), try r.read(&msg));
}
- try testing.expectEqual(true, try p.next());
{
+ const r = (try p.next()).?;
const bytes = try r.read(&msg);
try testing.expectEqual(@intCast(usize, 1), bytes);
try testing.expectEqualSlices(u8, ",", msg[0..bytes]);
try testing.expectEqual(@intCast(usize, 0), try r.read(&msg));
}
- try testing.expectEqual(true, try p.next());
{
+ const r = (try p.next()).?;
const bytes = try r.read(&msg);
try testing.expectEqual(@intCast(usize, 7), bytes);
try testing.expectEqualSlices(u8, " world!", msg[0..bytes]);
try testing.expectEqual(@intCast(usize, 0), try r.read(&msg));
}
- try testing.expectEqual(false, try p.next());
+ try testing.expectEqual(try p.next(), null);
}
test "calling next before completely reading current netstring" {
var input = std.io.fixedBufferStream("3:foo,3:bar,");
var p = netStringParser(input.reader());
var msg: [1]u8 = undefined;
- const r = p.reader();
- try testing.expectEqual(true, try p.next());
{
+ const r = (try p.next()).?;
const bytes = try r.read(&msg);
try testing.expectEqual(@intCast(usize, 1), bytes);
try testing.expectEqualSlices(u8, "f", msg[0..bytes]);
}
- try testing.expectEqual(true, try p.next());
{
+ const r = (try p.next()).?;
const bytes = try r.read(&msg);
try testing.expectEqual(@intCast(usize, 1), bytes);
try testing.expectEqualSlices(u8, "b", msg[0..bytes]);
+ // attempt to keep reading past current netstring
+ try testing.expectEqual(try p.next(), null);
+ try testing.expectEqual(@intCast(usize, 0), try r.read(&msg));
}
- try testing.expectEqual(false, try p.next());
- try testing.expectEqual(@intCast(usize, 0), try r.read(&msg));
}
test "invalid input" {
var input = std.io.fixedBufferStream("hello");
var p = netStringParser(input.reader());
var msg: [1024]u8 = undefined;
- const r = p.reader();
try testing.expectError(error.InvalidCharacter, p.next());
- try testing.expectEqual(@intCast(usize, 0), try r.read(&msg));
}