use std::net::{
IpAddr,
Ipv4Addr,
Ipv6Addr,
};
use crate::num::NumberOfAddresses;
pub trait PrivUnspecAddress: Sized {
type _Tools;
}
pub trait PrivCidr {}
pub trait PrivInet {}
pub trait PrivInetPair {
fn _covered_addresses(&self) -> NumberOfAddresses;
fn _inc_first(&mut self) -> bool;
fn _dec_second(&mut self) -> bool;
}
#[derive(Clone, Copy)]
struct Ipv4OverflowingOp {
address: u32,
net_mask: u32,
host_mask: u32,
}
impl Ipv4OverflowingOp {
const fn new(address: Ipv4Addr, prefix_len: u8) -> Self {
let host_mask = Ipv4AddrTools::native_host_mask(prefix_len);
let net_mask = !host_mask;
let address: u32 = Ipv4AddrTools::to_native(address);
Self {
address,
net_mask,
host_mask,
}
}
const fn handle_result(self, (mut res, mut overflow): (u32, bool)) -> (Ipv4Addr, bool) {
let net_address = self.address & self.net_mask;
if res & self.net_mask != net_address {
res = (res & self.host_mask) | net_address;
overflow = true
}
(Ipv4AddrTools::from_native(res), overflow)
}
}
pub struct Ipv4AddrTools(());
impl Ipv4AddrTools {
pub(crate) const fn to_native(ip: Ipv4Addr) -> u32 {
u32::from_be_bytes(ip.octets())
}
pub(crate) const fn from_native(ip: u32) -> Ipv4Addr {
let ip = ip.to_be_bytes();
Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3])
}
pub(crate) const fn native_host_mask(prefix_len: u8) -> u32 {
if let Some(mask) = (!0u32).checked_shr(prefix_len as u32) {
mask
} else {
0
}
}
pub(crate) const fn _has_zero_host_part(address: Ipv4Addr, prefix_len: u8) -> bool {
let host_mask: u32 = Self::native_host_mask(prefix_len);
let addr_num = Self::to_native(address);
(addr_num & host_mask) == 0
}
pub(crate) const fn _overflowing_next(address: Ipv4Addr, prefix_len: u8) -> (Ipv4Addr, bool) {
let op = Ipv4OverflowingOp::new(address, prefix_len);
op.handle_result(op.address.overflowing_add(1))
}
pub(crate) const fn _overflowing_inc_u32(
address: Ipv4Addr,
prefix_len: u8,
step_u32: u32,
) -> (Ipv4Addr, bool) {
let op = Ipv4OverflowingOp::new(address, prefix_len);
let (res, overflow) = op.handle_result(op.address.overflowing_add(step_u32));
(res, overflow)
}
pub(crate) const fn _overflowing_inc(
address: Ipv4Addr,
prefix_len: u8,
step: u128,
) -> (Ipv4Addr, bool) {
let step_u32 = step as u32;
let step_overflow = step_u32 as u128 != step;
let (res, overflow) = Self::_overflowing_inc_u32(address, prefix_len, step_u32);
(res, overflow || step_overflow)
}
pub(crate) const fn _overflowing_prev(address: Ipv4Addr, prefix_len: u8) -> (Ipv4Addr, bool) {
let op = Ipv4OverflowingOp::new(address, prefix_len);
op.handle_result(op.address.overflowing_sub(1))
}
pub(crate) const fn _overflowing_dec_u32(
address: Ipv4Addr,
prefix_len: u8,
step_u32: u32,
) -> (Ipv4Addr, bool) {
let op = Ipv4OverflowingOp::new(address, prefix_len);
let (res, overflow) = op.handle_result(op.address.overflowing_sub(step_u32));
(res, overflow)
}
pub(crate) const fn _overflowing_dec(
address: Ipv4Addr,
prefix_len: u8,
step: u128,
) -> (Ipv4Addr, bool) {
let step_u32 = step as u32;
let step_overflow = step_u32 as u128 != step;
let (res, overflow) = Self::_overflowing_dec_u32(address, prefix_len, step_u32);
(res, overflow || step_overflow)
}
pub(crate) const fn _prefix_match(address: Ipv4Addr, other: Ipv4Addr, prefix_len: u8) -> bool {
let net_mask: u32 = !Self::native_host_mask(prefix_len);
(Self::to_native(address) & net_mask) == (Self::to_native(other) & net_mask)
}
pub(crate) const fn _network_address(address: Ipv4Addr, prefix_len: u8) -> Ipv4Addr {
let net_mask: u32 = !Self::native_host_mask(prefix_len);
Self::from_native(Self::to_native(address) & net_mask)
}
pub(crate) const fn _last_address(address: Ipv4Addr, prefix_len: u8) -> Ipv4Addr {
let host_mask: u32 = Self::native_host_mask(prefix_len);
Self::from_native(Self::to_native(address) | host_mask)
}
pub(crate) const fn _network_mask(prefix_len: u8) -> Ipv4Addr {
Self::from_native(!Self::native_host_mask(prefix_len))
}
}
impl PrivUnspecAddress for Ipv4Addr {
type _Tools = Ipv4AddrTools;
}
#[derive(Clone, Copy)]
struct Ipv6OverflowingOp {
address: u128,
net_mask: u128,
host_mask: u128,
}
impl Ipv6OverflowingOp {
const fn new(address: Ipv6Addr, prefix_len: u8) -> Self {
let host_mask = Ipv6AddrTools::native_host_mask(prefix_len);
let net_mask = !host_mask;
let address: u128 = u128::from_be_bytes(address.octets());
Self {
address,
net_mask,
host_mask,
}
}
const fn handle_result(self, (mut res, mut overflow): (u128, bool)) -> (Ipv6Addr, bool) {
let net_address = self.address & self.net_mask;
if res & self.net_mask != net_address {
res = (res & self.host_mask) | net_address;
overflow = true
}
(Ipv6AddrTools::from_native(res), overflow)
}
}
pub struct Ipv6AddrTools(());
impl Ipv6AddrTools {
pub(crate) const fn to_native(ip: Ipv6Addr) -> u128 {
u128::from_be_bytes(ip.octets())
}
pub(crate) const fn from_native(ip: u128) -> Ipv6Addr {
let ip = ip.to_be_bytes();
#[cfg(not(feature = "no_unsafe"))]
{
unsafe { std::mem::transmute(ip) }
}
#[cfg(feature = "no_unsafe")]
{
Ipv6Addr::new(
u16::from_be_bytes([ip[0], ip[1]]),
u16::from_be_bytes([ip[2], ip[3]]),
u16::from_be_bytes([ip[4], ip[5]]),
u16::from_be_bytes([ip[6], ip[7]]),
u16::from_be_bytes([ip[8], ip[9]]),
u16::from_be_bytes([ip[10], ip[11]]),
u16::from_be_bytes([ip[12], ip[13]]),
u16::from_be_bytes([ip[14], ip[15]]),
)
}
}
pub(crate) const fn native_host_mask(prefix_len: u8) -> u128 {
if let Some(mask) = (!0u128).checked_shr(prefix_len as u32) {
mask
} else {
0
}
}
pub(crate) const fn _has_zero_host_part(address: Ipv6Addr, prefix_len: u8) -> bool {
let host_mask: u128 = Self::native_host_mask(prefix_len);
let addr_num = Self::to_native(address);
(addr_num & host_mask) == 0
}
pub(crate) const fn _overflowing_next(address: Ipv6Addr, prefix_len: u8) -> (Ipv6Addr, bool) {
let op = Ipv6OverflowingOp::new(address, prefix_len);
op.handle_result(op.address.overflowing_add(1))
}
pub(crate) const fn _overflowing_inc(
address: Ipv6Addr,
prefix_len: u8,
step: u128,
) -> (Ipv6Addr, bool) {
let op = Ipv6OverflowingOp::new(address, prefix_len);
op.handle_result(op.address.overflowing_add(step))
}
pub(crate) const fn _overflowing_prev(address: Ipv6Addr, prefix_len: u8) -> (Ipv6Addr, bool) {
let op = Ipv6OverflowingOp::new(address, prefix_len);
op.handle_result(op.address.overflowing_sub(1))
}
pub(crate) const fn _overflowing_dec(
address: Ipv6Addr,
prefix_len: u8,
step: u128,
) -> (Ipv6Addr, bool) {
let op = Ipv6OverflowingOp::new(address, prefix_len);
op.handle_result(op.address.overflowing_sub(step))
}
pub(crate) const fn _prefix_match(address: Ipv6Addr, other: Ipv6Addr, prefix_len: u8) -> bool {
let net_mask: u128 = !Self::native_host_mask(prefix_len);
(Self::to_native(address) & net_mask) == (Self::to_native(other) & net_mask)
}
pub(crate) const fn _network_address(address: Ipv6Addr, prefix_len: u8) -> Ipv6Addr {
let net_mask: u128 = !Self::native_host_mask(prefix_len);
Self::from_native(Self::to_native(address) & net_mask)
}
pub(crate) const fn _last_address(address: Ipv6Addr, prefix_len: u8) -> Ipv6Addr {
let host_mask: u128 = Self::native_host_mask(prefix_len);
Self::from_native(Self::to_native(address) | host_mask)
}
pub(crate) const fn _network_mask(prefix_len: u8) -> Ipv6Addr {
Self::from_native(!Self::native_host_mask(prefix_len))
}
}
impl PrivUnspecAddress for Ipv6Addr {
type _Tools = Ipv6AddrTools;
}
pub struct IpAddrTools(());
impl IpAddrTools {
}
impl PrivUnspecAddress for IpAddr {
type _Tools = IpAddrTools;
}