Skip to content

Instantly share code, notes, and snippets.

@Profpatsch
Created May 16, 2020 00:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Profpatsch/8698419de43f1930e6065cb69257157a to your computer and use it in GitHub Desktop.
Save Profpatsch/8698419de43f1930e6065cb69257157a to your computer and use it in GitHub Desktop.
#[derive(Clone, Debug, PartialEq, Eq,)]
struct Parsed<'a> {
protocol: Protocol,
domain: &'a str,
port: &'a str,
rest: &'a str,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Protocol {
Http,
Https,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Error {
NotHttp,
ColonButNoPort
}
fn mini_parse_http(url: &str) -> Result<Parsed, Error> {
let (protocol, off) = {
if url.starts_with("https://") {
(Protocol::Https, 8)
} else if url.starts_with("http://") {
(Protocol::Http, 7)
} else {
return Err(Error::NotHttp)
}
};
let (_, rest) = url.split_at(off);
let (domain_port, rest) = match rest.find('/') {
Some(boundary) => rest.split_at(boundary),
None => (rest, "")
};
let (domain, port) = match domain_port.find(':') {
Some(boundary) => match domain_port.split_at(boundary) {
(d, ":") => return Err(Error::ColonButNoPort),
(d, p) => unsafe { (d, p.get_unchecked(1..)) }
},
None => match protocol {
Protocol::Http => (domain_port, "80"),
Protocol::Https => (domain_port, "443"),
}
};
Ok(Parsed {
protocol,
domain,
port,
rest
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mini_parse() {
assert_eq!(mini_parse_http("https://abc.bar:8080/blabla"),
Ok(Parsed {
protocol: Protocol::Https,
domain: "abc.bar",
port: "8080",
rest: "/blabla"
}));
assert_eq!(mini_parse_http("http://abc.bar:8080/blabla"),
Ok(Parsed {
protocol: Protocol::Http,
domain: "abc.bar",
port: "8080",
rest: "/blabla"
}));
assert_eq!(mini_parse_http("http://abc.bar/blabla"),
Ok(Parsed {
protocol: Protocol::Http,
domain: "abc.bar",
port: "80",
rest: "/blabla"
}));
assert_eq!(mini_parse_http("https://f"),
Ok(Parsed {
protocol: Protocol::Https,
domain: "f",
port: "443",
rest: ""
}));
assert_eq!(mini_parse_http("foo.bar"),
Err(Error::NotHttp));
assert_eq!(mini_parse_http("mirror://abc.bar:8080/blabla"),
Err(Error::NotHttp));
assert_eq!(mini_parse_http("http://abc.bar:"),
Err(Error::ColonButNoPort));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment