use crate::PrefixMap;
use crate::error::{DerefError, IriRefError, PrefixMapError};
use crate::iri::deref_iri::DerefIri;
use iri_s::IriS;
use iri_s::error::IriSError;
use serde::Serialize;
use std::borrow::Cow;
use std::{fmt::Display, str::FromStr};
#[derive(Serialize, Debug, PartialEq, Hash, Eq, Clone, PartialOrd, Ord)]
#[serde(into = "String")]
pub enum IriRef {
Iri(IriS),
Prefixed { prefix: String, local: String },
}
impl IriRef {
pub fn get_iri(&self) -> Result<&IriS, IriRefError> {
match self {
IriRef::Iri(iri) => Ok(iri),
IriRef::Prefixed { prefix, local } => Err(IriRefError {
prefix: prefix.clone(),
local: local.clone(),
}),
}
}
pub fn get_iri_prefixmap(&self, prefixmap: &PrefixMap) -> Result<Cow<'_, IriS>, PrefixMapError> {
match self {
IriRef::Iri(iri) => Ok(Cow::Borrowed(iri)),
IriRef::Prefixed { prefix, local } => prefixmap.resolve_prefix_local(prefix, local).map(Cow::Owned),
}
}
pub fn prefixed<S: Into<String>>(prefix: S, local: S) -> IriRef {
IriRef::Prefixed {
prefix: prefix.into(),
local: local.into(),
}
}
pub fn iri(iri: IriS) -> IriRef {
IriRef::Iri(iri)
}
}
impl DerefIri for IriRef {
fn deref_iri(self, base: Option<&IriS>, prefixmap: Option<&PrefixMap>) -> Result<Self, DerefError> {
match self {
IriRef::Iri(iri_s) => {
let resolved = match base {
None => iri_s,
Some(base) => base.resolve(iri_s)?,
};
Ok(IriRef::Iri(resolved))
},
IriRef::Prefixed { prefix, local } => {
let prefixmap = match prefixmap {
None => return Err(DerefError::NoPrefixMapPrefixedName { prefix, local }),
Some(pm) => pm,
};
let iri =
prefixmap
.resolve_prefix_local(&prefix, &local)
.map_err(|e| DerefError::DerefPrefixMapError {
alias: prefix,
local,
error: Box::new(e),
})?;
Ok(IriRef::Iri(iri))
},
}
}
}
impl TryFrom<&str> for IriRef {
type Error = IriSError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
FromStr::from_str(value)
}
}
impl FromStr for IriRef {
type Err = IriSError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(IriRef::Iri(IriS::from_str(s)?))
}
}
impl From<IriRef> for IriS {
fn from(iri_ref: IriRef) -> IriS {
match iri_ref {
IriRef::Iri(iri_s) => iri_s,
IriRef::Prefixed { prefix, local } => {
panic!("Cannot convert prefixed name {prefix}:{local} to IriS without context")
},
}
}
}
impl From<IriS> for IriRef {
fn from(i: IriS) -> IriRef {
IriRef::Iri(i)
}
}
impl From<IriRef> for String {
fn from(iri_ref: IriRef) -> String {
match iri_ref {
IriRef::Iri(i) => i.as_str().to_string(),
IriRef::Prefixed { prefix, local } => format!("{prefix}:{local}"),
}
}
}
impl Display for IriRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
IriRef::Iri(i) => write!(f, "{i}"),
IriRef::Prefixed { prefix, local } => write!(f, "{prefix}:{local}"),
}
}
}