use crate::{Id, Reference, ToReference};
use iref::{AsIri, Iri, IriBuf};
use std::convert::TryFrom;
use std::fmt;
use std::hash::Hash;
pub trait Vocab: AsIri + Clone + PartialEq + Eq + Hash {
fn from_iri(iri: Iri) -> Option<Self>;
}
impl<T: AsIri + Clone + PartialEq + Eq + Hash> Vocab for T
where
for<'a> T: TryFrom<Iri<'a>>,
{
#[inline]
fn from_iri(iri: Iri) -> Option<Self> {
match T::try_from(iri) {
Ok(t) => Some(t),
Err(_) => None,
}
}
}
impl<V: Vocab> ToReference<Lexicon<V>> for V {
type Reference = Reference<Lexicon<V>>;
#[inline(always)]
fn to_ref(&self) -> Self::Reference {
Reference::Id(Lexicon::Id(self.clone()))
}
}
impl<V: Vocab> PartialEq<V> for Reference<Lexicon<V>> {
#[inline]
fn eq(&self, other: &V) -> bool {
match self {
Reference::Id(Lexicon::Id(v)) => other == v,
_ => false,
}
}
}
impl<V: Vocab> PartialEq<V> for Lexicon<V> {
#[inline]
fn eq(&self, other: &V) -> bool {
match self {
Lexicon::Id(v) => other == v,
_ => false,
}
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum Lexicon<V: Vocab> {
Id(V),
Iri(IriBuf),
}
impl<V: Vocab> fmt::Display for Lexicon<V> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Lexicon::Id(id) => id.as_iri().fmt(f),
Lexicon::Iri(iri) => iri.fmt(f),
}
}
}
impl<V: Vocab> AsIri for Lexicon<V> {
#[inline]
fn as_iri(&self) -> Iri {
match self {
Lexicon::Id(id) => id.as_iri(),
Lexicon::Iri(iri) => iri.as_iri(),
}
}
}
impl<V: Vocab> Id for Lexicon<V> {
#[inline]
fn from_iri(iri: Iri) -> Lexicon<V> {
if let Some(v) = V::from_iri(iri) {
Lexicon::Id(v)
} else {
Lexicon::Iri(iri.into())
}
}
}