structstd.tar.Diagnostics[src]

Provide this to receive detailed error messages. When this is provided, some errors which would otherwise be returned immediately will instead be added to this structure. The API user must check the errors in diagnostics to know whether the operation succeeded or failed.

Fields

allocator: std.mem.Allocator
errors: std.ArrayListUnmanaged(Error) = .empty
entries: usize = 0
root_dir: []const u8 = ""

Functions

Functiondeinit[src]

pub fn deinit(d: *Diagnostics) void

Parameters

Source Code

Source code
pub fn deinit(d: *Diagnostics) void {
    for (d.errors.items) |item| {
        switch (item) {
            .unable_to_create_sym_link => |info| {
                d.allocator.free(info.file_name);
                d.allocator.free(info.link_name);
            },
            .unable_to_create_file => |info| {
                d.allocator.free(info.file_name);
            },
            .unsupported_file_type => |info| {
                d.allocator.free(info.file_name);
            },
            .components_outside_stripped_prefix => |info| {
                d.allocator.free(info.file_name);
            },
        }
    }
    d.errors.deinit(d.allocator);
    d.allocator.free(d.root_dir);
    d.* = undefined;
}

Source Code

Source code
pub const Diagnostics = struct {
    allocator: std.mem.Allocator,
    errors: std.ArrayListUnmanaged(Error) = .empty,

    entries: usize = 0,
    root_dir: []const u8 = "",

    pub 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: Header.Kind,
        },
        components_outside_stripped_prefix: struct {
            file_name: []const u8,
        },
    };

    fn findRoot(d: *Diagnostics, path: []const u8) !void {
        if (path.len == 0) return;

        d.entries += 1;
        const root_dir = rootDir(path);
        if (d.entries == 1) {
            d.root_dir = try d.allocator.dupe(u8, root_dir);
            return;
        }
        if (d.root_dir.len == 0 or std.mem.eql(u8, root_dir, d.root_dir))
            return;
        d.allocator.free(d.root_dir);
        d.root_dir = "";
    }

    // Returns root dir of the path, assumes non empty path.
    fn rootDir(path: []const u8) []const u8 {
        const start_index: usize = if (path[0] == '/') 1 else 0;
        const end_index: usize = if (path[path.len - 1] == '/') path.len - 1 else path.len;
        const buf = path[start_index..end_index];
        if (std.mem.indexOfScalarPos(u8, buf, 0, '/')) |idx| {
            return buf[0..idx];
        }
        return buf;
    }

    test rootDir {
        const expectEqualStrings = testing.expectEqualStrings;
        try expectEqualStrings("a", rootDir("a"));
        try expectEqualStrings("b", rootDir("b"));
        try expectEqualStrings("c", rootDir("/c"));
        try expectEqualStrings("d", rootDir("/d/"));
        try expectEqualStrings("a", rootDir("a/b"));
        try expectEqualStrings("a", rootDir("a/b/c"));
    }

    pub fn deinit(d: *Diagnostics) void {
        for (d.errors.items) |item| {
            switch (item) {
                .unable_to_create_sym_link => |info| {
                    d.allocator.free(info.file_name);
                    d.allocator.free(info.link_name);
                },
                .unable_to_create_file => |info| {
                    d.allocator.free(info.file_name);
                },
                .unsupported_file_type => |info| {
                    d.allocator.free(info.file_name);
                },
                .components_outside_stripped_prefix => |info| {
                    d.allocator.free(info.file_name);
                },
            }
        }
        d.errors.deinit(d.allocator);
        d.allocator.free(d.root_dir);
        d.* = undefined;
    }
}