1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use std;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use emu128::emu128;

/// Convert an emulated u128 to an Ipv6Addr.
///
/// TODO: It would be nice to implement From on Ipv6Addr for this.
///
/// # Examples
///
/// ```
/// use std::net::Ipv6Addr;
/// use std::str::FromStr;
/// use ipnet::ipv6_addr_from_double_u64;
/// assert_eq!(ipv6_addr_from_double_u64([0u64, 1u64]), Ipv6Addr::from_str("::1").unwrap());
/// ```
pub fn ipv6_addr_from_emu128(ip: emu128) -> Ipv6Addr {
    Ipv6Addr::new(
        (ip.hi >> 48) as u16, (ip.hi >> 32) as u16, (ip.hi >> 16) as u16, ip.hi as u16,
        (ip.lo >> 48) as u16, (ip.lo >> 32) as u16, (ip.lo >> 16) as u16, ip.lo as u16
    )
}

/// Convert an Ipv6Addr to an emulated u128.
///
/// TODO: It would be nice to implement From on Ipv6Addr for this.
///
/// # Examples
///
/// ```
/// use std::net::Ipv6Addr;
/// use std::str::FromStr;
/// use ipnet::ipv6_addr_into_double_u64;
/// assert_eq!(ipv6_addr_into_double_u64(Ipv6Addr::from_str("::1").unwrap()), [0u64, 1u64]);
/// ```
pub fn ipv6_addr_into_emu128(ip: Ipv6Addr) -> emu128 {
    let ip = ip.octets();
    emu128 {
        hi: ((ip[0] as u64) << 56) + ((ip[1] as u64) << 48) +
            ((ip[2] as u64) << 40) + ((ip[3] as u64) << 32) +
            ((ip[4] as u64) << 24) + ((ip[5] as u64) << 16) +
            ((ip[6] as u64) << 8) + (ip[7] as u64),
        lo: ((ip[8] as u64) << 56) + ((ip[9] as u64) << 48) +
            ((ip[10] as u64) << 40) + ((ip[11] as u64) << 32) +
            ((ip[12] as u64) << 24) + ((ip[13] as u64) << 16) +
            ((ip[14] as u64) << 8) + (ip[15] as u64),
    }
}

pub trait IpAdd<RHS = Self> {
    type Output;
    fn add(self, rhs: RHS) -> Self::Output;
}

pub trait IpSub<RHS = Self> {
    type Output;
    fn sub(self, rhs: RHS) -> Self::Output;
}

pub trait IpBitAnd<RHS = Self> {
    type Output;
    fn bitand(self, rhs: RHS) -> Self::Output;
}

pub trait IpBitOr<RHS = Self> {
    type Output;
    fn bitor(self, rhs: RHS) -> Self::Output;
}

macro_rules! ip_add_impl {
    ($(($t:ty, $f:ty),)*) => {
    $(
        impl IpAdd<$f> for $t {
            type Output = $t;
            #[inline]
            fn add(self, rhs: $f) -> $t {
                Self::from(u32::from(self).saturating_add(u32::from(rhs)))
            }
        }
    )*
    }
}

ip_add_impl! { (Ipv4Addr, Ipv4Addr), (Ipv4Addr, u32), }

macro_rules! ip_sub_impl {
    ($(($t:ty, $f:ty),)*) => {
    $(
        impl IpSub<$f> for $t {
            type Output = $t;
            #[inline]
            fn sub(self, rhs: $f) -> $t {
                Self::from(u32::from(self).saturating_sub(u32::from(rhs)))
            }
        }
    )*
    }
}

ip_sub_impl! { (Ipv4Addr, Ipv4Addr), (Ipv4Addr, u32), }

macro_rules! ip_bitand_impl {
    ($(($t:ty, $f:ty),)*) => {
    $(
        impl IpBitAnd<$f> for $t {
            type Output = $t;
            #[inline]
            fn bitand(self, rhs: $f) -> $t {
                Self::from(u32::from(self) & u32::from(rhs))
            }
        }
    )*
    }
}

ip_bitand_impl! { (Ipv4Addr, Ipv4Addr), (Ipv4Addr, u32), }

macro_rules! ip_bitor_impl {
    ($(($t:ty, $f:ty),)*) => {
    $(
        impl IpBitOr<$f> for $t {
            type Output = $t;
            #[inline]
            fn bitor(self, rhs: $f) -> $t {
                Self::from(u32::from(self) | u32::from(rhs))
            }
        }
    )*
    }
}

ip_bitor_impl! { (Ipv4Addr, Ipv4Addr), (Ipv4Addr, u32), }