use rdftk_iri::{Name, NameParser, QName};
use std::fmt::{Display, Formatter};
use std::str::FromStr;
use unique_id::sequence::SequenceGenerator as IDGenerator;
use unique_id::Generator;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BlankNode(String);
pub const BLANK_NODE_NAMESPACE: &str = "_";
pub const BLANK_NODE_PREFIX: &str = "_:";
impl Display for BlankNode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl FromStr for BlankNode {
type Err = crate::error::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
if BlankNode::is_valid_str(s) {
Ok(Self(s.into()))
} else {
Err(crate::error::Error::InvalidBlankNodeName { name: s.into() })
}
}
}
impl From<BlankNode> for String {
fn from(v: BlankNode) -> Self {
v.0
}
}
impl From<Name> for BlankNode {
fn from(v: Name) -> Self {
Self(v.into())
}
}
impl From<&Name> for BlankNode {
fn from(v: &Name) -> Self {
Self(v.into())
}
}
impl From<&BlankNode> for String {
fn from(v: &BlankNode) -> Self {
v.0.clone()
}
}
impl AsRef<str> for BlankNode {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
impl BlankNode {
pub fn generate() -> Self {
Self(format!("B{}", IDGenerator.next_id()))
}
pub fn is_valid_str<S>(s: S) -> bool
where
S: AsRef<str>,
{
let s: &str = s.as_ref();
NameParser::BlankNode.is_valid_str(if let Some(s) = s.strip_prefix(BLANK_NODE_PREFIX) {
s
} else {
s
})
}
pub fn to_qname(&self) -> QName {
QName::new_blank(Name::new_unchecked(&self.0)).unwrap()
}
}