Created
January 12, 2012 02:30
-
-
Save z0w0/1598193 to your computer and use it in GitHub Desktop.
Extended IP address parsing for net.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Module: net | |
*/ | |
import core::{vec, uint, str}; | |
/* Section: Types */ | |
/* | |
Tag: ip_addr | |
An IP address | |
*/ | |
tag ip_addr { | |
/* | |
Variant: ipv4 | |
An IPv4 address | |
*/ | |
ipv4(u8, u8, u8, u8); | |
/* | |
Variant: ipv6 | |
An IPv6 address | |
*/ | |
ipv6(u16, u16, u16, u16, u16, u16, u16, u16); | |
} | |
/* Section: Operations */ | |
/* | |
Function: format_addr | |
Convert an <ip_addr> to a str | |
*/ | |
fn format_addr(ip: ip_addr) -> str { | |
alt ip { | |
ipv4(a, b, c, d) { | |
#fmt["%u.%u.%u.%u", a as uint, b as uint, c as uint, d as uint] | |
} | |
ipv6(a, b, c, d, e, f, g, h) { | |
#fmt["%s:%s:%s:%s:%s:%s:%s:%s", | |
core::uint::to_str(a as uint, 16u), | |
core::uint::to_str(b as uint, 16u), | |
core::uint::to_str(c as uint, 16u), | |
core::uint::to_str(d as uint, 16u), | |
core::uint::to_str(e as uint, 16u), | |
core::uint::to_str(f as uint, 16u), | |
core::uint::to_str(g as uint, 16u), | |
core::uint::to_str(h as uint, 16u) | |
] | |
} | |
_ { fail "Unsupported address type"; } | |
} | |
} | |
/* | |
Function: parse_addr | |
Convert a str to <ip_addr> | |
Converts a string of the format "x.x.x.x" or "x:x:x:x:x:x:x:x" into an ip_addr tag. | |
Failure: | |
String must be a valid IPv4 or IPv6 address | |
*/ | |
fn parse_addr(ip: str) -> ip_addr { | |
if str::is_empty(ip) { fail "Invalid IP address"; } | |
if str::index(ip, ":"[0]) != -1 { | |
let parts_str = str::split(ip, ":"[0]); | |
let parts = vec::to_mut([0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u]); | |
let i = 0u; | |
let found_sub = false; | |
let parts_str_len = vec::len(parts_str); | |
if parts_str_len > 8u { fail "Too many colons in IP address"; } | |
for part in parts_str { | |
if str::char_len(part) > 4u { fail "Invalid IP address part"; } | |
if str::is_empty(part) { | |
if !found_sub { | |
found_sub = true; | |
let j = 0u; | |
let amount = 8u - parts_str_len + 1u; | |
if i < parts_str_len - 1u && str::is_empty(parts_str[i + 1u]) { amount += 1u; } | |
while j < amount { | |
parts[i + j] = 0u; | |
j += 1u; | |
} | |
i = i + amount; | |
} | |
cont; | |
} | |
else { parts[i] = uint::parse_buf(str::bytes(part), 16u);} | |
if parts[i] > 65535u { fail "Invalid IP address part"; } | |
i += 1u; | |
} | |
ret ipv6( | |
parts[0] as u16, | |
parts[1] as u16, | |
parts[2] as u16, | |
parts[3] as u16, | |
parts[4] as u16, | |
parts[5] as u16, | |
parts[6] as u16, | |
parts[7] as u16 | |
); | |
} | |
let parts = vec::map(str::split(ip, "."[0]), {|s| uint::from_str(s) }); | |
if vec::len(parts) != 4u { fail "Too many dots in IP address"; } | |
for i in parts { if i > 255u { fail "Invalid IP address part"; } } | |
ipv4(parts[0] as u8, parts[1] as u8, parts[2] as u8, parts[3] as u8) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment