zig/lib/std/io/change_detection_stream.zig

59 lines
1.9 KiB
Zig

const std = @import("../std.zig");
const io = std.io;
const mem = std.mem;
const assert = std.debug.assert;
pub fn ChangeDetectionStream(comptime OutStreamType: type) type {
return struct {
const Self = @This();
pub const Error = OutStreamType.Error;
pub const OutStream = io.OutStream(*Self, Error, write);
anything_changed: bool = false,
out_stream: *OutStreamType,
source_index: usize,
source: []const u8,
pub fn init(source: []const u8, out_stream: *OutStreamType) Self {
return Self{
.out_stream = out_stream,
.source_index = 0,
.source = source,
};
}
pub fn outStream(self: *Self) OutStream {
return .{ .context = self };
}
fn write(self: *Self, bytes: []const u8) Error!usize {
if (!self.anything_changed) {
const end = self.source_index + bytes.len;
if (end > self.source.len) {
self.anything_changed = true;
} else {
const src_slice = self.source[self.source_index..end];
self.source_index += bytes.len;
if (!mem.eql(u8, bytes, src_slice)) {
self.anything_changed = true;
}
}
}
return self.out_stream.write(bytes);
}
pub fn changeDetected(self: *Self) bool {
return self.anything_changed or (self.source_index != self.source.len);
}
};
}
pub fn changeDetectionStream(
source: []const u8,
underlying_stream: anytype,
) ChangeDetectionStream(@TypeOf(underlying_stream).Child) {
comptime assert(@typeInfo(@TypeOf(underlying_stream)) == .Pointer);
return ChangeDetectionStream(@TypeOf(underlying_stream).Child).init(source, underlying_stream);
}