use qubit_metadata::Metadata;
use url::Url;
use crate::{
FsAuthority,
FsError,
FsOperation,
FsPath,
FsResult,
};
#[derive(Clone, Debug, PartialEq)]
pub struct FsUri {
pub scheme: String,
pub authority: Option<FsAuthority>,
pub path: FsPath,
pub query: Metadata,
}
impl FsUri {
pub fn parse(uri: &str) -> FsResult<Self> {
let parsed = Url::parse(uri).map_err(|error| {
FsError::with_source(
crate::FsErrorKind::InvalidPath,
FsOperation::ParseUri,
"invalid filesystem URI",
error,
)
})?;
let scheme = parsed.scheme().to_ascii_lowercase();
let authority = parsed.host_str().map(|host| {
let mut authority = FsAuthority::new(host);
if let Some(port) = parsed.port() {
authority = authority.with_port(port);
}
let username = parsed.username();
if !username.is_empty() {
authority = authority.with_username(username);
}
authority
});
let path = FsPath::parse(parsed.path()).map_err(|error| {
FsError::new(
error.kind(),
FsOperation::ParseUri,
"URI path is not a valid filesystem path",
)
})?;
let mut query = Metadata::new();
for (key, value) in parsed.query_pairs() {
query.set(key.as_ref(), value.into_owned());
}
Ok(Self {
scheme,
authority,
path,
query,
})
}
}