Skip to content

Commit 2542a90

Browse files
committed
Add IpAddress.to_prefix_len()
1 parent 3f68033 commit 2542a90

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

src/wire/ip.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,33 @@ impl Address {
184184
&Address::__Nonexhaustive => unreachable!()
185185
}
186186
}
187+
188+
/// Treat as subnet mask, get position of first 0
189+
pub fn to_prefix_len(&self) -> Option<u8> {
190+
let mut ones = true;
191+
let mut prefix_len = 0;
192+
for byte in self.as_bytes() {
193+
let mut mask = 0x80;
194+
for _ in 0..8 {
195+
let one = *byte & mask != 0;
196+
if ones {
197+
// Expect 1s until first 0
198+
if one {
199+
prefix_len += 1;
200+
} else {
201+
ones = false;
202+
}
203+
} else {
204+
if one {
205+
// 1 where 0 was expected
206+
return None;
207+
}
208+
}
209+
mask >>= 1;
210+
}
211+
}
212+
Some(prefix_len)
213+
}
187214
}
188215

189216
#[cfg(all(feature = "std", feature = "proto-ipv4", feature = "proto-ipv6"))]
@@ -1074,4 +1101,73 @@ pub(crate) mod test {
10741101
fn endpoint_unspecified() {
10751102
assert!(!Endpoint::UNSPECIFIED.is_specified());
10761103
}
1104+
1105+
#[test]
1106+
#[cfg(feature = "proto-ipv4")]
1107+
fn to_prefix_len_ipv4() {
1108+
fn test_eq<A: Into<Address>>(prefix_len: u8, mask: A) {
1109+
assert_eq!(
1110+
Some(prefix_len),
1111+
mask.into().to_prefix_len()
1112+
);
1113+
}
1114+
1115+
test_eq(0, Ipv4Address::new(0, 0, 0, 0));
1116+
test_eq(1, Ipv4Address::new(128, 0, 0, 0));
1117+
test_eq(2, Ipv4Address::new(192, 0, 0, 0));
1118+
test_eq(3, Ipv4Address::new(224, 0, 0, 0));
1119+
test_eq(4, Ipv4Address::new(240, 0, 0, 0));
1120+
test_eq(5, Ipv4Address::new(248, 0, 0, 0));
1121+
test_eq(6, Ipv4Address::new(252, 0, 0, 0));
1122+
test_eq(7, Ipv4Address::new(254, 0, 0, 0));
1123+
test_eq(8, Ipv4Address::new(255, 0, 0, 0));
1124+
test_eq(9, Ipv4Address::new(255, 128, 0, 0));
1125+
test_eq(10, Ipv4Address::new(255, 192, 0, 0));
1126+
test_eq(11, Ipv4Address::new(255, 224, 0, 0));
1127+
test_eq(12, Ipv4Address::new(255, 240, 0, 0));
1128+
test_eq(13, Ipv4Address::new(255, 248, 0, 0));
1129+
test_eq(14, Ipv4Address::new(255, 252, 0, 0));
1130+
test_eq(15, Ipv4Address::new(255, 254, 0, 0));
1131+
test_eq(16, Ipv4Address::new(255, 255, 0, 0));
1132+
test_eq(17, Ipv4Address::new(255, 255, 128, 0));
1133+
test_eq(18, Ipv4Address::new(255, 255, 192, 0));
1134+
test_eq(19, Ipv4Address::new(255, 255, 224, 0));
1135+
test_eq(20, Ipv4Address::new(255, 255, 240, 0));
1136+
test_eq(21, Ipv4Address::new(255, 255, 248, 0));
1137+
test_eq(22, Ipv4Address::new(255, 255, 252, 0));
1138+
test_eq(23, Ipv4Address::new(255, 255, 254, 0));
1139+
test_eq(24, Ipv4Address::new(255, 255, 255, 0));
1140+
test_eq(25, Ipv4Address::new(255, 255, 255, 128));
1141+
test_eq(26, Ipv4Address::new(255, 255, 255, 192));
1142+
test_eq(27, Ipv4Address::new(255, 255, 255, 224));
1143+
test_eq(28, Ipv4Address::new(255, 255, 255, 240));
1144+
test_eq(29, Ipv4Address::new(255, 255, 255, 248));
1145+
test_eq(30, Ipv4Address::new(255, 255, 255, 252));
1146+
test_eq(31, Ipv4Address::new(255, 255, 255, 254));
1147+
test_eq(32, Ipv4Address::new(255, 255, 255, 255));
1148+
}
1149+
1150+
#[cfg(feature = "proto-ipv4")]
1151+
fn to_prefix_len_ipv4_error() {
1152+
assert_eq!(None, IpAddress::from(Ipv4Address::new(255,255,255,1)).to_prefix_len());
1153+
}
1154+
1155+
#[test]
1156+
#[cfg(feature = "proto-ipv6")]
1157+
fn to_prefix_len_ipv6() {
1158+
fn test_eq<A: Into<Address>>(prefix_len: u8, mask: A) {
1159+
assert_eq!(
1160+
Some(prefix_len),
1161+
mask.into().to_prefix_len()
1162+
);
1163+
}
1164+
1165+
test_eq(0, Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 0));
1166+
test_eq(128, Ipv6Address::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff));
1167+
}
1168+
1169+
#[cfg(feature = "proto-ipv6")]
1170+
fn to_prefix_len_ipv6_error() {
1171+
assert_eq!(None, IpAddress::from(Ipv6Address::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 1)).to_prefix_len());
1172+
}
10771173
}

0 commit comments

Comments
 (0)