Function parse [src]

Parse a given IPv6 address string into an Address. Assumes the Scope ID of the address is fully numeric. For non-numeric addresses, see resolveIp6.

Prototype

pub fn parse(buf: []const u8, port: u16) IPv6ParseError!Ip6Address

Parameters

buf: []const u8port: u16

Possible Errors

Incomplete IPParseError
InvalidCharacter IPParseError
InvalidEnd IPParseError
InvalidIpv4Mapping
Overflow IPParseError

Source

pub fn parse(buf: []const u8, port: u16) IPv6ParseError!Ip6Address { var result = Ip6Address{ .sa = posix.sockaddr.in6{ .scope_id = 0, .port = mem.nativeToBig(u16, port), .flowinfo = 0, .addr = undefined, }, }; var ip_slice: *[16]u8 = result.sa.addr[0..]; var tail: [16]u8 = undefined; var x: u16 = 0; var saw_any_digits = false; var index: u8 = 0; var scope_id = false; var abbrv = false; for (buf, 0..) |c, i| { if (scope_id) { if (c >= '0' and c <= '9') { const digit = c - '0'; { const ov = @mulWithOverflow(result.sa.scope_id, 10); if (ov[1] != 0) return error.Overflow; result.sa.scope_id = ov[0]; } { const ov = @addWithOverflow(result.sa.scope_id, digit); if (ov[1] != 0) return error.Overflow; result.sa.scope_id = ov[0]; } } else { return error.InvalidCharacter; } } else if (c == ':') { if (!saw_any_digits) { if (abbrv) return error.InvalidCharacter; // ':::' if (i != 0) abbrv = true; @memset(ip_slice[index..], 0); ip_slice = tail[0..]; index = 0; continue; } if (index == 14) { return error.InvalidEnd; } ip_slice[index] = @as(u8, @truncate(x >> 8)); index += 1; ip_slice[index] = @as(u8, @truncate(x)); index += 1; x = 0; saw_any_digits = false; } else if (c == '%') { if (!saw_any_digits) { return error.InvalidCharacter; } scope_id = true; saw_any_digits = false; } else if (c == '.') { if (!abbrv or ip_slice[0] != 0xff or ip_slice[1] != 0xff) { // must start with '::ffff:' return error.InvalidIpv4Mapping; } const start_index = mem.lastIndexOfScalar(u8, buf[0..i], ':').? + 1; const addr = (Ip4Address.parse(buf[start_index..], 0) catch { return error.InvalidIpv4Mapping; }).sa.addr; ip_slice = result.sa.addr[0..]; ip_slice[10] = 0xff; ip_slice[11] = 0xff; const ptr = mem.sliceAsBytes(@as(*const [1]u32, &addr)[0..]); ip_slice[12] = ptr[0]; ip_slice[13] = ptr[1]; ip_slice[14] = ptr[2]; ip_slice[15] = ptr[3]; return result; } else { const digit = try std.fmt.charToDigit(c, 16); { const ov = @mulWithOverflow(x, 16); if (ov[1] != 0) return error.Overflow; x = ov[0]; } { const ov = @addWithOverflow(x, digit); if (ov[1] != 0) return error.Overflow; x = ov[0]; } saw_any_digits = true; } } if (!saw_any_digits and !abbrv) { return error.Incomplete; } if (!abbrv and index < 14) { return error.Incomplete; } if (index == 14) { ip_slice[14] = @as(u8, @truncate(x >> 8)); ip_slice[15] = @as(u8, @truncate(x)); return result; } else { ip_slice[index] = @as(u8, @truncate(x >> 8)); index += 1; ip_slice[index] = @as(u8, @truncate(x)); index += 1; @memcpy(result.sa.addr[16 - index ..][0..index], ip_slice[0..index]); return result; } }