shared/http/
url.rs

1use core::fmt::{self, Display};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct Url<'a> {
5    pub scheme: &'a str,
6    pub host: &'a str,
7    pub path: &'a str,
8}
9
10impl<'a> Url<'a> {
11    pub fn parse(url: &'a str) -> Option<Self> {
12        let scheme_end = url.find("://")?;
13        let scheme = &url[..scheme_end];
14
15        let host_start = scheme_end + 3;
16        let path_start = url[host_start..]
17            .find('/')
18            .map_or(url.len(), |i| host_start + i);
19        let host = &url[host_start..path_start];
20
21        let path = if path_start < url.len() {
22            &url[path_start..]
23        } else {
24            "/"
25        };
26
27        Some(Url { scheme, host, path })
28    }
29}
30
31impl Display for Url<'_> {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
33        write!(f, "{}://{}{}", self.scheme, self.host, self.path)
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    #[test]
42    fn test_url_parsing() {
43        let url_str = "https://example.com/path/to/resource";
44        let url = Url::parse(url_str).unwrap();
45        assert_eq!(url.scheme, "https");
46        assert_eq!(url.host, "example.com");
47        assert_eq!(url.path, "/path/to/resource");
48    }
49    #[test]
50    fn test_url_parsing_no_path() {
51        let url_str = "http://example.com";
52        let url = Url::parse(url_str).unwrap();
53        assert_eq!(url.scheme, "http");
54        assert_eq!(url.host, "example.com");
55        assert_eq!(url.path, "/");
56    }
57}