use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
enum SubnetMask {
Ipv4 = 24,
Ipv6 = 48,
}
pub struct ClientSubnetEncodingData {
pub client_subnet: u64,
pub subnet_mask: u64,
pub is_ipv6: u64,
}
pub fn parse_client_ip(client_ip: &str) -> ClientSubnetEncodingData {
if let Ok(addr) = client_ip.parse::<IpAddr>() {
if addr.is_ipv4() {
let ipv4_address: Ipv4Addr = client_ip.parse().unwrap();
ClientSubnetEncodingData {
client_subnet: (u32::from_be_bytes(ipv4_address.octets()) as u64 & 0xffffff00)
<< 32,
subnet_mask: SubnetMask::Ipv4 as u64,
is_ipv6: 0,
}
} else {
let ipv6_address: Ipv6Addr = client_ip.parse().unwrap();
ClientSubnetEncodingData {
client_subnet: ((u128::from_be_bytes(ipv6_address.octets()) >> 64)
& 0xffffffffffff0000) as u64,
subnet_mask: SubnetMask::Ipv6 as u64,
is_ipv6: 1,
}
}
} else {
ClientSubnetEncodingData {
client_subnet: 0,
subnet_mask: 0,
is_ipv6: 0,
}
}
}
#[cfg(test)]
mod tests {
use super::parse_client_ip;
#[test]
fn validate_parse_ipv4() {
let client_subnet_encoding_data = parse_client_ip("85.83.215.126");
assert_eq!(
6148494311290830848,
client_subnet_encoding_data.client_subnet
);
assert_eq!(24, client_subnet_encoding_data.subnet_mask);
assert_eq!(0, client_subnet_encoding_data.is_ipv6);
}
#[test]
fn validate_parse_ipv6() {
let client_subnet_encoding_data =
parse_client_ip("819e:5c2e:21e4:0094:4805:1635:f8e4:049b");
assert_eq!(
9340004030419828736,
client_subnet_encoding_data.client_subnet
);
assert_eq!(48, client_subnet_encoding_data.subnet_mask);
assert_eq!(1, client_subnet_encoding_data.is_ipv6);
}
#[test]
fn validate_parse_abbreviated_ipv6() {
let client_subnet_encoding_data = parse_client_ip("0319:7db1:f4d6::");
assert_eq!(
223347859801899008,
client_subnet_encoding_data.client_subnet
);
assert_eq!(48, client_subnet_encoding_data.subnet_mask);
assert_eq!(1, client_subnet_encoding_data.is_ipv6);
}
#[test]
fn validate_parse_invalid_client_ip() {
let client_subnet_encoding_data = parse_client_ip("1.2");
assert_eq!(0, client_subnet_encoding_data.client_subnet);
assert_eq!(0, client_subnet_encoding_data.subnet_mask);
assert_eq!(0, client_subnet_encoding_data.is_ipv6);
}
}