feature. See also
. The project being documented here (as the example) is the Zig library itself.
errors.CorrespondingLines
const CorrespondingLines = struct
File
Code
const CorrespondingLines = struct {
// track of this being truncated, since the extra codepoint will ensure
// the visual line will need to truncate in that case.
line_buf: [max_source_line_bytes + 4]u8 = undefined,
line_len: usize = 0,
visual_line_buf: [max_source_line_bytes]u8 = undefined,
visual_line_len: usize = 0,
truncated: bool = false,
line_num: usize = 1,
initial_line: bool = true,
last_byte: u8 = 0,
at_eof: bool = false,
span: SourceMappings.CorrespondingSpan,
file: Io.File,
file_reader: Io.File.Reader,
code_page: SupportedCodePage,
pub fn init(
io: Io,
cwd: Io.Dir,
err_details: ErrorDetails,
line_for_comparison: []const u8,
corresponding_span: SourceMappings.CorrespondingSpan,
corresponding_file: []const u8,
file_reader_buf: []u8,
) !CorrespondingLines {
// number is different
if (err_details.err == .string_literal_too_long and err_details.token.line_number != corresponding_span.start_line) {
return error.NotWorthPrintingNote;
}
if (err_details.err == .string_literal_too_long) {
return error.NotWorthPrintingLines;
}
var corresponding_lines = CorrespondingLines{
.span = corresponding_span,
.file = try cwd.openFile(io, corresponding_file, .{ .allow_directory = false }),
.code_page = err_details.code_page,
.file_reader = undefined,
};
corresponding_lines.file_reader = corresponding_lines.file.reader(io, file_reader_buf);
errdefer corresponding_lines.deinit(io);
try corresponding_lines.writeLineFromStreamVerbatim(
&corresponding_lines.file_reader.interface,
corresponding_span.start_line,
);
const visual_line = writeSourceSlice(
&corresponding_lines.visual_line_buf,
corresponding_lines.line_buf[0..corresponding_lines.line_len],
err_details.code_page,
);
corresponding_lines.visual_line_len = visual_line.line.len;
corresponding_lines.truncated = visual_line.truncated;
if (corresponding_span.start_line == corresponding_span.end_line and std.mem.eql(
u8,
line_for_comparison,
corresponding_lines.visual_line_buf[0..corresponding_lines.visual_line_len],
)) {
return error.NotWorthPrintingNote;
}
return corresponding_lines;
}
pub fn next(self: *CorrespondingLines) !?VisualLine {
if (self.initial_line) {
self.initial_line = false;
return .{
.line = self.visual_line_buf[0..self.visual_line_len],
.truncated = self.truncated,
};
}
if (self.line_num > self.span.end_line) return null;
if (self.at_eof) return error.LinesNotFound;
self.line_len = 0;
self.visual_line_len = 0;
try self.writeLineFromStreamVerbatim(
&self.file_reader.interface,
self.line_num,
);
const visual_line = writeSourceSlice(
&self.visual_line_buf,
self.line_buf[0..self.line_len],
self.code_page,
);
self.visual_line_len = visual_line.line.len;
return visual_line;
}
fn writeLineFromStreamVerbatim(self: *CorrespondingLines, input: *std.Io.Reader, line_num: usize) !void {
while (try readByteOrEof(input)) |byte| {
switch (byte) {
'\n', '\r' => {
if (!utils.isLineEndingPair(self.last_byte, byte)) {
const line_complete = self.line_num == line_num;
self.line_num += 1;
if (line_complete) {
self.last_byte = byte;
return;
}
} else {
// consecutive CRLF pairs don't get treated as one
// long line ending 'pair'
self.last_byte = 0;
continue;
}
},
else => {
if (self.line_num == line_num and self.line_len < self.line_buf.len) {
self.line_buf[self.line_len] = byte;
self.line_len += 1;
}
},
}
self.last_byte = byte;
}
self.at_eof = true;
self.line_num += 1;
}
fn readByteOrEof(reader: *std.Io.Reader) !?u8 {
return reader.takeByte() catch |err| switch (err) {
error.EndOfStream => return null,
else => |e| return e,
};
}
pub fn deinit(self: *CorrespondingLines, io: Io) void {
self.file.close(io);
}
}