boreholeio 0.1.0

A library for interacting with borehole.io, a subsurface data management, delivery and visualisation platform
Documentation
use super::{AbsoluteUri, Authority, Fragment, Query, Uri};
use iri_string::{
    format::ToDedicatedString,
    types::{IriRelativeStr, UriRelativeStr, UriRelativeString},
};
use std::path::{Path, PathBuf};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RelativeReference(pub(super) UriRelativeString);

impl RelativeReference {
    pub fn as_str(&self) -> &str {
        self.0.as_str()
    }

    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub fn empty() -> Self {
        Self("".try_into().unwrap())
    }

    pub fn resolve(&self, absolute: &AbsoluteUri) -> Uri {
        Uri(self.0.resolve_against(&absolute.0).and_normalize().into())
    }

    pub fn authority(&self) -> Option<Authority> {
        self.0.authority_str().map(Authority)
    }

    pub fn query(&self) -> Option<Query> {
        self.0.query().map(Query::from)
    }

    #[expect(unused_variables)]
    pub fn set_query(&mut self, query: Option<&Query>) {
        // There doesn't seem to be a set_query in iri-string?!?
        todo!()
    }

    pub fn fragment(&self) -> Option<Fragment> {
        self.0.fragment().map(Fragment::from)
    }

    pub fn set_fragment(&mut self, fragment: Option<&Fragment>) {
        self.0.set_fragment(fragment.map(|f| f.0.as_slice()));
    }
}

impl From<&UriRelativeStr> for RelativeReference {
    fn from(value: &UriRelativeStr) -> Self {
        Self(value.to_owned())
    }
}

impl TryFrom<&Path> for RelativeReference {
    type Error = String;

    fn try_from(value: &Path) -> Result<Self, Self::Error> {
        if value.is_absolute() {
            Err(format!(
                "Cannot convert an absolute path {value:?} into a Relative Reference."
            ))
        } else {
            let path_string = value
                .to_str()
                .ok_or(format!(
                    "Provided path {value:?} cannot be converted into a Relative Reference."
                ))?
                .replace(std::path::MAIN_SEPARATOR, "/");
            let relative_reference = IriRelativeStr::new(&path_string).or(Err(format!(
                "Provided path {value:?} cannot be converted into a Relative Reference."
            )))?;
            Ok(Self(
                relative_reference.encode_to_uri().to_dedicated_string(),
            ))
        }
    }
}

impl TryFrom<&RelativeReference> for PathBuf {
    type Error = String;

    fn try_from(value: &RelativeReference) -> Result<Self, Self::Error> {
        if value.fragment().is_some() {
            Err(format!(
                "Can't convert Relative Reference with a fragment {value:?} into a path."
            ))
        } else if value.query().is_some() {
            Err(format!(
                "Can't convert Relative Reference with a query {value:?} into a path."
            ))
        } else if !value.authority().unwrap_or(Authority::EMPTY).is_empty() {
            Err(format!(
                "Can't convert Relative Reference with a non-empty authority {value:?} into a path."
            ))
        } else {
            Ok(value.as_str().into())
        }
    }
}