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);
}
}