@@ -15,16 +15,26 @@ pub use super::IpProtocol as Protocol;
15
15
/// [RFC 8200 § 5]: https://tools.ietf.org/html/rfc8200#section-5
16
16
pub const MIN_MTU : usize = 1280 ;
17
17
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
+
18
28
/// A sixteen-octet IPv6 address.
19
29
#[ derive( Debug , Hash , PartialEq , Eq , PartialOrd , Ord , Clone , Copy , Default ) ]
20
30
#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
21
- pub struct Address ( pub [ u8 ; 16 ] ) ;
31
+ pub struct Address ( pub [ u8 ; ADDR_SIZE ] ) ;
22
32
23
33
impl Address {
24
34
/// The [unspecified address].
25
35
///
26
36
/// [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 ] ) ;
28
38
29
39
/// The link-local [all nodes multicast address].
30
40
///
@@ -50,18 +60,24 @@ impl Address {
50
60
0x01 ,
51
61
] ) ;
52
62
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
+
53
69
/// Construct an IPv6 address from parts.
54
70
#[ allow( clippy:: too_many_arguments) ]
55
71
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) ;
58
74
NetworkEndian :: write_u16 ( & mut addr[ 2 ..4 ] , a1) ;
59
75
NetworkEndian :: write_u16 ( & mut addr[ 4 ..6 ] , a2) ;
60
76
NetworkEndian :: write_u16 ( & mut addr[ 6 ..8 ] , a3) ;
61
77
NetworkEndian :: write_u16 ( & mut addr[ 8 ..10 ] , a4) ;
62
78
NetworkEndian :: write_u16 ( & mut addr[ 10 ..12 ] , a5) ;
63
79
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) ;
65
81
Address ( addr)
66
82
}
67
83
@@ -70,7 +86,7 @@ impl Address {
70
86
/// # Panics
71
87
/// The function panics if `data` is not sixteen octets long.
72
88
pub fn from_bytes ( data : & [ u8 ] ) -> Address {
73
- let mut bytes = [ 0 ; 16 ] ;
89
+ let mut bytes = [ 0 ; ADDR_SIZE ] ;
74
90
bytes. copy_from_slice ( data) ;
75
91
Address ( bytes)
76
92
}
@@ -81,7 +97,7 @@ impl Address {
81
97
/// The function panics if `data` is not 8 words long.
82
98
pub fn from_parts ( data : & [ u16 ] ) -> Address {
83
99
assert ! ( data. len( ) >= 8 ) ;
84
- let mut bytes = [ 0 ; 16 ] ;
100
+ let mut bytes = [ 0 ; ADDR_SIZE ] ;
85
101
for ( word_idx, chunk) in bytes. chunks_mut ( 2 ) . enumerate ( ) {
86
102
NetworkEndian :: write_u16 ( chunk, data[ word_idx] ) ;
87
103
}
@@ -122,7 +138,7 @@ impl Address {
122
138
///
123
139
/// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2
124
140
pub fn is_unspecified ( & self ) -> bool {
125
- self . 0 == [ 0x00 ; 16 ]
141
+ self . 0 == [ 0x00 ; ADDR_SIZE ]
126
142
}
127
143
128
144
/// Query whether the IPv6 address is in the [link-local] scope.
@@ -143,15 +159,15 @@ impl Address {
143
159
///
144
160
/// [IPv4 mapped IPv6 address]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
145
161
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
147
163
}
148
164
149
165
#[ cfg( feature = "proto-ipv4" ) ]
150
166
/// Convert an IPv4 mapped IPv6 address to an IPv4 address.
151
167
pub fn as_ipv4 ( & self ) -> Option < ipv4:: Address > {
152
168
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 .. ] ,
155
171
) )
156
172
} else {
157
173
None
@@ -162,14 +178,14 @@ impl Address {
162
178
///
163
179
/// # Panics
164
180
/// 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 ] {
166
182
assert ! ( mask <= 128 ) ;
167
- let mut bytes = [ 0u8 ; 16 ] ;
183
+ let mut bytes = [ 0u8 ; ADDR_SIZE ] ;
168
184
let idx = ( mask as usize ) / 8 ;
169
185
let modulus = ( mask as usize ) % 8 ;
170
186
let ( first, second) = self . 0 . split_at ( idx) ;
171
187
bytes[ 0 ..idx] . copy_from_slice ( first) ;
172
- if idx < 16 {
188
+ if idx < ADDR_SIZE {
173
189
let part = second[ 0 ] ;
174
190
bytes[ idx] = part & ( !( 0xff >> modulus) as u8 ) ;
175
191
}
@@ -217,7 +233,10 @@ impl fmt::Display for Address {
217
233
return write ! (
218
234
f,
219
235
"::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 ]
221
240
) ;
222
241
}
223
242
@@ -273,10 +292,10 @@ impl fmt::Display for Address {
273
292
/// Convert the given IPv4 address into a IPv4-mapped IPv6 address
274
293
impl From < ipv4:: Address > for Address {
275
294
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 )
280
299
}
281
300
}
282
301
0 commit comments