Fork of https://github.com/oxigraph/oxigraph.git for the purpose of NextGraph project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
oxigraph/lib/oxrdf/src/interning.rs

427 lines
14 KiB

//! Interning of RDF elements using Rodeo
use crate::*;
use lasso::{Key, Rodeo, Spur};
#[cfg(feature = "rdf-star")]
use std::collections::HashMap;
#[derive(Debug, Default)]
pub struct Interner {
strings: Rodeo,
#[cfg(feature = "rdf-star")]
triples: HashMap<InternedTriple, Triple>,
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
pub struct InternedNamedNode {
id: Spur,
}
impl InternedNamedNode {
pub fn encoded_into(named_node: NamedNodeRef<'_>, interner: &mut Interner) -> Self {
Self {
id: interner.strings.get_or_intern(named_node.as_str()),
}
}
pub fn encoded_from(named_node: NamedNodeRef<'_>, interner: &Interner) -> Option<Self> {
Some(Self {
id: interner.strings.get(named_node.as_str())?,
})
}
pub fn decode_from<'a>(&self, interner: &'a Interner) -> NamedNodeRef<'a> {
NamedNodeRef::new_unchecked(interner.strings.resolve(&self.id))
}
pub fn first() -> Self {
Self { id: fist_spur() }
}
pub fn next(self) -> Self {
Self {
id: next_spur(self.id),
}
}
pub fn impossible() -> Self {
Self {
id: impossible_spur(),
}
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
pub struct InternedBlankNode {
id: Spur,
}
impl InternedBlankNode {
pub fn encoded_into(blank_node: BlankNodeRef<'_>, interner: &mut Interner) -> Self {
Self {
id: interner.strings.get_or_intern(blank_node.as_str()),
}
}
pub fn encoded_from(blank_node: BlankNodeRef<'_>, interner: &Interner) -> Option<Self> {
Some(Self {
id: interner.strings.get(blank_node.as_str())?,
})
}
pub fn decode_from<'a>(&self, interner: &'a Interner) -> BlankNodeRef<'a> {
BlankNodeRef::new_unchecked(interner.strings.resolve(&self.id))
}
pub fn next(self) -> Self {
Self {
id: next_spur(self.id),
}
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
pub enum InternedLiteral {
String {
value_id: Spur,
},
LanguageTaggedString {
value_id: Spur,
language_id: Spur,
},
TypedLiteral {
value_id: Spur,
datatype: InternedNamedNode,
},
}
impl InternedLiteral {
pub fn encoded_into(literal: LiteralRef<'_>, interner: &mut Interner) -> Self {
let value_id = interner.strings.get_or_intern(literal.value());
if literal.is_plain() {
if let Some(language) = literal.language() {
Self::LanguageTaggedString {
value_id,
language_id: interner.strings.get_or_intern(language),
}
} else {
Self::String { value_id }
}
} else {
Self::TypedLiteral {
value_id,
datatype: InternedNamedNode::encoded_into(literal.datatype(), interner),
}
}
}
pub fn encoded_from(literal: LiteralRef<'_>, interner: &Interner) -> Option<Self> {
let value_id = interner.strings.get(literal.value())?;
Some(if literal.is_plain() {
if let Some(language) = literal.language() {
Self::LanguageTaggedString {
value_id,
language_id: interner.strings.get(language)?,
}
} else {
Self::String { value_id }
}
} else {
Self::TypedLiteral {
value_id,
datatype: InternedNamedNode::encoded_from(literal.datatype(), interner)?,
}
})
}
pub fn decode_from<'a>(&self, interner: &'a Interner) -> LiteralRef<'a> {
match self {
InternedLiteral::String { value_id } => {
LiteralRef::new_simple_literal(interner.strings.resolve(value_id))
}
InternedLiteral::LanguageTaggedString {
value_id,
language_id,
} => LiteralRef::new_language_tagged_literal_unchecked(
interner.strings.resolve(value_id),
interner.strings.resolve(language_id),
),
InternedLiteral::TypedLiteral { value_id, datatype } => LiteralRef::new_typed_literal(
interner.strings.resolve(value_id),
datatype.decode_from(interner),
),
}
}
pub fn next(&self) -> Self {
match self {
Self::String { value_id } => Self::String {
value_id: next_spur(*value_id),
},
Self::LanguageTaggedString {
value_id,
language_id,
} => Self::LanguageTaggedString {
value_id: *value_id,
language_id: next_spur(*language_id),
},
Self::TypedLiteral { value_id, datatype } => Self::TypedLiteral {
value_id: *value_id,
datatype: datatype.next(),
},
}
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub enum InternedSubject {
NamedNode(InternedNamedNode),
BlankNode(InternedBlankNode),
#[cfg(feature = "rdf-star")]
Triple(Box<InternedTriple>),
}
impl InternedSubject {
pub fn encoded_into(node: SubjectRef<'_>, interner: &mut Interner) -> Self {
match node {
SubjectRef::NamedNode(node) => {
Self::NamedNode(InternedNamedNode::encoded_into(node, interner))
}
SubjectRef::BlankNode(node) => {
Self::BlankNode(InternedBlankNode::encoded_into(node, interner))
}
#[cfg(feature = "rdf-star")]
SubjectRef::Triple(triple) => Self::Triple(Box::new(InternedTriple::encoded_into(
triple.as_ref(),
interner,
))),
}
}
pub fn encoded_from(node: SubjectRef<'_>, interner: &Interner) -> Option<Self> {
Some(match node {
SubjectRef::NamedNode(node) => {
Self::NamedNode(InternedNamedNode::encoded_from(node, interner)?)
}
SubjectRef::BlankNode(node) => {
Self::BlankNode(InternedBlankNode::encoded_from(node, interner)?)
}
#[cfg(feature = "rdf-star")]
SubjectRef::Triple(triple) => Self::Triple(Box::new(InternedTriple::encoded_from(
triple.as_ref(),
interner,
)?)),
})
}
pub fn decode_from<'a>(&self, interner: &'a Interner) -> SubjectRef<'a> {
match self {
Self::NamedNode(node) => SubjectRef::NamedNode(node.decode_from(interner)),
Self::BlankNode(node) => SubjectRef::BlankNode(node.decode_from(interner)),
#[cfg(feature = "rdf-star")]
Self::Triple(triple) => SubjectRef::Triple(&interner.triples[triple.as_ref()]),
}
}
pub fn first() -> Self {
Self::NamedNode(InternedNamedNode::first())
}
pub fn next(&self) -> Self {
match self {
Self::NamedNode(node) => Self::NamedNode(node.next()),
Self::BlankNode(node) => Self::BlankNode(node.next()),
#[cfg(feature = "rdf-star")]
Self::Triple(triple) => Self::Triple(Box::new(triple.next())),
}
}
pub fn impossible() -> Self {
Self::NamedNode(InternedNamedNode::impossible())
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub enum InternedGraphName {
DefaultGraph,
NamedNode(InternedNamedNode),
BlankNode(InternedBlankNode),
}
impl InternedGraphName {
pub fn encoded_into(node: GraphNameRef<'_>, interner: &mut Interner) -> Self {
match node {
GraphNameRef::DefaultGraph => Self::DefaultGraph,
GraphNameRef::NamedNode(node) => {
Self::NamedNode(InternedNamedNode::encoded_into(node, interner))
}
GraphNameRef::BlankNode(node) => {
Self::BlankNode(InternedBlankNode::encoded_into(node, interner))
}
}
}
pub fn encoded_from(node: GraphNameRef<'_>, interner: &Interner) -> Option<Self> {
Some(match node {
GraphNameRef::DefaultGraph => Self::DefaultGraph,
GraphNameRef::NamedNode(node) => {
Self::NamedNode(InternedNamedNode::encoded_from(node, interner)?)
}
GraphNameRef::BlankNode(node) => {
Self::BlankNode(InternedBlankNode::encoded_from(node, interner)?)
}
})
}
pub fn decode_from<'a>(&self, interner: &'a Interner) -> GraphNameRef<'a> {
match self {
Self::DefaultGraph => GraphNameRef::DefaultGraph,
Self::NamedNode(node) => GraphNameRef::NamedNode(node.decode_from(interner)),
Self::BlankNode(node) => GraphNameRef::BlankNode(node.decode_from(interner)),
}
}
pub fn first() -> Self {
Self::DefaultGraph
}
pub fn next(&self) -> Self {
match self {
Self::DefaultGraph => Self::NamedNode(InternedNamedNode::first()),
Self::NamedNode(node) => Self::NamedNode(node.next()),
Self::BlankNode(node) => Self::BlankNode(node.next()),
}
}
pub fn impossible() -> Self {
Self::NamedNode(InternedNamedNode::impossible())
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub enum InternedTerm {
NamedNode(InternedNamedNode),
BlankNode(InternedBlankNode),
Literal(InternedLiteral),
#[cfg(feature = "rdf-star")]
Triple(Box<InternedTriple>),
}
impl InternedTerm {
pub fn encoded_into(term: TermRef<'_>, interner: &mut Interner) -> Self {
match term {
TermRef::NamedNode(term) => {
Self::NamedNode(InternedNamedNode::encoded_into(term, interner))
}
TermRef::BlankNode(term) => {
Self::BlankNode(InternedBlankNode::encoded_into(term, interner))
}
TermRef::Literal(term) => Self::Literal(InternedLiteral::encoded_into(term, interner)),
#[cfg(feature = "rdf-star")]
TermRef::Triple(triple) => Self::Triple(Box::new(InternedTriple::encoded_into(
triple.as_ref(),
interner,
))),
}
}
pub fn encoded_from(term: TermRef<'_>, interner: &Interner) -> Option<Self> {
Some(match term {
TermRef::NamedNode(term) => {
Self::NamedNode(InternedNamedNode::encoded_from(term, interner)?)
}
TermRef::BlankNode(term) => {
Self::BlankNode(InternedBlankNode::encoded_from(term, interner)?)
}
TermRef::Literal(term) => Self::Literal(InternedLiteral::encoded_from(term, interner)?),
#[cfg(feature = "rdf-star")]
TermRef::Triple(triple) => Self::Triple(Box::new(InternedTriple::encoded_from(
triple.as_ref(),
interner,
)?)),
})
}
pub fn decode_from<'a>(&self, interner: &'a Interner) -> TermRef<'a> {
match self {
Self::NamedNode(term) => TermRef::NamedNode(term.decode_from(interner)),
Self::BlankNode(term) => TermRef::BlankNode(term.decode_from(interner)),
Self::Literal(term) => TermRef::Literal(term.decode_from(interner)),
#[cfg(feature = "rdf-star")]
Self::Triple(triple) => TermRef::Triple(&interner.triples[triple.as_ref()]),
}
}
pub fn first() -> Self {
Self::NamedNode(InternedNamedNode::first())
}
pub fn next(&self) -> Self {
match self {
Self::NamedNode(node) => Self::NamedNode(node.next()),
Self::BlankNode(node) => Self::BlankNode(node.next()),
Self::Literal(node) => Self::Literal(node.next()),
#[cfg(feature = "rdf-star")]
Self::Triple(triple) => Self::Triple(Box::new(triple.next())),
}
}
pub fn impossible() -> Self {
Self::NamedNode(InternedNamedNode::impossible())
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct InternedTriple {
pub subject: InternedSubject,
pub predicate: InternedNamedNode,
pub object: InternedTerm,
}
#[cfg(feature = "rdf-star")]
impl InternedTriple {
pub fn encoded_into(triple: TripleRef<'_>, interner: &mut Interner) -> Self {
let interned_triple = Self {
subject: InternedSubject::encoded_into(triple.subject, interner),
predicate: InternedNamedNode::encoded_into(triple.predicate, interner),
object: InternedTerm::encoded_into(triple.object, interner),
};
interner
.triples
.insert(interned_triple.clone(), triple.into_owned());
interned_triple
}
pub fn encoded_from(triple: TripleRef<'_>, interner: &Interner) -> Option<Self> {
let interned_triple = Self {
subject: InternedSubject::encoded_from(triple.subject, interner)?,
predicate: InternedNamedNode::encoded_from(triple.predicate, interner)?,
object: InternedTerm::encoded_from(triple.object, interner)?,
};
if interner.triples.contains_key(&interned_triple) {
Some(interned_triple)
} else {
None
}
}
pub fn next(&self) -> Self {
Self {
subject: self.subject.clone(),
predicate: self.predicate,
object: self.object.next(),
}
}
}
fn fist_spur() -> Spur {
Spur::try_from_usize(0).unwrap()
}
fn next_spur(value: Spur) -> Spur {
Spur::try_from_usize(value.into_usize() + 1).unwrap()
}
fn impossible_spur() -> Spur {
Spur::try_from_usize((u32::MAX - 10).try_into().unwrap()).unwrap()
}