use alloc::{borrow::Cow, string::String};
use core::str::FromStr;
const RDF_LANG_STRING: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString";
const RDF_DIR_LANG_STRING: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString";
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Datatype {
RdfLangString,
RdfDirLangString,
Xsd(xsd::Type),
Other(Cow<'static, str>),
}
impl Datatype {
pub fn from_iri(iri: impl AsRef<str>) -> Self {
Self::from(iri.as_ref())
}
pub fn curie(&self) -> Option<&str> {
Some(match self {
Datatype::RdfLangString => "rdf:langString",
Datatype::RdfDirLangString => "rdf:dirLangString",
Datatype::Xsd(xsd) => xsd.curie(),
Datatype::Other(_) => return None, })
}
pub fn iri_string(&self) -> Cow<'_, str> {
match self {
Datatype::RdfLangString => Cow::Borrowed(RDF_LANG_STRING),
Datatype::RdfDirLangString => Cow::Borrowed(RDF_DIR_LANG_STRING),
Datatype::Xsd(xsd) => xsd.iri_string(),
Datatype::Other(other) => other.clone(),
}
}
}
impl core::fmt::Display for Datatype {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
if let Some(curie) = self.curie() {
f.write_str(curie)
} else {
f.write_str(self.iri_string().as_ref())
}
}
}
impl FromStr for Datatype {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
Ok(match input {
"rdf:langString" => Datatype::RdfLangString,
"rdf:dirLangString" => Datatype::RdfDirLangString,
_ => {
if let Some(input) = input.strip_prefix("xsd:") {
Datatype::Xsd(xsd::Type::from(input))
} else {
Self::from(input)
}
},
})
}
}
impl From<&str> for Datatype {
fn from(input: &str) -> Self {
if input == RDF_LANG_STRING {
Datatype::RdfLangString
} else if input == RDF_DIR_LANG_STRING {
Datatype::RdfDirLangString
} else if input.starts_with(xsd::BASE_URI) {
Datatype::Xsd(xsd::Type::from(&input[xsd::BASE_URI.len()..]))
} else {
Datatype::Other(Cow::Owned(input.into()))
}
}
}
impl From<Cow<'_, str>> for Datatype {
fn from(input: Cow<'_, str>) -> Self {
Self::from(input.as_ref())
}
}
impl From<String> for Datatype {
fn from(input: String) -> Self {
Self::from(input.as_str())
}
}
impl From<&String> for Datatype {
fn from(input: &String) -> Self {
Self::from(input.as_str())
}
}
impl From<xsd::Type> for Datatype {
fn from(input: xsd::Type) -> Self {
Self::Xsd(input)
}
}
impl From<&xsd::Type> for Datatype {
fn from(input: &xsd::Type) -> Self {
Self::Xsd(input.clone())
}
}