Skip to content

Commit f7bbb57

Browse files
committed
Made IPv4 and IPv6 modules a bit DRYer by moving sizes into constants and exposed IPv4-mapping prefix.
1 parent 6b8b667 commit f7bbb57

File tree

2 files changed

+49
-25
lines changed

2 files changed

+49
-25
lines changed

src/wire/ipv4.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ pub use super::IpProtocol as Protocol;
2121
// accept a packet of the following size.
2222
pub const MIN_MTU: usize = 576;
2323

24+
/// Size of IPv4 adderess in octets.
25+
///
26+
/// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc791#section-3.2
27+
pub const ADDR_SIZE: usize = 4;
28+
2429
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
2530
pub struct Key {
2631
id: u16,
@@ -30,14 +35,14 @@ pub struct Key {
3035

3136
/// A four-octet IPv4 address.
3237
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
33-
pub struct Address(pub [u8; 4]);
38+
pub struct Address(pub [u8; ADDR_SIZE]);
3439

3540
impl Address {
3641
/// An unspecified address.
37-
pub const UNSPECIFIED: Address = Address([0x00; 4]);
42+
pub const UNSPECIFIED: Address = Address([0x00; ADDR_SIZE]);
3843

3944
/// The broadcast address.
40-
pub const BROADCAST: Address = Address([0xff; 4]);
45+
pub const BROADCAST: Address = Address([0xff; ADDR_SIZE]);
4146

4247
/// All multicast-capable nodes
4348
pub const MULTICAST_ALL_SYSTEMS: Address = Address([224, 0, 0, 1]);
@@ -55,7 +60,7 @@ impl Address {
5560
/// # Panics
5661
/// The function panics if `data` is not four octets long.
5762
pub fn from_bytes(data: &[u8]) -> Address {
58-
let mut bytes = [0; 4];
63+
let mut bytes = [0; ADDR_SIZE];
5964
bytes.copy_from_slice(data);
6065
Address(bytes)
6166
}
@@ -72,7 +77,7 @@ impl Address {
7277

7378
/// Query whether the address is the broadcast address.
7479
pub fn is_broadcast(&self) -> bool {
75-
self.0[0..4] == [255; 4]
80+
self.0[0..4] == [255; ADDR_SIZE]
7681
}
7782

7883
/// Query whether the address is a multicast address.
@@ -871,7 +876,7 @@ mod test {
871876
0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0xff,
872877
];
873878

874-
static REPR_PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
879+
static REPR_PAYLOAD_BYTES: [u8; ADDR_SIZE] = [0xaa, 0x00, 0x00, 0xff];
875880

876881
fn packet_repr() -> Repr {
877882
Repr {

src/wire/ipv6.rs

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,26 @@ pub use super::IpProtocol as Protocol;
1515
/// [RFC 8200 § 5]: https://tools.ietf.org/html/rfc8200#section-5
1616
pub 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

2333
impl 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
274293
impl 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

Comments
 (0)