Validates a hostname according to RFC 1123
pub fn validate(bytes: []const u8) ValidateError!void
pub fn validate(bytes: []const u8) ValidateError!void {
if (bytes.len == 0) return error.InvalidHostName;
// The accepted maximum length of a hostname, including labels and dots.
if (bytes.len > max_len) return error.NameTooLong;
// Ignore trailing dot (FQDN).
const end = if (bytes[bytes.len - 1] == '.') bytes.len - 1 else bytes.len;
// Hostnames are divided into dot-separated "labels", which:
//
// - Start with a letter or digit
// - Can contain letters, digits, or hyphens
// - Must end with a letter or digit
// - Have a minimum of 1 character and a maximum of 63
var label_len: usize = 0;
for (bytes[0..end], 0..) |c, i| {
switch (c) {
'.' => {
if (label_len == 0 or label_len > 63) return error.InvalidHostName;
if (!std.ascii.isAlphanumeric(bytes[i - 1])) return error.InvalidHostName;
label_len = 0;
},
'-' => {
if (label_len == 0) return error.InvalidHostName;
label_len += 1;
},
else => {
if (!std.ascii.isAlphanumeric(c)) return error.InvalidHostName;
label_len += 1;
},
}
}
// Validate the final label
if (label_len == 0 or label_len > 63) return error.InvalidHostName;
if (!std.ascii.isAlphanumeric(bytes[end - 1])) return error.InvalidHostName;
}