cidr/parsers/
ipv4_short.rs1use core::str::FromStr;
2use std::net::{
3 IpAddr,
4 Ipv4Addr,
5};
6
7use crate::{
8 errors::NetworkParseError,
9 AnyIpCidr,
10 IpCidr,
11 Ipv4Cidr,
12};
13
14fn _parse_short_ipv4_address_as_cidr(s: &str) -> Option<Ipv4Cidr> {
17 let mut octets = [0u8; 4];
18 let mut last = 0;
19 for (ndx, os) in s.split('.').enumerate() {
20 if ndx >= 4 {
21 return None;
23 }
24 octets[ndx] = os.parse().ok()?;
26 last = ndx;
27 }
28 let bits = (last as u8 + 1) * 8;
29 Some(Ipv4Cidr::new(Ipv4Addr::from(octets), bits).expect("host bits are zero"))
30}
31
32pub fn parse_short_ipv4_address_as_cidr(s: &str) -> Result<Ipv4Cidr, NetworkParseError> {
48 match _parse_short_ipv4_address_as_cidr(s) {
49 Some(n) => Ok(n),
50 None => {
51 Ok(Ipv4Cidr::new_host(s.parse()?))
54 },
55 }
56}
57
58pub fn parse_short_ipv4_cidr(s: &str) -> Result<Ipv4Cidr, NetworkParseError> {
60 super::parse_cidr_full(s, FromStr::from_str, parse_short_ipv4_address_as_cidr)
61}
62
63pub fn parse_short_ip_address_as_cidr(s: &str) -> Result<IpCidr, NetworkParseError> {
68 match s.parse::<IpAddr>() {
69 Ok(a) => Ok(IpCidr::new_host(a)),
70 Err(e) => match _parse_short_ipv4_address_as_cidr(s) {
72 Some(n) => Ok(n.into()),
73 None => Err(e.into()),
74 },
75 }
76}
77
78pub fn parse_short_ip_cidr(s: &str) -> Result<IpCidr, NetworkParseError> {
80 super::parse_cidr_full(s, FromStr::from_str, parse_short_ip_address_as_cidr)
81}
82
83pub fn parse_short_any_ip_cidr(s: &str) -> Result<AnyIpCidr, NetworkParseError> {
85 super::parse_any_cidr_full(s, FromStr::from_str, parse_short_ip_address_as_cidr)
86}
87
88#[cfg(test)]
89mod tests {
90 use super::{
91 parse_short_ip_cidr,
92 parse_short_ipv4_cidr,
93 };
94 use crate::{
95 IpCidr,
96 Ipv4Cidr,
97 };
98
99 fn test(s: &str, expect: &str) {
100 let expect_v4 = expect.parse::<Ipv4Cidr>().unwrap();
102 let expect = expect.parse::<IpCidr>().unwrap();
103
104 assert_eq!(parse_short_ipv4_cidr(s).unwrap(), expect_v4);
105
106 assert_eq!(parse_short_ip_cidr(s).unwrap(), expect);
107 }
108
109 #[test]
110 fn invalid_short() {
111 assert!(parse_short_ipv4_cidr("").is_err());
112 assert!(parse_short_ip_cidr("").is_err());
113 }
114
115 #[test]
116 fn short_10() {
117 test("10.0.0.0/8", "10.0.0.0/8");
118 test("10", "10.0.0.0/8");
119 test("10.42.0.0/16", "10.42.0.0/16");
120 test("10.42", "10.42.0.0/16");
121 test("10.0.42.0/24", "10.0.42.0/24");
122 test("10.0.42", "10.0.42.0/24");
123 test("10.0.0.42/32", "10.0.0.42/32");
124 test("10.0.0.42", "10.0.0.42/32");
125 }
126
127 #[test]
128 fn short_192_168() {
129 test("192.168.0.0/16", "192.168.0.0/16");
130 test("192.168", "192.168.0.0/16");
131 test("192.168.42.0/24", "192.168.42.0/24");
132 test("192.168.42", "192.168.42.0/24");
133 test("192.168.0.42/32", "192.168.0.42/32");
134 test("192.168.0.42", "192.168.0.42/32");
135 }
136
137 #[test]
138 fn short_192_0_2() {
139 test("192.0.2.0/24", "192.0.2.0/24");
140 test("192.0.2", "192.0.2.0/24");
141 test("192.0.2.42/32", "192.0.2.42/32");
142 test("192.0.2.42", "192.0.2.42/32");
143 }
144}