1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use super::{
super::{errors::*, url::*, util::*},
context::*,
};
impl UrlContext {
/// Parses the argument as an absolute URL.
///
/// Make sure to call `URL::conform` or `URL::conform_async` before calling
/// `URL::open` or `URL::open_async`.
///
/// To support relative URLs, see [url](UrlContext::url).
///
/// If you are expecting either a URL or a file path, consider
/// [absolute_url_or_file_path](UrlContext::absolute_url_or_file_path).
pub fn absolute_url(self: &UrlContextRef, url_representation: &str) -> Result<UrlRef, UrlError> {
let url_representation = self.get_url_or_override(url_representation.into())?;
let url = url::Url::parse(&url_representation).map_err(|error| UrlError::MalformedUrl(error.to_string()))?;
match url.scheme() {
"internal" => {
let (query, fragment) = url_query_and_fragment(&url);
Ok(self.internal_url(url.path().into(), url.host_str().map(|host| host.into()), query, fragment))
}
#[cfg(feature = "file")]
"file" => {
let (query, fragment) = url_query_and_fragment(&url);
Ok(self.file_url(url.path().into(), url.host_str().map(|host| host.into()), query, fragment))
}
#[cfg(feature = "http")]
"http" | "https" => Ok(self.http_url(url)),
#[cfg(feature = "tar")]
"tar" => {
use super::super::tar::*;
let (archive_url_representation, path) = TarUrl::parse(url.as_str())?;
let archive_url = self.absolute_url(&archive_url_representation)?;
let compression = TarUrl::compression_from(&archive_url)?;
Ok(self.tar_url(archive_url, path.into(), compression))
}
#[cfg(feature = "zip")]
"zip" => {
use super::super::zip::*;
let (archive_url_representation, path) = ZipUrl::parse(url.as_str())?;
let archive_url = self.absolute_url(&archive_url_representation)?;
Ok(self.zip_url(archive_url, path.into()))
}
#[cfg(feature = "git")]
"git" => {
use super::super::git::*;
let (repository_url_representation, path) = GitUrl::parse(url.as_str())?;
let repository_url = self.absolute_url(&repository_url_representation)?;
Ok(self.git_url(repository_url, path.into())?)
}
scheme => Err(UrlError::UnsupportedScheme(scheme.into())),
}
}
/// Parses the argument as either an absolute URL or an absolute file path.
///
/// Make sure to call `URL::conform` or `URL::conform_async` before calling
/// `URL::open` or `URL::open_async`.
///
/// Internally, attempts to parse the URL via
/// [absolute_url](super::super::UrlContext::absolute_url) and if that fails treats
/// the URL as an absolute file path and returns a
/// [FileUrl](super::super::file::FileUrl).
///
/// To support relative URLs and relative file paths, see
/// [url_or_file_path](UrlContext::url_or_file_path).
///
/// On Windows note a rare edge case: If there happens to be a drive that has the
/// same name as a supported URL scheme (e.g. "http") then callers would have to
/// provide a full file URL, e.g. instead of "http:\Dir\file" provide
/// "file:///http:/Dir/file". Otherwise it would be parsed as a URL of that scheme.
/// rather than a file path.
#[cfg(feature = "file")]
pub fn absolute_url_or_file_path(
self: &UrlContextRef,
url_or_file_path_representation: &str,
) -> Result<UrlRef, UrlError> {
match self.clone().absolute_url(url_or_file_path_representation) {
Ok(url) => Ok(url),
Err(_) => Ok(self.file_url(url_or_file_path_representation.into(), None, None, None)),
}
}
}