1use qubit_metadata::Metadata;
13use url::Url;
14
15use crate::{
16 FsAuthority,
17 FsError,
18 FsOperation,
19 FsPath,
20 FsResult,
21};
22
23#[derive(Clone, Debug, PartialEq)]
25pub struct FsUri {
26 pub scheme: String,
28 pub authority: Option<FsAuthority>,
30 pub path: FsPath,
32 pub query: Metadata,
34}
35
36impl FsUri {
37 pub fn parse(uri: &str) -> FsResult<Self> {
48 let parsed = Url::parse(uri).map_err(|error| {
49 FsError::with_source(
50 crate::FsErrorKind::InvalidPath,
51 FsOperation::ParseUri,
52 "invalid filesystem URI",
53 error,
54 )
55 })?;
56 let scheme = parsed.scheme().to_ascii_lowercase();
57 let authority = parsed.host_str().map(|host| {
58 let mut authority = FsAuthority::new(host);
59 if let Some(port) = parsed.port() {
60 authority = authority.with_port(port);
61 }
62 let username = parsed.username();
63 if !username.is_empty() {
64 authority = authority.with_username(username);
65 }
66 authority
67 });
68 let path = FsPath::parse(parsed.path()).map_err(|error| {
69 FsError::new(
70 error.kind(),
71 FsOperation::ParseUri,
72 "URI path is not a valid filesystem path",
73 )
74 })?;
75 let mut query = Metadata::new();
76 for (key, value) in parsed.query_pairs() {
77 query.set(key.as_ref(), value.into_owned());
78 }
79 Ok(Self {
80 scheme,
81 authority,
82 path,
83 query,
84 })
85 }
86}