feature. See also
. The project being documented here (as the example) is the Zig library itself.
Fetch.UnpackResult
const UnpackResult = struct
File
Code
const UnpackResult = struct {
errors: []Error = undefined,
errors_count: usize = 0,
root_error_message: []const u8 = "",
// sub-directory indicated by the named path.
root_dir: []const u8 = "",
const Error = union(enum) {
unable_to_create_sym_link: struct {
code: anyerror,
file_name: []const u8,
link_name: []const u8,
},
unable_to_create_file: struct {
code: anyerror,
file_name: []const u8,
},
unsupported_file_type: struct {
file_name: []const u8,
file_type: u8,
},
fn excluded(self: Error, filter: Filter) bool {
const file_name = switch (self) {
.unable_to_create_file => |info| info.file_name,
.unable_to_create_sym_link => |info| info.file_name,
.unsupported_file_type => |info| info.file_name,
};
return !filter.includePath(file_name);
}
};
fn allocErrors(self: *UnpackResult, arena: std.mem.Allocator, n: usize, root_error_message: []const u8) !void {
self.root_error_message = try arena.dupe(u8, root_error_message);
self.errors = try arena.alloc(UnpackResult.Error, n);
}
fn hasErrors(self: *UnpackResult) bool {
return self.errors_count > 0;
}
fn unableToCreateFile(self: *UnpackResult, file_name: []const u8, err: anyerror) void {
self.errors[self.errors_count] = .{ .unable_to_create_file = .{
.code = err,
.file_name = file_name,
} };
self.errors_count += 1;
}
fn unableToCreateSymLink(self: *UnpackResult, file_name: []const u8, link_name: []const u8, err: anyerror) void {
self.errors[self.errors_count] = .{ .unable_to_create_sym_link = .{
.code = err,
.file_name = file_name,
.link_name = link_name,
} };
self.errors_count += 1;
}
fn unsupportedFileType(self: *UnpackResult, file_name: []const u8, file_type: u8) void {
self.errors[self.errors_count] = .{ .unsupported_file_type = .{
.file_name = file_name,
.file_type = file_type,
} };
self.errors_count += 1;
}
fn validate(self: *UnpackResult, f: *Fetch, filter: Filter) !void {
if (self.errors_count == 0) return;
var unfiltered_errors: u32 = 0;
for (self.errors) |item| {
if (item.excluded(filter)) continue;
unfiltered_errors += 1;
}
if (unfiltered_errors == 0) return;
const eb = &f.error_bundle;
try eb.addRootErrorMessage(.{
.msg = try eb.addString(self.root_error_message),
.src_loc = try f.srcLoc(f.location_tok),
.notes_len = unfiltered_errors,
});
var note_i: u32 = try eb.reserveNotes(unfiltered_errors);
for (self.errors) |item| {
if (item.excluded(filter)) continue;
switch (item) {
.unable_to_create_sym_link => |info| {
eb.extra.items[note_i] = @backingInt(try eb.addErrorMessage(.{
.msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{
info.file_name, info.link_name, @errorName(info.code),
}),
}));
},
.unable_to_create_file => |info| {
eb.extra.items[note_i] = @backingInt(try eb.addErrorMessage(.{
.msg = try eb.printString("unable to create file '{s}': {s}", .{
info.file_name, @errorName(info.code),
}),
}));
},
.unsupported_file_type => |info| {
eb.extra.items[note_i] = @backingInt(try eb.addErrorMessage(.{
.msg = try eb.printString("file '{s}' has unsupported type '{c}'", .{
info.file_name, info.file_type,
}),
}));
},
}
note_i += 1;
}
return error.FetchFailed;
}
test validate {
const gpa = std.testing.allocator;
var arena_instance = std.heap.ArenaAllocator.init(gpa);
defer arena_instance.deinit();
const arena = arena_instance.allocator();
var res: UnpackResult = .{};
try res.allocErrors(arena, 4, "unable to unpack");
try std.testing.expectEqual(0, res.errors_count);
res.unableToCreateFile("dir1/file1", error.File1);
res.unableToCreateSymLink("dir2/file2", "filename", error.SymlinkError);
res.unableToCreateFile("dir1/file3", error.File3);
res.unsupportedFileType("dir2/file4", 'x');
try std.testing.expectEqual(4, res.errors_count);
var filter: Filter = .{};
try filter.include_paths.put(arena, "dir2", {});
var fetch: Fetch = undefined;
fetch.parent_manifest_ast = null;
fetch.location_tok = 0;
try fetch.error_bundle.init(gpa);
defer fetch.error_bundle.deinit();
try std.testing.expectError(error.FetchFailed, res.validate(&fetch, filter));
var errors = try fetch.error_bundle.toOwnedBundle("");
defer errors.deinit(gpa);
var aw: Io.Writer.Allocating = .init(gpa);
defer aw.deinit();
try errors.renderToWriter(.{}, &aw.writer);
try std.testing.expectEqualStrings(
\\error: unable to unpack
\\ note: unable to create symlink from 'dir2/file2' to 'filename': SymlinkError
\\ note: file 'dir2/file4' has unsupported type 'x'
\\
, aw.written());
}
}