Skip to content

Instantly share code, notes, and snippets.

@z0w0
Created Jan 12, 2012
Embed
What would you like to do?
Extended IP address parsing for net.rs
/*
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