cargo/util/
into_url_with_base.rs

1use crate::util::{CargoResult, IntoUrl};
2
3use url::Url;
4
5/// A type that can be interpreted as a relative Url and converted to
6/// a Url.
7pub trait IntoUrlWithBase {
8    /// Performs the conversion
9    fn into_url_with_base<U: IntoUrl>(self, base: Option<U>) -> CargoResult<Url>;
10}
11
12impl<'a> IntoUrlWithBase for &'a str {
13    fn into_url_with_base<U: IntoUrl>(self, base: Option<U>) -> CargoResult<Url> {
14        let base_url = match base {
15            Some(base) => Some(
16                base.into_url()
17                    .map_err(|s| anyhow::format_err!("invalid url `{}`: {}", self, s))?,
18            ),
19            None => None,
20        };
21
22        Url::options()
23            .base_url(base_url.as_ref())
24            .parse(self)
25            .map_err(|s| anyhow::format_err!("invalid url `{}`: {}", self, s))
26    }
27}
28
29#[cfg(test)]
30mod tests {
31    use crate::util::IntoUrlWithBase;
32
33    #[test]
34    fn into_url_with_base() {
35        assert_eq!(
36            "rel/path"
37                .into_url_with_base(Some("file:///abs/path/"))
38                .unwrap()
39                .to_string(),
40            "file:///abs/path/rel/path"
41        );
42        assert_eq!(
43            "rel/path"
44                .into_url_with_base(Some("file:///abs/path/popped-file"))
45                .unwrap()
46                .to_string(),
47            "file:///abs/path/rel/path"
48        );
49    }
50}