11use crate :: error:: IpNetworkError ;
22use crate :: parse:: { cidr_parts, parse_prefix} ;
3- use std:: { cmp , convert:: TryFrom , fmt, net:: Ipv6Addr , str:: FromStr } ;
3+ use std:: { convert:: TryFrom , fmt, net:: Ipv6Addr , str:: FromStr } ;
44
55const IPV6_BITS : u8 = 128 ;
66const IPV6_SEGMENT_BITS : u8 = 16 ;
@@ -87,6 +87,23 @@ impl Ipv6Network {
8787
8888 /// Constructs without checking prefix a new `Ipv6Network` from any `Ipv6Addr,
8989 /// and a prefix denoting the network size.
90+ ///
91+ /// # Safety
92+ ///
93+ /// The caller must ensure that the prefix is less than or equal to 32.
94+ ///
95+ /// # Examples
96+ ///
97+ /// ```
98+ /// use std::net::Ipv6Addr;
99+ /// use ipnetwork::Ipv6Network;
100+ ///
101+ /// let prefix = 64;
102+ /// let addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0);
103+ ///
104+ /// debug_assert!(prefix <= 128);
105+ /// let net = unsafe { Ipv6Network::new_unchecked(addr, prefix) };
106+ /// ```
90107 pub const unsafe fn new_unchecked ( addr : Ipv6Addr , prefix : u8 ) -> Ipv6Network {
91108 Ipv6Network { addr, prefix }
92109 }
@@ -106,6 +123,10 @@ impl Ipv6Network {
106123 /// Returns an iterator over `Ipv6Network`. Each call to `next` will return the next
107124 /// `Ipv6Addr` in the given network. `None` will be returned when there are no more
108125 /// addresses.
126+ ///
127+ /// # Warning
128+ ///
129+ /// This can return up to 2^128 addresses, which will take a _long_ time to iterate over.
109130 pub fn iter ( & self ) -> Ipv6NetworkIterator {
110131 let dec = u128:: from ( self . addr ) ;
111132 let max = u128:: max_value ( ) ;
@@ -123,42 +144,6 @@ impl Ipv6Network {
123144 }
124145 }
125146
126- /// Returns the address of the network denoted by this `Ipv6Network`.
127- /// This means the lowest possible IPv6 address inside of the network.
128- ///
129- /// # Examples
130- ///
131- /// ```
132- /// use std::net::Ipv6Addr;
133- /// use ipnetwork::Ipv6Network;
134- ///
135- /// let net: Ipv6Network = "2001:db8::/96".parse().unwrap();
136- /// assert_eq!(net.network(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0));
137- /// ```
138- pub fn network ( & self ) -> Ipv6Addr {
139- let mask = u128:: from ( self . mask ( ) ) ;
140- let ip = u128:: from ( self . addr ) & mask;
141- Ipv6Addr :: from ( ip)
142- }
143-
144- /// Returns the broadcast address of this `Ipv6Network`.
145- /// This means the highest possible IPv4 address inside of the network.
146- ///
147- /// # Examples
148- ///
149- /// ```
150- /// use std::net::Ipv6Addr;
151- /// use ipnetwork::Ipv6Network;
152- ///
153- /// let net: Ipv6Network = "2001:db8::/96".parse().unwrap();
154- /// assert_eq!(net.broadcast(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xffff, 0xffff));
155- /// ```
156- pub fn broadcast ( & self ) -> Ipv6Addr {
157- let mask = u128:: from ( self . mask ( ) ) ;
158- let broadcast = u128:: from ( self . addr ) | !mask;
159- Ipv6Addr :: from ( broadcast)
160- }
161-
162147 pub fn ip ( & self ) -> Ipv6Addr {
163148 self . addr
164149 }
@@ -180,8 +165,9 @@ impl Ipv6Network {
180165 /// Checks if the given `Ipv6Network` is partly contained in other.
181166 pub fn overlaps ( self , other : Ipv6Network ) -> bool {
182167 other. contains ( self . ip ( ) )
183- || ( other. contains ( self . broadcast ( ) )
184- || ( self . contains ( other. ip ( ) ) || ( self . contains ( other. broadcast ( ) ) ) ) )
168+ || other. contains ( self . broadcast ( ) )
169+ || self . contains ( other. ip ( ) )
170+ || self . contains ( other. broadcast ( ) )
185171 }
186172
187173 /// Returns the mask for this `Ipv6Network`.
@@ -199,17 +185,47 @@ impl Ipv6Network {
199185 /// assert_eq!(net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
200186 /// ```
201187 pub fn mask ( & self ) -> Ipv6Addr {
202- let mut segments = [ 0 ; 16 ] ;
203- for ( i, chunk) in segments. chunks_mut ( 2 ) . enumerate ( ) {
204- let bits_remaining = self . prefix . saturating_sub ( i as u8 * 16 ) ;
205- let set_bits = cmp:: min ( bits_remaining, 16 ) ;
206- let mask = !( 0xffff >> set_bits) as u16 ;
207- chunk[ 0 ] = ( mask >> 8 ) as u8 ;
208- chunk[ 1 ] = mask as u8 ;
209- }
210- Ipv6Addr :: from ( segments)
188+ debug_assert ! ( self . prefix <= IPV6_BITS ) ;
189+
190+ let mask = u128:: MAX << ( IPV6_BITS - self . prefix ) ;
191+ Ipv6Addr :: from ( mask)
192+ }
193+
194+ /// Returns the address of the network denoted by this `Ipv6Network`.
195+ /// This means the lowest possible IPv6 address inside of the network.
196+ ///
197+ /// # Examples
198+ ///
199+ /// ```
200+ /// use std::net::Ipv6Addr;
201+ /// use ipnetwork::Ipv6Network;
202+ ///
203+ /// let net: Ipv6Network = "2001:db8::/96".parse().unwrap();
204+ /// assert_eq!(net.network(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0));
205+ /// ```
206+ pub fn network ( & self ) -> Ipv6Addr {
207+ let mask = u128:: from ( self . mask ( ) ) ;
208+ let network = u128:: from ( self . addr ) & mask;
209+ Ipv6Addr :: from ( network)
210+ }
211+
212+ /// Returns the broadcast address of this `Ipv6Network`.
213+ /// This means the highest possible IPv4 address inside of the network.
214+ ///
215+ /// # Examples
216+ ///
217+ /// ```
218+ /// use std::net::Ipv6Addr;
219+ /// use ipnetwork::Ipv6Network;
220+ ///
221+ /// let net: Ipv6Network = "2001:db8::/96".parse().unwrap();
222+ /// assert_eq!(net.broadcast(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xffff, 0xffff));
223+ /// ```
224+ pub fn broadcast ( & self ) -> Ipv6Addr {
225+ let mask = u128:: from ( self . mask ( ) ) ;
226+ let broadcast = u128:: from ( self . addr ) | !mask;
227+ Ipv6Addr :: from ( broadcast)
211228 }
212-
213229
214230 /// Checks if a given `Ipv6Addr` is in this `Ipv6Network`
215231 ///
@@ -225,14 +241,10 @@ impl Ipv6Network {
225241 /// ```
226242 #[ inline]
227243 pub fn contains ( & self , ip : Ipv6Addr ) -> bool {
228- let a = self . addr . segments ( ) ;
229- let b = ip. segments ( ) ;
230- let addrs = Iterator :: zip ( a. iter ( ) , b. iter ( ) ) ;
231- self . mask ( )
232- . segments ( )
233- . iter ( )
234- . zip ( addrs)
235- . all ( |( mask, ( a, b) ) | a & mask == b & mask)
244+ let ip = u128:: from ( ip) ;
245+ let net = u128:: from ( self . network ( ) ) ;
246+ let mask = u128:: from ( self . mask ( ) ) ;
247+ ( ip & mask) == net
236248 }
237249
238250 /// Returns number of possible host addresses in this `Ipv6Network`.
@@ -250,12 +262,12 @@ impl Ipv6Network {
250262 /// assert_eq!(tinynet.size(), 1);
251263 /// ```
252264 pub fn size ( & self ) -> u128 {
253- let host_bits = u32 :: from ( IPV6_BITS - self . prefix ) ;
254- 2u128 . pow ( host_bits )
265+ debug_assert ! ( self . prefix <= IPV6_BITS ) ;
266+ 1 << ( IPV6_BITS - self . prefix )
255267 }
256268
257269 /// Returns the `n`:th address within this network.
258- /// The adresses are indexed from 0 and `n` must be smaller than the size of the network.
270+ /// The addresses are indexed from 0 and `n` must be smaller than the size of the network.
259271 ///
260272 /// # Examples
261273 ///
@@ -296,14 +308,12 @@ impl FromStr for Ipv6Network {
296308 type Err = IpNetworkError ;
297309 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
298310 let ( addr_str, prefix_str) = cidr_parts ( s) ?;
299- let addr = Ipv6Addr :: from_str ( addr_str) . map_err ( |e| IpNetworkError :: InvalidAddr ( e . to_string ( ) ) ) ?;
311+ let addr = Ipv6Addr :: from_str ( addr_str) ?;
300312 let prefix = parse_prefix ( prefix_str. unwrap_or ( & IPV6_BITS . to_string ( ) ) , IPV6_BITS ) ?;
301313 Ipv6Network :: new ( addr, prefix)
302314 }
303315}
304316
305-
306-
307317impl TryFrom < & str > for Ipv6Network {
308318 type Error = IpNetworkError ;
309319
@@ -694,7 +704,7 @@ mod test {
694704 let other: Ipv6Network = "2001:DB8:ACAD::1/64" . parse ( ) . unwrap ( ) ;
695705 let other2: Ipv6Network = "2001:DB8:ACAD::20:2/64" . parse ( ) . unwrap ( ) ;
696706
697- assert_eq ! ( other2. overlaps( other) , true ) ;
707+ assert ! ( other2. overlaps( other) ) ;
698708 }
699709
700710 #[ test]
@@ -726,9 +736,6 @@ mod test {
726736 net. nth( 65538 ) . unwrap( ) ,
727737 Ipv6Addr :: from_str( "ff01::1:2" ) . unwrap( )
728738 ) ;
729- assert_eq ! (
730- net. nth( net. size( ) ) ,
731- None
732- ) ;
739+ assert_eq ! ( net. nth( net. size( ) ) , None ) ;
733740 }
734741}
0 commit comments