@@ -15,16 +15,26 @@ pub use super::IpProtocol as Protocol;
1515/// [RFC 8200 § 5]: https://tools.ietf.org/html/rfc8200#section-5
1616pub const MIN_MTU : usize = 1280 ;
1717
18+ /// Size of IPv6 adderess in octets.
19+ ///
20+ /// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc4291#section-2
21+ pub const ADDR_SIZE : usize = 16 ;
22+
23+ /// Size of IPv4-mapping prefix in octets.
24+ ///
25+ /// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc4291#section-2
26+ pub const IPV4_MAPPED_PREFIX_SIZE : usize = ADDR_SIZE - 4 ; // 4 == ipv4::ADDR_SIZE , cannot DRY here because of dependency on a IPv4 module which is behind the feature
27+
1828/// A sixteen-octet IPv6 address.
1929#[ derive( Debug , Hash , PartialEq , Eq , PartialOrd , Ord , Clone , Copy , Default ) ]
2030#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
21- pub struct Address ( pub [ u8 ; 16 ] ) ;
31+ pub struct Address ( pub [ u8 ; ADDR_SIZE ] ) ;
2232
2333impl Address {
2434 /// The [unspecified address].
2535 ///
2636 /// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2
27- pub const UNSPECIFIED : Address = Address ( [ 0x00 ; 16 ] ) ;
37+ pub const UNSPECIFIED : Address = Address ( [ 0x00 ; ADDR_SIZE ] ) ;
2838
2939 /// The link-local [all nodes multicast address].
3040 ///
@@ -50,18 +60,24 @@ impl Address {
5060 0x01 ,
5161 ] ) ;
5262
63+ /// The prefix used in [IPv4-mapped addresses].
64+ ///
65+ /// [IPv4-mapped addresses]: https://www.rfc-editor.org/rfc/rfc4291#section-2.5.5.2
66+ pub const IPV4_MAPPED_PREFIX : [ u8 ; IPV4_MAPPED_PREFIX_SIZE ] =
67+ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xff , 0xff ] ;
68+
5369 /// Construct an IPv6 address from parts.
5470 #[ allow( clippy:: too_many_arguments) ]
5571 pub fn new ( a0 : u16 , a1 : u16 , a2 : u16 , a3 : u16 , a4 : u16 , a5 : u16 , a6 : u16 , a7 : u16 ) -> Address {
56- let mut addr = [ 0u8 ; 16 ] ;
57- NetworkEndian :: write_u16 ( & mut addr[ 0 ..2 ] , a0) ;
72+ let mut addr = [ 0u8 ; ADDR_SIZE ] ;
73+ NetworkEndian :: write_u16 ( & mut addr[ ..2 ] , a0) ;
5874 NetworkEndian :: write_u16 ( & mut addr[ 2 ..4 ] , a1) ;
5975 NetworkEndian :: write_u16 ( & mut addr[ 4 ..6 ] , a2) ;
6076 NetworkEndian :: write_u16 ( & mut addr[ 6 ..8 ] , a3) ;
6177 NetworkEndian :: write_u16 ( & mut addr[ 8 ..10 ] , a4) ;
6278 NetworkEndian :: write_u16 ( & mut addr[ 10 ..12 ] , a5) ;
6379 NetworkEndian :: write_u16 ( & mut addr[ 12 ..14 ] , a6) ;
64- NetworkEndian :: write_u16 ( & mut addr[ 14 ..16 ] , a7) ;
80+ NetworkEndian :: write_u16 ( & mut addr[ 14 ..] , a7) ;
6581 Address ( addr)
6682 }
6783
@@ -70,7 +86,7 @@ impl Address {
7086 /// # Panics
7187 /// The function panics if `data` is not sixteen octets long.
7288 pub fn from_bytes ( data : & [ u8 ] ) -> Address {
73- let mut bytes = [ 0 ; 16 ] ;
89+ let mut bytes = [ 0 ; ADDR_SIZE ] ;
7490 bytes. copy_from_slice ( data) ;
7591 Address ( bytes)
7692 }
@@ -81,7 +97,7 @@ impl Address {
8197 /// The function panics if `data` is not 8 words long.
8298 pub fn from_parts ( data : & [ u16 ] ) -> Address {
8399 assert ! ( data. len( ) >= 8 ) ;
84- let mut bytes = [ 0 ; 16 ] ;
100+ let mut bytes = [ 0 ; ADDR_SIZE ] ;
85101 for ( word_idx, chunk) in bytes. chunks_mut ( 2 ) . enumerate ( ) {
86102 NetworkEndian :: write_u16 ( chunk, data[ word_idx] ) ;
87103 }
@@ -122,7 +138,7 @@ impl Address {
122138 ///
123139 /// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2
124140 pub fn is_unspecified ( & self ) -> bool {
125- self . 0 == [ 0x00 ; 16 ]
141+ self . 0 == [ 0x00 ; ADDR_SIZE ]
126142 }
127143
128144 /// Query whether the IPv6 address is in the [link-local] scope.
@@ -143,15 +159,15 @@ impl Address {
143159 ///
144160 /// [IPv4 mapped IPv6 address]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
145161 pub fn is_ipv4_mapped ( & self ) -> bool {
146- self . 0 [ 0 .. 12 ] == [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xff , 0xff ]
162+ self . 0 [ .. IPV4_MAPPED_PREFIX_SIZE ] == Self :: IPV4_MAPPED_PREFIX
147163 }
148164
149165 #[ cfg( feature = "proto-ipv4" ) ]
150166 /// Convert an IPv4 mapped IPv6 address to an IPv4 address.
151167 pub fn as_ipv4 ( & self ) -> Option < ipv4:: Address > {
152168 if self . is_ipv4_mapped ( ) {
153- Some ( ipv4:: Address :: new (
154- self . 0 [ 12 ] , self . 0 [ 13 ] , self . 0 [ 14 ] , self . 0 [ 15 ] ,
169+ Some ( ipv4:: Address :: from_bytes (
170+ & self . 0 [ IPV4_MAPPED_PREFIX_SIZE .. ] ,
155171 ) )
156172 } else {
157173 None
@@ -162,14 +178,14 @@ impl Address {
162178 ///
163179 /// # Panics
164180 /// This function panics if `mask` is greater than 128.
165- pub ( super ) fn mask ( & self , mask : u8 ) -> [ u8 ; 16 ] {
181+ pub ( super ) fn mask ( & self , mask : u8 ) -> [ u8 ; ADDR_SIZE ] {
166182 assert ! ( mask <= 128 ) ;
167- let mut bytes = [ 0u8 ; 16 ] ;
183+ let mut bytes = [ 0u8 ; ADDR_SIZE ] ;
168184 let idx = ( mask as usize ) / 8 ;
169185 let modulus = ( mask as usize ) % 8 ;
170186 let ( first, second) = self . 0 . split_at ( idx) ;
171187 bytes[ 0 ..idx] . copy_from_slice ( first) ;
172- if idx < 16 {
188+ if idx < ADDR_SIZE {
173189 let part = second[ 0 ] ;
174190 bytes[ idx] = part & ( !( 0xff >> modulus) as u8 ) ;
175191 }
@@ -217,7 +233,10 @@ impl fmt::Display for Address {
217233 return write ! (
218234 f,
219235 "::ffff:{}.{}.{}.{}" ,
220- self . 0 [ 12 ] , self . 0 [ 13 ] , self . 0 [ 14 ] , self . 0 [ 15 ]
236+ self . 0 [ IPV4_MAPPED_PREFIX_SIZE + 0 ] ,
237+ self . 0 [ IPV4_MAPPED_PREFIX_SIZE + 1 ] ,
238+ self . 0 [ IPV4_MAPPED_PREFIX_SIZE + 2 ] ,
239+ self . 0 [ IPV4_MAPPED_PREFIX_SIZE + 3 ]
221240 ) ;
222241 }
223242
@@ -273,10 +292,10 @@ impl fmt::Display for Address {
273292/// Convert the given IPv4 address into a IPv4-mapped IPv6 address
274293impl From < ipv4:: Address > for Address {
275294 fn from ( address : ipv4:: Address ) -> Self {
276- let octets = address . 0 ;
277- Address ( [
278- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xff , 0xff , octets [ 0 ] , octets [ 1 ] , octets [ 2 ] , octets [ 3 ] ,
279- ] )
295+ let mut b = [ 0_u8 ; ADDR_SIZE ] ;
296+ b [ .. Self :: IPV4_MAPPED_PREFIX . len ( ) ] . copy_from_slice ( & Self :: IPV4_MAPPED_PREFIX ) ;
297+ b [ Self :: IPV4_MAPPED_PREFIX . len ( ) .. ] . copy_from_slice ( & address . 0 ) ;
298+ Self ( b )
280299 }
281300}
282301
0 commit comments