web_url/parse/pre_path/
port.rs1use std::str::FromStr;
2
3use crate::parse::Error;
4use crate::parse::Error::InvalidPort;
5
6#[allow(clippy::type_complexity)]
14pub fn parse_port(s: &str) -> Result<(Option<u16>, &str), Error> {
15 if !s.is_empty() && s.as_bytes()[0] == b':' {
16 let s: &str = &s[1..];
17 if let Some(slash) = s.as_bytes().iter().position(|c| *c == b'/') {
18 let port: u16 = u16::from_str(&s[..slash]).map_err(|_| InvalidPort)?;
19 Ok((Some(port), &s[slash..]))
20 } else {
21 let port: u16 = u16::from_str(s).map_err(|_| InvalidPort)?;
22 Ok((Some(port), ""))
23 }
24 } else {
25 Ok((None, s))
26 }
27}
28
29#[cfg(test)]
30mod tests {
31 use crate::parse::pre_path::parse_port;
32 use crate::parse::Error;
33 use crate::parse::Error::InvalidPort;
34
35 #[test]
36 #[allow(clippy::type_complexity)]
37 fn fn_extract_port() {
38 let test_cases: &[(&str, Result<(Option<u16>, &str), Error>)] = &[
39 ("", Ok((None, ""))),
40 ("anything", Ok((None, "anything"))),
41 (":invalid", Err(InvalidPort)),
42 (":invalid/", Err(InvalidPort)),
43 (":80", Ok((Some(80), ""))),
44 (":80/", Ok((Some(80), "/"))),
45 (":80?", Err(InvalidPort)),
46 (":80#", Err(InvalidPort)),
47 (":80 ", Err(InvalidPort)),
48 ];
49 for (s, expected) in test_cases {
50 let result: Result<(Option<u16>, &str), Error> = parse_port(s);
51 assert_eq!(result, *expected, "s={}", s);
52 }
53 }
54}