use self::errors::*;
use crate::DsntkError;
use uriparse::URIReference;
#[derive(Debug, Clone)]
pub struct HRef {
namespace: Option<String>,
id: String,
}
impl HRef {
pub fn namespace(&self) -> Option<&String> {
self.namespace.as_ref()
}
pub fn id(&self) -> &str {
&self.id
}
}
impl TryFrom<&str> for HRef {
type Error = DsntkError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
match URIReference::try_from(s) {
Ok(mut uri_reference) => {
uri_reference.normalize();
let (scheme, authority, path, query, fragment) = uri_reference.into_parts();
if query.is_some() {
return Err(err_query_not_allowed(s));
}
if fragment.is_none() {
return Err(err_fragment_is_missing(s));
}
let id = fragment.unwrap().to_string();
let base_uri = URIReference::builder()
.with_scheme(scheme)
.with_authority(authority)
.with_path(path)
.build()
.unwrap() .to_string();
let namespace = if base_uri.is_empty() { None } else { Some(base_uri) };
Ok(Self { namespace, id })
}
Err(reason) => Err(err_invalid_reference(s, reason.to_string())),
}
}
}
mod errors {
use crate::{DsntkError, ToErrorMessage};
#[derive(ToErrorMessage)]
struct HRefError(String);
pub fn err_invalid_reference(s: &str, reason: String) -> DsntkError {
HRefError(format!("invalid reference '{s}', reason: {reason}")).into()
}
pub fn err_fragment_is_missing(s: &str) -> DsntkError {
HRefError(format!("fragment is missing in reference: '{s}'")).into()
}
pub fn err_query_not_allowed(s: &str) -> DsntkError {
HRefError(format!("query is not allowed in reference: '{s}'")).into()
}
}