use ipaddress::IPAddress;
use core::result::Result;
use num::bigint::BigUint;
use core::str::FromStr;
use num_traits::One;
use num_traits::Num;
use core::ops::Rem;
use core::ops::Shl;
use core::ops::Shr;
use num_traits::Zero;
use num_traits::FromPrimitive;
use num_traits::ToPrimitive;
use prefix128;
use ipv4;
pub fn from_str<S: Into<String>>(_str: S, radix: u32, prefix: usize) -> Result<IPAddress, String> {
let str = _str.into();
let num = BigUint::from_str_radix(&str.clone(), radix);
if num.is_err() {
return Err(format!("unparsable {}", str));
}
return from_int(num.unwrap(), prefix);
}
pub fn enhance_if_mapped(mut ip: IPAddress) -> Result<IPAddress, String> {
if ip.is_mapped() {
return Ok(ip);
}
let ipv6_top_96bit = ip.host_address.clone().shr(32);
if ipv6_top_96bit == BigUint::from_u32(0xffff).unwrap() {
let num: BigUint = ip.host_address.clone().rem(BigUint::one().shl(32));
if num == BigUint::zero() {
return Ok(ip);
}
println!("ip:{},{:x}", ip.to_string(), num);
let ipv4_bits = ::ip_bits::v4();
if ipv4_bits.bits < ip.prefix.host_prefix() {
println!("enhance_if_mapped-2:{}:{}", ip.to_string(), ip.prefix.host_prefix());
return Err(format!("enhance_if_mapped prefix not ipv4 compatible {}", ip.prefix.host_prefix()));
}
let mapped = ipv4::from_u32(num.to_u32().unwrap(), ipv4_bits.bits-ip.prefix.host_prefix());
if mapped.is_err() {
println!("enhance_if_mapped-3");
return mapped;
}
ip.mapped = Some(Box::new(mapped.unwrap()));
}
return Ok(ip);
}
pub fn from_int(adr: BigUint, prefix: usize) -> Result<IPAddress, String> {
let prefix = prefix128::new(prefix);
if prefix.is_err() {
return Err(prefix.unwrap_err());
}
return enhance_if_mapped(IPAddress {
ip_bits: ::ip_bits::v6(),
host_address: adr.clone(),
prefix: prefix.unwrap(),
mapped: None,
vt_is_private: ipv6_is_private,
vt_is_loopback: ipv6_is_loopback,
vt_to_ipv6: to_ipv6,
});
}
pub fn new<S: Into<String>>(_str: S) -> Result<IPAddress, String> {
let str = _str.into();
let (ip, o_netmask) = IPAddress::split_at_slash(&str);
if IPAddress::is_valid_ipv6(ip.clone()) {
let o_num = IPAddress::split_to_num(&ip);
if o_num.is_err() {
return Err(o_num.unwrap_err());
}
let mut netmask = 128;
if o_netmask.is_some() {
let network = o_netmask.unwrap();
let num_mask = u8::from_str(&network);
if num_mask.is_err() {
return Err(format!("Invalid Netmask {}", str));
}
netmask = network.parse::<usize>().unwrap();
}
let prefix = ::prefix128::new(netmask);
if prefix.is_err() {
return Err(prefix.unwrap_err());
}
return enhance_if_mapped(IPAddress {
ip_bits: ::ip_bits::v6(),
host_address: o_num.unwrap(),
prefix: prefix.unwrap(),
mapped: None,
vt_is_private: ipv6_is_private,
vt_is_loopback: ipv6_is_loopback,
vt_to_ipv6: to_ipv6
});
} else {
return Err(format!("Invalid IP {}", str));
}
}
pub fn to_ipv6(ia: &IPAddress) -> IPAddress {
return ia.clone();
}
pub fn ipv6_is_loopback(my: &IPAddress) -> bool {
return my.host_address == BigUint::one();
}
pub fn ipv6_is_private(my: &IPAddress) -> bool {
return IPAddress::parse("fd00::/8").unwrap().includes(my);
}