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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! Types for IPv4 and IPv6 network addresses.

//! Extensions to IP address types for Add, Sub, BitAnd, and BitOr operations.
//!
//! # TODO:
//!
//! * Tests and documentation.

use std::net::{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 saturating_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 saturating_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), }

impl IpBitAnd<emu128> for Ipv6Addr {
    type Output = Ipv6Addr;
    #[inline]
    fn bitand(self, rhs: emu128) -> Ipv6Addr {
        ipv6_addr_from_emu128(ipv6_addr_into_emu128(self) & rhs)
    }
}

impl IpBitOr<emu128> for Ipv6Addr {
    type Output = Ipv6Addr;
    #[inline]
    fn bitor(self, rhs: emu128) -> Ipv6Addr {
        ipv6_addr_from_emu128(ipv6_addr_into_emu128(self) | rhs)
    }
}