use super::{AbsoluteUri, Authority, Fragment, Query, Scheme};
use iri_string::types::{UriStr, UriString};
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Uri(pub(super) UriString);
impl Uri {
pub fn as_str(&self) -> &str {
self.0.as_str()
}
pub fn to_absolute_and_fragment(&self) -> (AbsoluteUri, Option<Fragment>) {
let (absolute, fragment) = self.0.to_absolute_and_fragment();
(absolute.into(), fragment.map(Fragment::from))
}
pub fn scheme(&self) -> Scheme {
Scheme(self.0.scheme_str())
}
pub fn authority(&self) -> Option<Authority> {
self.0.authority_str().map(Authority)
}
pub fn query(&self) -> Option<Query> {
self.0.query().map(Query::from)
}
pub fn fragment(&self) -> Option<Fragment> {
self.0.fragment().map(Fragment::from)
}
}
impl From<&UriStr> for Uri {
fn from(value: &UriStr) -> Self {
Self(value.to_owned())
}
}
impl From<&AbsoluteUri> for Uri {
fn from(value: &AbsoluteUri) -> Self {
Self(value.0.to_owned().into())
}
}
impl TryFrom<&Path> for Uri {
type Error = String;
fn try_from(value: &Path) -> Result<Self, Self::Error> {
let absolute_uri: AbsoluteUri = value.try_into()?;
Ok((&absolute_uri).into())
}
}
impl TryFrom<&Uri> for PathBuf {
type Error = String;
fn try_from(value: &Uri) -> Result<Self, Self::Error> {
#[allow(clippy::collapsible_else_if)]
if value.fragment().is_some() {
Err(format!(
"Can't convert URI with a fragment {value:?} into a path."
))
} else if value.query().is_some() {
Err(format!(
"Can't convert URI with a query {value:?} into a path."
))
} else if !value.authority().unwrap_or(Authority::EMPTY).is_empty() {
Err(format!(
"Can't convert URI with a non-empty authority {value:?} into a path."
))
} else if value.scheme() != Scheme::FILE {
Err(format!(
"Can't convert URI with a scheme other than 'file' {value:?} into a path."
))
} else {
if cfg!(unix) {
Ok(value.0.path_str().into())
} else if cfg!(windows) {
Ok((&value.0.path_str()[1..]).into())
} else {
Err(format!(
"Unsure of operating system path semantics, so cannot convert URI {value:?} to a path."),
)
}
}
}
}