39 lines
1.1 KiB
Text
39 lines
1.1 KiB
Text
use std::net::Ipv4Addr;
|
|
|
|
fn canonical_cidr(cidr: &str) -> Result<String, &str> {
|
|
let mut split = cidr.splitn(2, '/');
|
|
if let (Some(addr), Some(mask)) = (split.next(), split.next()) {
|
|
let addr = addr.parse::<Ipv4Addr>().map(u32::from).map_err(|_| cidr)?;
|
|
let mask = mask.parse::<u8>().map_err(|_| cidr)?;
|
|
let bitmask = 0xff_ff_ff_ffu32 << (32 - mask);
|
|
let addr = Ipv4Addr::from(addr & bitmask);
|
|
Ok(format!("{}/{}", addr, mask))
|
|
} else {
|
|
Err(cidr)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
|
|
#[test]
|
|
fn valid() {
|
|
[
|
|
("87.70.141.1/22", "87.70.140.0/22"),
|
|
("36.18.154.103/12", "36.16.0.0/12"),
|
|
("62.62.197.11/29", "62.62.197.8/29"),
|
|
("67.137.119.181/4", "64.0.0.0/4"),
|
|
("161.214.74.21/24", "161.214.74.0/24"),
|
|
("184.232.176.184/18", "184.232.128.0/18"),
|
|
]
|
|
.iter()
|
|
.cloned()
|
|
.for_each(|(input, expected)| {
|
|
assert_eq!(expected, super::canonical_cidr(input).unwrap());
|
|
});
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
println!("{}", canonical_cidr("127.1.2.3/24").unwrap());
|
|
}
|