mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
std.io.Reader.peekDelimiterInclusive: simplify and fix
This commit is contained in:
parent
93ac76594a
commit
c072cf2bb8
@ -752,6 +752,11 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
|
|||||||
@branchHint(.likely);
|
@branchHint(.likely);
|
||||||
return buffer[seek .. end + 1];
|
return buffer[seek .. end + 1];
|
||||||
}
|
}
|
||||||
|
if (r.vtable.stream == &endingStream) {
|
||||||
|
// Protect the `@constCast` of `fixed`.
|
||||||
|
return error.EndOfStream;
|
||||||
|
}
|
||||||
|
r.rebase();
|
||||||
while (r.buffer.len - r.end != 0) {
|
while (r.buffer.len - r.end != 0) {
|
||||||
const end_cap = r.buffer[r.end..];
|
const end_cap = r.buffer[r.end..];
|
||||||
var writer: Writer = .fixed(end_cap);
|
var writer: Writer = .fixed(end_cap);
|
||||||
@ -761,29 +766,9 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
|
|||||||
};
|
};
|
||||||
r.end += n;
|
r.end += n;
|
||||||
if (std.mem.indexOfScalarPos(u8, end_cap[0..n], 0, delimiter)) |end| {
|
if (std.mem.indexOfScalarPos(u8, end_cap[0..n], 0, delimiter)) |end| {
|
||||||
return r.buffer[seek .. r.end - n + end + 1];
|
return r.buffer[0 .. r.end - n + end + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var i: usize = 0;
|
|
||||||
while (seek - i != 0) {
|
|
||||||
const begin_cap = r.buffer[i..seek];
|
|
||||||
var writer: Writer = .fixed(begin_cap);
|
|
||||||
const n = r.vtable.stream(r, &writer, .limited(begin_cap.len)) catch |err| switch (err) {
|
|
||||||
error.WriteFailed => unreachable,
|
|
||||||
else => |e| return e,
|
|
||||||
};
|
|
||||||
i += n;
|
|
||||||
if (std.mem.indexOfScalarPos(u8, r.buffer[0..seek], i, delimiter)) |end| {
|
|
||||||
std.mem.rotate(u8, r.buffer, seek);
|
|
||||||
r.seek = 0;
|
|
||||||
r.end += i;
|
|
||||||
return r.buffer[0 .. seek + end + 1];
|
|
||||||
}
|
|
||||||
} else if (i != 0) {
|
|
||||||
std.mem.rotate(u8, r.buffer, seek);
|
|
||||||
r.seek = 0;
|
|
||||||
r.end += i;
|
|
||||||
}
|
|
||||||
return error.StreamTooLong;
|
return error.StreamTooLong;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1665,6 +1650,23 @@ test "readAlloc when the backing reader provides one byte at a time" {
|
|||||||
try std.testing.expectEqualStrings(str, res);
|
try std.testing.expectEqualStrings(str, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "takeDelimiterInclusive when it rebases" {
|
||||||
|
const written_line = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n";
|
||||||
|
var buffer: [128]u8 = undefined;
|
||||||
|
var tr: std.testing.Reader = .init(&buffer, &.{
|
||||||
|
.{ .buffer = written_line },
|
||||||
|
.{ .buffer = written_line },
|
||||||
|
.{ .buffer = written_line },
|
||||||
|
.{ .buffer = written_line },
|
||||||
|
.{ .buffer = written_line },
|
||||||
|
.{ .buffer = written_line },
|
||||||
|
});
|
||||||
|
const r = &tr.interface;
|
||||||
|
for (0..6) |_| {
|
||||||
|
try std.testing.expectEqualStrings(written_line, try r.takeDelimiterInclusive('\n'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Provides a `Reader` implementation by passing data from an underlying
|
/// Provides a `Reader` implementation by passing data from an underlying
|
||||||
/// reader through `Hasher.update`.
|
/// reader through `Hasher.update`.
|
||||||
///
|
///
|
||||||
|
|||||||
@ -1206,3 +1206,43 @@ pub inline fn fuzz(
|
|||||||
) anyerror!void {
|
) anyerror!void {
|
||||||
return @import("root").fuzz(context, testOne, options);
|
return @import("root").fuzz(context, testOne, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A `std.io.Reader` that writes a predetermined list of buffers during `stream`.
|
||||||
|
pub const Reader = struct {
|
||||||
|
calls: []const Call,
|
||||||
|
interface: std.io.Reader,
|
||||||
|
next_call_index: usize,
|
||||||
|
next_offset: usize,
|
||||||
|
|
||||||
|
pub const Call = struct {
|
||||||
|
buffer: []const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn init(buffer: []u8, calls: []const Call) Reader {
|
||||||
|
return .{
|
||||||
|
.next_call_index = 0,
|
||||||
|
.next_offset = 0,
|
||||||
|
.interface = .{
|
||||||
|
.vtable = &.{ .stream = stream },
|
||||||
|
.buffer = buffer,
|
||||||
|
.seek = 0,
|
||||||
|
.end = 0,
|
||||||
|
},
|
||||||
|
.calls = calls,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stream(io_r: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
|
||||||
|
const r: *Reader = @alignCast(@fieldParentPtr("interface", io_r));
|
||||||
|
if (r.calls.len - r.next_call_index == 0) return error.EndOfStream;
|
||||||
|
const call = r.calls[r.next_call_index];
|
||||||
|
const buffer = limit.sliceConst(call.buffer[r.next_offset..]);
|
||||||
|
const n = try w.write(buffer);
|
||||||
|
r.next_offset += n;
|
||||||
|
if (call.buffer.len - r.next_offset == 0) {
|
||||||
|
r.next_call_index += 1;
|
||||||
|
r.next_offset = 0;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user