use std::net::{IpAddr, ToSocketAddrs};
pub fn hostname_to_ip_addr(host: &str) -> Option<String> {
let sock_addr = format!("{}:0", host).to_socket_addrs();
match sock_addr {
Ok(mut addrs) => {
while let Some(addr) = addrs.next() {
match addr.ip() {
IpAddr::V4(ipv4) => return Some(ipv4.to_string()),
IpAddr::V6(ipv6) => return Some(ipv6.to_string()),
}
}
None
}
Err(_) => None,
}
}
pub fn is_ipv4(s: &str) -> bool {
let parts: Vec<&str> = s.split('.').collect();
if parts.len() != 4 {
return false;
}
for part in parts {
match part.parse::<u8>() {
Ok(_) => continue,
Err(_) => return false,
}
}
true
}
pub fn is_ipv6(s: &str) -> bool {
s.contains(':')
}
pub fn is_link(link: &str) -> bool {
link.starts_with("http://")
|| link.starts_with("https://")
|| link.starts_with("data:")
|| link.starts_with("content://")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_ipv4_valid() {
assert!(is_ipv4("192.168.1.1"));
assert!(is_ipv4("127.0.0.1"));
assert!(is_ipv4("8.8.8.8"));
assert!(is_ipv4("255.255.255.255"));
}
#[test]
fn test_is_ipv4_invalid() {
assert!(!is_ipv4("192.168.1"));
assert!(!is_ipv4("192.168.1.256"));
assert!(!is_ipv4("192.168.1.a"));
assert!(!is_ipv4("192.168.1.1.1"));
assert!(!is_ipv4("2001:0db8:85a3:0000:0000:8a2e:0370:7334"));
}
#[test]
fn test_is_ipv6_valid() {
assert!(is_ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334"));
assert!(is_ipv6("::1"));
assert!(is_ipv6("2001:db8::"));
}
#[test]
fn test_is_ipv6_invalid() {
assert!(!is_ipv6("192.168.1.1"));
assert!(!is_ipv6("not an ip"));
}
#[test]
fn test_hostname_to_ip_addr() {
let ip = hostname_to_ip_addr("localhost");
assert!(ip.is_some());
assert!(ip.as_ref().unwrap() == "127.0.0.1" || ip.as_ref().unwrap() == "::1");
}
}