Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

ResolvConf

HostName.ResolvConf
pub const ResolvConf = struct

File

lib/std/Io/net/HostName.zig:396

Code

pub const ResolvConf = struct {
    attempts: u32,
    ndots: u32,
    timeout_seconds: u32,
    nameservers_buffer: [max_nameservers]IpAddress,
    nameservers_len: usize,
    search_buffer: [max_len]u8,
    search_len: usize,

    /// According to resolv.conf(5) there is a maximum of 3 nameservers in this
    /// file.
    pub const max_nameservers = 3;

    /// Returns `error.StreamTooLong` if a line is longer than 512 bytes.
    pub fn init(io: Io) !ResolvConf {
        var rc: ResolvConf = .{
            .nameservers_buffer = undefined,
            .nameservers_len = 0,
            .search_buffer = undefined,
            .search_len = 0,
            .ndots = 1,
            .timeout_seconds = 5,
            .attempts = 2,
        };

        const file = Io.Dir.openFileAbsolute(io, "/etc/resolv.conf", .{}) catch |err| switch (err) {
            error.FileNotFound,
            error.NotDir,
            error.AccessDenied,
            => {
                try addNumeric(&rc, io, "127.0.0.1", 53);
                return rc;
            },

            else => |e| return e,
        };
        defer file.close(io);

        var line_buf: [512]u8 = undefined;
        var file_reader = file.reader(io, &line_buf);
        parse(&rc, io, &file_reader.interface) catch |err| switch (err) {
            error.ReadFailed => return file_reader.err.?,
            else => |e| return e,
        };
        return rc;
    }

    const Directive = enum { options, nameserver, domain, search };
    const Option = enum { ndots, attempts, timeout };

    pub fn parse(rc: *ResolvConf, io: Io, reader: *Io.Reader) !void {
        while (reader.takeSentinel('\n')) |line_with_comment| {
            const line = line: {
                var split = std.mem.splitScalar(u8, line_with_comment, '#');
                break :line split.first();
            };
            var line_it = std.mem.tokenizeAny(u8, line, " \t");

            const token = line_it.next() orelse continue;
            switch (std.meta.stringToEnum(Directive, token) orelse continue) {
                .options => while (line_it.next()) |sub_tok| {
                    var colon_it = std.mem.splitScalar(u8, sub_tok, ':');
                    const name = colon_it.first();
                    const value_txt = colon_it.next() orelse continue;
                    const value = std.fmt.parseInt(u8, value_txt, 10) catch |err| switch (err) {
                        error.Overflow => 255,
                        error.InvalidCharacter => continue,
                    };
                    switch (std.meta.stringToEnum(Option, name) orelse continue) {
                        .ndots => rc.ndots = @min(value, 15),
                        .attempts => rc.attempts = @min(value, 10),
                        .timeout => rc.timeout_seconds = @min(value, 60),
                    }
                },
                .nameserver => {
                    const ip_txt = line_it.next() orelse continue;
                    try addNumeric(rc, io, ip_txt, 53);
                },
                .domain, .search => {
                    const rest = line_it.rest();
                    @memcpy(rc.search_buffer[0..rest.len], rest);
                    rc.search_len = rest.len;
                },
            }
        } else |err| switch (err) {
            error.EndOfStream => if (reader.bufferedLen() != 0) return error.EndOfStream,
            else => |e| return e,
        }

        if (rc.nameservers_len == 0) {
            try addNumeric(rc, io, "127.0.0.1", 53);
        }
    }

    fn addNumeric(rc: *ResolvConf, io: Io, name: []const u8, port: u16) !void {
        if (rc.nameservers_len < rc.nameservers_buffer.len) {
            rc.nameservers_buffer[rc.nameservers_len] = try .resolve(io, name, port);
            rc.nameservers_len += 1;
        }
    }

    pub fn nameservers(rc: *const ResolvConf) []const IpAddress {
        return rc.nameservers_buffer[0..rc.nameservers_len];
    }
}