Adds borrowed data structures for RDF terms

pull/46/head
Tpt 4 years ago
parent d3d78b9713
commit 8bc84b2820
  1. 2
      js/src/model.rs
  2. 18
      js/src/store.rs
  3. 1
      lib/Cargo.toml
  4. 10
      lib/src/io/write.rs
  5. 2
      lib/src/lib.rs
  6. 207
      lib/src/model/blank_node.rs
  7. 294
      lib/src/model/literal.rs
  8. 11
      lib/src/model/mod.rs
  9. 119
      lib/src/model/named_node.rs
  10. 663
      lib/src/model/triple.rs
  11. 264
      lib/src/model/vocab.rs
  12. 12
      lib/src/sparql/algebra.rs
  13. 9
      lib/src/sparql/eval.rs
  14. 34
      lib/src/sparql/parser.rs
  15. 13
      lib/src/sparql/plan_builder.rs
  16. 46
      lib/src/store/memory.rs
  17. 69
      lib/src/store/mod.rs
  18. 101
      lib/src/store/numeric_encoder.rs
  19. 106
      lib/src/store/rocksdb.rs
  20. 106
      lib/src/store/sled.rs
  21. 8
      python/src/memory_store.rs
  22. 2
      python/src/model.rs
  23. 8
      python/src/sled_store.rs
  24. 1
      testsuite/Cargo.toml
  25. 73
      testsuite/src/manifest.rs
  26. 128
      testsuite/src/sparql_evaluator.rs
  27. 115
      testsuite/src/vocab.rs
  28. 8
      wikibase/src/loader.rs

@ -246,7 +246,7 @@ impl JsLiteral {
#[wasm_bindgen(getter)] #[wasm_bindgen(getter)]
pub fn datatype(&self) -> JsNamedNode { pub fn datatype(&self) -> JsNamedNode {
self.inner.datatype().clone().into() self.inner.datatype().into_owned().into()
} }
pub fn equals(&self, other: &JsValue) -> bool { pub fn equals(&self, other: &JsValue) -> bool {

@ -3,10 +3,10 @@ use crate::model::*;
use crate::utils::to_err; use crate::utils::to_err;
use js_sys::{Array, Map}; use js_sys::{Array, Map};
use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::io::{DatasetFormat, GraphFormat};
use oxigraph::model::GraphName; use oxigraph::model::*;
use oxigraph::sparql::{QueryOptions, QueryResult}; use oxigraph::sparql::{QueryOptions, QueryResult};
use oxigraph::MemoryStore; use oxigraph::MemoryStore;
use std::convert::TryInto; use std::convert::{TryFrom, TryInto};
use std::io::Cursor; use std::io::Cursor;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
@ -74,25 +74,29 @@ impl JsMemoryStore {
} else { } else {
None None
} }
.as_ref(), .as_ref()
.map(|t: &NamedOrBlankNode| t.into()),
if let Some(predicate) = self.from_js.to_optional_term(predicate)? { if let Some(predicate) = self.from_js.to_optional_term(predicate)? {
Some(predicate.try_into()?) Some(NamedNode::try_from(predicate)?)
} else { } else {
None None
} }
.as_ref(), .as_ref()
.map(|t: &NamedNode| t.into()),
if let Some(object) = self.from_js.to_optional_term(object)? { if let Some(object) = self.from_js.to_optional_term(object)? {
Some(object.try_into()?) Some(object.try_into()?)
} else { } else {
None None
} }
.as_ref(), .as_ref()
.map(|t: &Term| t.into()),
if let Some(graph_name) = self.from_js.to_optional_term(graph_name)? { if let Some(graph_name) = self.from_js.to_optional_term(graph_name)? {
Some(graph_name.try_into()?) Some(graph_name.try_into()?)
} else { } else {
None None
} }
.as_ref(), .as_ref()
.map(|t: &GraphName| t.into()),
) )
.map(|v| JsQuad::from(v).into()) .map(|v| JsQuad::from(v).into())
.collect::<Vec<_>>() .collect::<Vec<_>>()

@ -16,7 +16,6 @@ edition = "2018"
all-features = true all-features = true
[dependencies] [dependencies]
lazy_static = "1"
rocksdb = { version = "0.14", optional = true } rocksdb = { version = "0.14", optional = true }
sled = { version = "0.34", optional = true } sled = { version = "0.34", optional = true }
quick-xml = "0.18" quick-xml = "0.18"

@ -88,7 +88,8 @@ enum TripleWriterKind<W: Write> {
} }
impl<W: Write> TripleWriter<W> { impl<W: Write> TripleWriter<W> {
pub fn write(&mut self, triple: &Triple) -> Result<(), io::Error> { pub fn write<'a>(&mut self, triple: impl Into<TripleRef<'a>>) -> Result<(), io::Error> {
let triple = triple.into();
match &mut self.formatter { match &mut self.formatter {
TripleWriterKind::NTriples(formatter) => formatter.format(&triple.into())?, TripleWriterKind::NTriples(formatter) => formatter.format(&triple.into())?,
TripleWriterKind::Turtle(formatter) => formatter.format(&triple.into())?, TripleWriterKind::Turtle(formatter) => formatter.format(&triple.into())?,
@ -187,10 +188,11 @@ enum QuadWriterKind<W: Write> {
} }
impl<W: Write> QuadWriter<W> { impl<W: Write> QuadWriter<W> {
pub fn write(&mut self, triple: &Quad) -> Result<(), io::Error> { pub fn write<'a>(&mut self, quad: impl Into<QuadRef<'a>>) -> Result<(), io::Error> {
let quad = quad.into();
match &mut self.formatter { match &mut self.formatter {
QuadWriterKind::NQuads(formatter) => formatter.format(&triple.into())?, QuadWriterKind::NQuads(formatter) => formatter.format(&quad.into())?,
QuadWriterKind::TriG(formatter) => formatter.format(&triple.into())?, QuadWriterKind::TriG(formatter) => formatter.format(&quad.into())?,
} }
Ok(()) Ok(())
} }

@ -27,7 +27,7 @@
//! store.insert(quad.clone()); //! store.insert(quad.clone());
//! //!
//! // quad filter //! // quad filter
//! let results: Vec<Quad> = store.quads_for_pattern(Some(&ex.clone().into()), None, None, None).collect(); //! let results: Vec<Quad> = store.quads_for_pattern(Some(ex.as_ref().into()), None, None, None).collect();
//! assert_eq!(vec![quad], results); //! assert_eq!(vec![quad], results);
//! //!
//! // SPARQL query //! // SPARQL query

@ -5,7 +5,7 @@ use std::fmt;
use std::io::Write; use std::io::Write;
use std::str; use std::str;
/// An RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). /// An owned RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node).
/// ///
/// The common way to create a new blank node is to use the `BlankNode::default` trait method. /// The common way to create a new blank node is to use the `BlankNode::default` trait method.
/// ///
@ -28,7 +28,7 @@ pub struct BlankNode(BlankNodeContent);
#[derive(PartialEq, Eq, Debug, Clone, Hash)] #[derive(PartialEq, Eq, Debug, Clone, Hash)]
enum BlankNodeContent { enum BlankNodeContent {
Named(String), Named(String),
Anonymous { id: u128, str: [u8; 32] }, Anonymous { id: u128, str: IdStr },
} }
impl BlankNode { impl BlankNode {
@ -52,13 +52,8 @@ impl BlankNode {
/// Except if you really know what you do, you should use [`new`](#method.new). /// Except if you really know what you do, you should use [`new`](#method.new).
pub fn new_unchecked(id: impl Into<String>) -> Self { pub fn new_unchecked(id: impl Into<String>) -> Self {
let id = id.into(); let id = id.into();
if let Ok(numerical_id) = u128::from_str_radix(&id, 16) { if let Some(numerical_id) = to_integer_id(&id) {
let result = Self::new_from_unique_id(numerical_id); Self::new_from_unique_id(numerical_id)
if result.as_str() == id {
result
} else {
Self(BlankNodeContent::Named(id))
}
} else { } else {
Self(BlankNodeContent::Named(id)) Self(BlankNodeContent::Named(id))
} }
@ -69,19 +64,17 @@ impl BlankNode {
/// In most cases, it is much more convenient to create a blank node using `BlankNode::default()`. /// In most cases, it is much more convenient to create a blank node using `BlankNode::default()`.
pub fn new_from_unique_id(id: impl Into<u128>) -> Self { pub fn new_from_unique_id(id: impl Into<u128>) -> Self {
let id = id.into(); let id = id.into();
let mut str = [0; 32]; Self(BlankNodeContent::Anonymous {
write!(&mut str[..], "{:x}", id).unwrap(); id,
Self(BlankNodeContent::Anonymous { id, str }) str: IdStr::new(id),
})
} }
/// Returns the underlying ID of this blank node /// Returns the underlying ID of this blank node
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
match &self.0 { match &self.0 {
BlankNodeContent::Named(id) => id, BlankNodeContent::Named(id) => id,
BlankNodeContent::Anonymous { str, .. } => { BlankNodeContent::Anonymous { str, .. } => str.as_str(),
let len = str.iter().position(|x| x == &0).unwrap_or(32);
str::from_utf8(&str[..len]).unwrap()
}
} }
} }
@ -89,25 +82,24 @@ impl BlankNode {
pub fn into_string(self) -> String { pub fn into_string(self) -> String {
match self.0 { match self.0 {
BlankNodeContent::Named(id) => id, BlankNodeContent::Named(id) => id,
BlankNodeContent::Anonymous { str, .. } => { BlankNodeContent::Anonymous { str, .. } => str.as_str().to_owned(),
let len = str.iter().position(|x| x == &0).unwrap_or(32);
str::from_utf8(&str[..len]).unwrap().to_owned()
}
} }
} }
/// Returns the internal numerical ID of this blank node, if it exists pub fn as_ref(&self) -> BlankNodeRef<'_> {
pub(crate) fn id(&self) -> Option<u128> { BlankNodeRef(match &self.0 {
match self.0 { BlankNodeContent::Named(id) => BlankNodeRefContent::Named(id.as_str()),
BlankNodeContent::Named(_) => None, BlankNodeContent::Anonymous { id, str } => BlankNodeRefContent::Anonymous {
BlankNodeContent::Anonymous { id, .. } => Some(id), id: *id,
} str: str.as_str(),
},
})
} }
} }
impl fmt::Display for BlankNode { impl fmt::Display for BlankNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::BlankNode::from(self).fmt(f) self.as_ref().fmt(f)
} }
} }
@ -118,12 +110,140 @@ impl Default for BlankNode {
} }
} }
impl<'a> From<&'a BlankNode> for rio::BlankNode<'a> { /// A borrowed RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node).
///
/// The common way to create a new blank node is to use the `BlankNode::default` trait method.
///
/// It is also possible to create a blank node from a blank node identifier using the `BlankNodeRef::new` method.
/// The blank node identifier must be valid according to N-Triples, Turtle and SPARQL grammars.
///
/// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation:
/// ```
/// use oxigraph::model::BlankNodeRef;
///
/// assert_eq!(
/// "_:a122",
/// BlankNodeRef::new("a122")?.to_string()
/// );
/// # Result::<_,oxigraph::model::BlankNodeIdParseError>::Ok(())
/// ```
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub struct BlankNodeRef<'a>(BlankNodeRefContent<'a>);
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
enum BlankNodeRefContent<'a> {
Named(&'a str),
Anonymous { id: u128, str: &'a str },
}
impl<'a> BlankNodeRef<'a> {
/// Creates a blank node from a unique identifier.
///
/// The blank node identifier must be valid according to N-Triples, Turtle and SPARQL grammars.
///
/// In most cases, it is much more convenient to create a blank node using `BlankNode::default()`.
/// `BlankNode::default()` creates a random ID that could be easily inlined by Oxigraph stores.
pub fn new(id: &'a str) -> Result<Self, BlankNodeIdParseError> {
validate_blank_node_identifier(id)?;
Ok(Self::new_unchecked(id))
}
/// Creates a blank node from a unique identifier without validation.
///
/// It is the caller's responsibility to ensure that `id` is a valid blank node identifier
/// according to N-Triples, Turtle and SPARQL grammars.
///
/// Except if you really know what you do, you should use [`new`](#method.new).
pub fn new_unchecked(id: &'a str) -> Self {
if let Some(numerical_id) = to_integer_id(id) {
Self(BlankNodeRefContent::Anonymous {
id: numerical_id,
str: id,
})
} else {
Self(BlankNodeRefContent::Named(id))
}
}
/// Returns the underlying ID of this blank node
pub fn as_str(self) -> &'a str {
match self.0 {
BlankNodeRefContent::Named(id) => id,
BlankNodeRefContent::Anonymous { str, .. } => str,
}
}
/// Returns the internal numerical ID of this blank node, if it exists
pub(crate) fn id(&self) -> Option<u128> {
match self.0 {
BlankNodeRefContent::Named(_) => None,
BlankNodeRefContent::Anonymous { id, .. } => Some(id),
}
}
pub fn into_owned(self) -> BlankNode {
BlankNode(match self.0 {
BlankNodeRefContent::Named(id) => BlankNodeContent::Named(id.to_owned()),
BlankNodeRefContent::Anonymous { id, .. } => BlankNodeContent::Anonymous {
id,
str: IdStr::new(id),
},
})
}
}
impl fmt::Display for BlankNodeRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::BlankNode::from(*self).fmt(f)
}
}
impl<'a> From<&'a BlankNode> for BlankNodeRef<'a> {
fn from(node: &'a BlankNode) -> Self { fn from(node: &'a BlankNode) -> Self {
node.as_ref()
}
}
impl<'a> From<BlankNodeRef<'a>> for BlankNode {
fn from(node: BlankNodeRef<'a>) -> Self {
node.into_owned()
}
}
impl<'a> From<BlankNodeRef<'a>> for rio::BlankNode<'a> {
fn from(node: BlankNodeRef<'a>) -> Self {
rio::BlankNode { id: node.as_str() } rio::BlankNode { id: node.as_str() }
} }
} }
impl PartialEq<BlankNode> for BlankNodeRef<'_> {
fn eq(&self, other: &BlankNode) -> bool {
*self == other.as_ref()
}
}
impl PartialEq<BlankNodeRef<'_>> for BlankNode {
fn eq(&self, other: &BlankNodeRef<'_>) -> bool {
self.as_ref() == *other
}
}
#[derive(PartialEq, Eq, Debug, Clone, Hash)]
struct IdStr([u8; 32]);
impl IdStr {
fn new(id: u128) -> Self {
let mut str = [0; 32];
write!(&mut str[..], "{:x}", id).unwrap();
Self(str)
}
fn as_str(&self) -> &str {
let len = self.0.iter().position(|x| x == &0).unwrap_or(32);
str::from_utf8(&self.0[..len]).unwrap()
}
}
fn validate_blank_node_identifier(id: &str) -> Result<(), BlankNodeIdParseError> { fn validate_blank_node_identifier(id: &str) -> Result<(), BlankNodeIdParseError> {
let mut chars = id.chars(); let mut chars = id.chars();
let front = chars.next().ok_or(BlankNodeIdParseError {})?; let front = chars.next().ok_or(BlankNodeIdParseError {})?;
@ -183,6 +303,25 @@ fn validate_blank_node_identifier(id: &str) -> Result<(), BlankNodeIdParseError>
} }
} }
fn to_integer_id(id: &str) -> Option<u128> {
let digits = id.as_bytes();
let mut value: u128 = 0;
if let None | Some(b'0') = digits.first() {
return None; // No empty string or leading zeros
}
for digit in digits {
value = value.checked_mul(16)?.checked_add(
match *digit {
b'0'..=b'9' => digit - b'0',
b'a'..=b'f' => digit - b'a' + 10,
_ => return None,
}
.into(),
)?;
}
Some(value)
}
/// An error raised during `BlankNode` validation. /// An error raised during `BlankNode` validation.
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[derive(Debug)] #[derive(Debug)]
@ -234,4 +373,16 @@ mod test {
BlankNode::new_from_unique_id(0x100a_u128) BlankNode::new_from_unique_id(0x100a_u128)
); );
} }
#[test]
fn test_equals() {
assert_eq!(
BlankNode::new("100a").unwrap(),
BlankNodeRef::new("100a").unwrap()
);
assert_eq!(
BlankNode::new("zzz").unwrap(),
BlankNodeRef::new("zzz").unwrap()
);
}
} }

@ -2,13 +2,14 @@ use crate::model::named_node::NamedNode;
use crate::model::vocab::rdf; use crate::model::vocab::rdf;
use crate::model::vocab::xsd; use crate::model::vocab::xsd;
use crate::model::xsd::*; use crate::model::xsd::*;
use crate::model::NamedNodeRef;
use oxilangtag::{LanguageTag, LanguageTagParseError}; use oxilangtag::{LanguageTag, LanguageTagParseError};
use rio_api::model as rio; use rio_api::model as rio;
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt; use std::fmt;
use std::option::Option; use std::option::Option;
/// An RDF [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) /// An owned RDF [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal)
/// ///
/// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation: /// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation:
/// ``` /// ```
@ -23,7 +24,7 @@ use std::option::Option;
/// ///
/// assert_eq!( /// assert_eq!(
/// "\"1999-01-01\"^^<http://www.w3.org/2001/XMLSchema#date>", /// "\"1999-01-01\"^^<http://www.w3.org/2001/XMLSchema#date>",
/// Literal::new_typed_literal("1999-01-01", xsd::DATE.clone()).to_string() /// Literal::new_typed_literal("1999-01-01", xsd::DATE).to_string()
/// ); /// );
/// ///
/// assert_eq!( /// assert_eq!(
@ -52,7 +53,7 @@ impl Literal {
pub fn new_typed_literal(value: impl Into<String>, datatype: impl Into<NamedNode>) -> Self { pub fn new_typed_literal(value: impl Into<String>, datatype: impl Into<NamedNode>) -> Self {
let value = value.into(); let value = value.into();
let datatype = datatype.into(); let datatype = datatype.into();
Literal(if datatype == *xsd::STRING { Literal(if datatype == xsd::STRING {
LiteralContent::String(value) LiteralContent::String(value)
} else { } else {
LiteralContent::TypedLiteral { value, datatype } LiteralContent::TypedLiteral { value, datatype }
@ -66,10 +67,10 @@ impl Literal {
) -> Result<Self, LanguageTagParseError> { ) -> Result<Self, LanguageTagParseError> {
let mut language = language.into(); let mut language = language.into();
language.make_ascii_lowercase(); language.make_ascii_lowercase();
Ok(Literal(LiteralContent::LanguageTaggedString { Ok(Self::new_language_tagged_literal_unchecked(
value: value.into(), value,
language: LanguageTag::parse(language)?.into_inner(), LanguageTag::parse(language)?.into_inner(),
})) ))
} }
/// Builds an RDF [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) /// Builds an RDF [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string)
@ -92,11 +93,7 @@ impl Literal {
/// The literal [lexical form](https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form) /// The literal [lexical form](https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form)
pub fn value(&self) -> &str { pub fn value(&self) -> &str {
match &self.0 { self.as_ref().value()
LiteralContent::String(value)
| LiteralContent::LanguageTaggedString { value, .. }
| LiteralContent::TypedLiteral { value, .. } => value,
}
} }
/// The literal [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) if it is a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string). /// The literal [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) if it is a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string).
@ -104,33 +101,36 @@ impl Literal {
/// Language tags are defined by the [BCP47](https://tools.ietf.org/html/bcp47). /// Language tags are defined by the [BCP47](https://tools.ietf.org/html/bcp47).
/// They are normalized to lowercase by this implementation. /// They are normalized to lowercase by this implementation.
pub fn language(&self) -> Option<&str> { pub fn language(&self) -> Option<&str> {
match &self.0 { self.as_ref().language()
LiteralContent::LanguageTaggedString { language, .. } => Some(language),
_ => None,
}
} }
/// The literal [datatype](https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri). /// The literal [datatype](https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri).
/// ///
/// The datatype of [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) is always [rdf:langString](http://www.w3.org/1999/02/22-rdf-syntax-ns#langString). /// The datatype of [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) is always [rdf:langString](http://www.w3.org/1999/02/22-rdf-syntax-ns#langString).
/// The datatype of [simple literals](https://www.w3.org/TR/rdf11-concepts/#dfn-simple-literal) is [xsd:string](http://www.w3.org/2001/XMLSchema#string). /// The datatype of [simple literals](https://www.w3.org/TR/rdf11-concepts/#dfn-simple-literal) is [xsd:string](http://www.w3.org/2001/XMLSchema#string).
pub fn datatype(&self) -> &NamedNode { pub fn datatype(&self) -> NamedNodeRef<'_> {
match &self.0 { self.as_ref().datatype()
LiteralContent::String(_) => &xsd::STRING,
LiteralContent::LanguageTaggedString { .. } => &rdf::LANG_STRING,
LiteralContent::TypedLiteral { datatype, .. } => datatype,
}
} }
/// Checks if this lieteral could be seen as an RDF 1.0 [plain literal](https://www.w3.org/TR/rdf-concepts/#dfn-plain-literal). /// Checks if this literal could be seen as an RDF 1.0 [plain literal](https://www.w3.org/TR/rdf-concepts/#dfn-plain-literal).
/// ///
/// It returns true if the literal is a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) /// It returns true if the literal is a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string)
/// or has the datatype [xsd:string](http://www.w3.org/2001/XMLSchema#string). /// or has the datatype [xsd:string](http://www.w3.org/2001/XMLSchema#string).
pub fn is_plain(&self) -> bool { pub fn is_plain(&self) -> bool {
match self.0 { self.as_ref().is_plain()
LiteralContent::String(_) | LiteralContent::LanguageTaggedString { .. } => true,
_ => false,
} }
pub fn as_ref(&self) -> LiteralRef<'_> {
LiteralRef(match &self.0 {
LiteralContent::String(value) => LiteralRefContent::String(value),
LiteralContent::LanguageTaggedString { value, language } => {
LiteralRefContent::LanguageTaggedString { value, language }
}
LiteralContent::TypedLiteral { value, datatype } => LiteralRefContent::TypedLiteral {
value,
datatype: datatype.as_ref(),
},
})
} }
/// Extract components from this literal /// Extract components from this literal
@ -147,7 +147,7 @@ impl Literal {
impl fmt::Display for Literal { impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::Literal::from(self).fmt(f) self.as_ref().fmt(f)
} }
} }
@ -173,7 +173,7 @@ impl From<bool> for Literal {
fn from(value: bool) -> Self { fn from(value: bool) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::BOOLEAN.clone(), datatype: xsd::BOOLEAN.into(),
}) })
} }
} }
@ -182,7 +182,7 @@ impl From<i128> for Literal {
fn from(value: i128) -> Self { fn from(value: i128) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::INTEGER.clone(), datatype: xsd::INTEGER.into(),
}) })
} }
} }
@ -191,7 +191,7 @@ impl From<i64> for Literal {
fn from(value: i64) -> Self { fn from(value: i64) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::INTEGER.clone(), datatype: xsd::INTEGER.into(),
}) })
} }
} }
@ -200,7 +200,7 @@ impl From<i32> for Literal {
fn from(value: i32) -> Self { fn from(value: i32) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::INTEGER.clone(), datatype: xsd::INTEGER.into(),
}) })
} }
} }
@ -209,7 +209,7 @@ impl From<i16> for Literal {
fn from(value: i16) -> Self { fn from(value: i16) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::INTEGER.clone(), datatype: xsd::INTEGER.into(),
}) })
} }
} }
@ -218,7 +218,7 @@ impl From<u64> for Literal {
fn from(value: u64) -> Self { fn from(value: u64) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::INTEGER.clone(), datatype: xsd::INTEGER.into(),
}) })
} }
} }
@ -227,7 +227,7 @@ impl From<u32> for Literal {
fn from(value: u32) -> Self { fn from(value: u32) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::INTEGER.clone(), datatype: xsd::INTEGER.into(),
}) })
} }
} }
@ -236,7 +236,7 @@ impl From<u16> for Literal {
fn from(value: u16) -> Self { fn from(value: u16) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::INTEGER.clone(), datatype: xsd::INTEGER.into(),
}) })
} }
} }
@ -245,7 +245,7 @@ impl From<f32> for Literal {
fn from(value: f32) -> Self { fn from(value: f32) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::FLOAT.clone(), datatype: xsd::FLOAT.into(),
}) })
} }
} }
@ -254,7 +254,7 @@ impl From<f64> for Literal {
fn from(value: f64) -> Self { fn from(value: f64) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::DOUBLE.clone(), datatype: xsd::DOUBLE.into(),
}) })
} }
} }
@ -263,7 +263,7 @@ impl From<Decimal> for Literal {
fn from(value: Decimal) -> Self { fn from(value: Decimal) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::DECIMAL.clone(), datatype: xsd::DECIMAL.into(),
}) })
} }
} }
@ -272,7 +272,7 @@ impl From<Date> for Literal {
fn from(value: Date) -> Self { fn from(value: Date) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::DATE.clone(), datatype: xsd::DATE.into(),
}) })
} }
} }
@ -281,7 +281,7 @@ impl From<Time> for Literal {
fn from(value: Time) -> Self { fn from(value: Time) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::TIME.clone(), datatype: xsd::TIME.into(),
}) })
} }
} }
@ -290,7 +290,7 @@ impl From<DateTime> for Literal {
fn from(value: DateTime) -> Self { fn from(value: DateTime) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::DATE_TIME.clone(), datatype: xsd::DATE_TIME.into(),
}) })
} }
} }
@ -299,7 +299,7 @@ impl From<Duration> for Literal {
fn from(value: Duration) -> Self { fn from(value: Duration) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::DURATION.clone(), datatype: xsd::DURATION.into(),
}) })
} }
} }
@ -308,7 +308,7 @@ impl From<YearMonthDuration> for Literal {
fn from(value: YearMonthDuration) -> Self { fn from(value: YearMonthDuration) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::YEAR_MONTH_DURATION.clone(), datatype: xsd::YEAR_MONTH_DURATION.into(),
}) })
} }
} }
@ -316,32 +316,196 @@ impl From<DayTimeDuration> for Literal {
fn from(value: DayTimeDuration) -> Self { fn from(value: DayTimeDuration) -> Self {
Literal(LiteralContent::TypedLiteral { Literal(LiteralContent::TypedLiteral {
value: value.to_string(), value: value.to_string(),
datatype: xsd::DAY_TIME_DURATION.clone(), datatype: xsd::DAY_TIME_DURATION.into(),
}) })
} }
} }
impl<'a> From<&'a Literal> for rio::Literal<'a> { /// A borrowed RDF [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal)
fn from(literal: &'a Literal) -> Self { ///
if literal.is_plain() { /// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation:
literal.language().map_or_else( /// ```
|| rio::Literal::Simple { /// # use oxilangtag::LanguageTagParseError;
value: literal.value(), /// use oxigraph::model::LiteralRef;
/// use oxigraph::model::vocab::xsd;
///
/// assert_eq!(
/// "\"foo\\nbar\"",
/// LiteralRef::new_simple_literal("foo\nbar").to_string()
/// );
///
/// assert_eq!(
/// "\"1999-01-01\"^^<http://www.w3.org/2001/XMLSchema#date>",
/// LiteralRef::new_typed_literal("1999-01-01", xsd::DATE).to_string()
/// );
/// # Result::<(), LanguageTagParseError>::Ok(())
/// ```
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub struct LiteralRef<'a>(LiteralRefContent<'a>);
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
enum LiteralRefContent<'a> {
String(&'a str),
LanguageTaggedString {
value: &'a str,
language: &'a str,
}, },
|lang| rio::Literal::LanguageTaggedString { TypedLiteral {
value: literal.value(), value: &'a str,
language: lang, datatype: NamedNodeRef<'a>,
}, },
) }
impl<'a> LiteralRef<'a> {
/// Builds an RDF [simple literal](https://www.w3.org/TR/rdf11-concepts/#dfn-simple-literal)
pub fn new_simple_literal(value: &'a str) -> Self {
LiteralRef(LiteralRefContent::String(value))
}
/// Builds an RDF [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal) with a [datatype](https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri)
pub fn new_typed_literal(value: &'a str, datatype: impl Into<NamedNodeRef<'a>>) -> Self {
let datatype = datatype.into();
LiteralRef(if datatype == xsd::STRING {
LiteralRefContent::String(value)
} else { } else {
rio::Literal::Typed { LiteralRefContent::TypedLiteral { value, datatype }
value: literal.value(), })
datatype: literal.datatype().into(),
} }
/// Builds an RDF [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string)
///
/// It is the responsibility of the caller to check that `language`
/// is valid [BCP47](https://tools.ietf.org/html/bcp47) language tag,
/// and is lowercase.
///
/// Except if you really know what you do,
/// you should use [`new_language_tagged_literal`](#method.new_language_tagged_literal).
pub fn new_language_tagged_literal_unchecked(value: &'a str, language: &'a str) -> Self {
LiteralRef(LiteralRefContent::LanguageTaggedString { value, language })
}
/// The literal [lexical form](https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form)
pub fn value(self) -> &'a str {
match self.0 {
LiteralRefContent::String(value)
| LiteralRefContent::LanguageTaggedString { value, .. }
| LiteralRefContent::TypedLiteral { value, .. } => value,
}
}
/// The literal [language tag](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag) if it is a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string).
///
/// Language tags are defined by the [BCP47](https://tools.ietf.org/html/bcp47).
/// They are normalized to lowercase by this implementation.
pub fn language(self) -> Option<&'a str> {
match self.0 {
LiteralRefContent::LanguageTaggedString { language, .. } => Some(language),
_ => None,
}
}
/// The literal [datatype](https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri).
///
/// The datatype of [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string) is always [rdf:langString](http://www.w3.org/1999/02/22-rdf-syntax-ns#langString).
/// The datatype of [simple literals](https://www.w3.org/TR/rdf11-concepts/#dfn-simple-literal) is [xsd:string](http://www.w3.org/2001/XMLSchema#string).
pub fn datatype(self) -> NamedNodeRef<'a> {
match self.0 {
LiteralRefContent::String(_) => xsd::STRING,
LiteralRefContent::LanguageTaggedString { .. } => rdf::LANG_STRING,
LiteralRefContent::TypedLiteral { datatype, .. } => datatype,
}
}
/// Checks if this literal could be seen as an RDF 1.0 [plain literal](https://www.w3.org/TR/rdf-concepts/#dfn-plain-literal).
///
/// It returns true if the literal is a [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string)
/// or has the datatype [xsd:string](http://www.w3.org/2001/XMLSchema#string).
pub fn is_plain(self) -> bool {
match self.0 {
LiteralRefContent::String(_) | LiteralRefContent::LanguageTaggedString { .. } => true,
_ => false,
}
}
pub fn into_owned(self) -> Literal {
Literal(match self.0 {
LiteralRefContent::String(value) => LiteralContent::String(value.to_owned()),
LiteralRefContent::LanguageTaggedString { value, language } => {
LiteralContent::LanguageTaggedString {
value: value.to_owned(),
language: language.to_owned(),
}
}
LiteralRefContent::TypedLiteral { value, datatype } => LiteralContent::TypedLiteral {
value: value.to_owned(),
datatype: datatype.into_owned(),
},
})
}
/// Extract components from this literal
pub fn destruct(self) -> (&'a str, Option<NamedNodeRef<'a>>, Option<&'a str>) {
match self.0 {
LiteralRefContent::String(s) => (s, None, None),
LiteralRefContent::LanguageTaggedString { value, language } => {
(value, None, Some(language))
}
LiteralRefContent::TypedLiteral { value, datatype } => (value, Some(datatype), None),
}
}
}
impl fmt::Display for LiteralRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::Literal::from(*self).fmt(f)
}
}
impl<'a> From<&'a Literal> for LiteralRef<'a> {
fn from(node: &'a Literal) -> Self {
node.as_ref()
}
}
impl<'a> From<LiteralRef<'a>> for Literal {
fn from(node: LiteralRef<'a>) -> Self {
node.into_owned()
}
}
impl<'a> From<LiteralRef<'a>> for rio::Literal<'a> {
fn from(literal: LiteralRef<'a>) -> Self {
match literal.0 {
LiteralRefContent::String(value) => rio::Literal::Simple { value },
LiteralRefContent::LanguageTaggedString { value, language } => {
rio::Literal::LanguageTaggedString { value, language }
}
LiteralRefContent::TypedLiteral { value, datatype } => rio::Literal::Typed {
value,
datatype: datatype.into(),
},
} }
} }
} }
impl<'a> From<&'a str> for LiteralRef<'a> {
fn from(value: &'a str) -> Self {
LiteralRef(LiteralRefContent::String(value))
}
}
impl PartialEq<Literal> for LiteralRef<'_> {
fn eq(&self, other: &Literal) -> bool {
*self == other.as_ref()
}
}
impl PartialEq<LiteralRef<'_>> for Literal {
fn eq(&self, other: &LiteralRef<'_>) -> bool {
self.as_ref() == *other
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@ -350,7 +514,19 @@ mod test {
fn test_simple_literal_equality() { fn test_simple_literal_equality() {
assert_eq!( assert_eq!(
Literal::new_simple_literal("foo"), Literal::new_simple_literal("foo"),
Literal::new_typed_literal("foo", xsd::STRING.clone()) Literal::new_typed_literal("foo", xsd::STRING)
) );
assert_eq!(
Literal::new_simple_literal("foo"),
LiteralRef::new_typed_literal("foo", xsd::STRING)
);
assert_eq!(
LiteralRef::new_simple_literal("foo"),
Literal::new_typed_literal("foo", xsd::STRING)
);
assert_eq!(
LiteralRef::new_simple_literal("foo"),
LiteralRef::new_typed_literal("foo", xsd::STRING)
);
} }
} }

@ -9,9 +9,12 @@ mod triple;
pub mod vocab; pub mod vocab;
pub(crate) mod xsd; pub(crate) mod xsd;
pub use crate::model::blank_node::{BlankNode, BlankNodeIdParseError}; pub use crate::model::blank_node::{BlankNode, BlankNodeIdParseError, BlankNodeRef};
pub use crate::model::literal::Literal; pub use crate::model::literal::{Literal, LiteralRef};
pub use crate::model::named_node::NamedNode; pub use crate::model::named_node::{NamedNode, NamedNodeRef};
pub use crate::model::triple::{GraphName, NamedOrBlankNode, Quad, Term, Triple}; pub use crate::model::triple::{
GraphName, GraphNameRef, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, QuadRef, Term, TermRef,
Triple, TripleRef,
};
pub use oxilangtag::LanguageTagParseError; pub use oxilangtag::LanguageTagParseError;
pub use oxiri::IriParseError; pub use oxiri::IriParseError;

@ -2,7 +2,7 @@ use oxiri::{Iri, IriParseError};
use rio_api::model as rio; use rio_api::model as rio;
use std::fmt; use std::fmt;
/// An RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) /// An owned RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri)
/// ///
/// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation: /// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation:
/// ``` /// ```
@ -50,17 +50,15 @@ impl NamedNode {
pub fn into_string(self) -> String { pub fn into_string(self) -> String {
self.iri self.iri
} }
}
impl fmt::Display for NamedNode { pub fn as_ref(&self) -> NamedNodeRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { NamedNodeRef::new_unchecked(&self.iri)
rio::NamedNode::from(self).fmt(f)
} }
} }
impl<'a> From<&'a NamedNode> for rio::NamedNode<'a> { impl fmt::Display for NamedNode {
fn from(node: &'a NamedNode) -> Self { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::NamedNode { iri: node.as_str() } self.as_ref().fmt(f)
} }
} }
@ -87,3 +85,108 @@ impl PartialEq<NamedNode> for &str {
*self == other *self == other
} }
} }
/// A borrowed RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri)
///
/// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation:
/// ```
/// use oxigraph::model::NamedNodeRef;
///
/// assert_eq!(
/// "<http://example.com/foo>",
/// NamedNodeRef::new("http://example.com/foo")?.to_string()
/// );
/// # Result::<_,oxigraph::model::IriParseError>::Ok(())
/// ```
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
pub struct NamedNodeRef<'a> {
iri: &'a str,
}
impl<'a> NamedNodeRef<'a> {
/// Builds and validate an RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri)
pub fn new(iri: &'a str) -> Result<Self, IriParseError> {
Ok(Self::new_from_iri(Iri::parse(iri)?))
}
pub(crate) fn new_from_iri(iri: Iri<&'a str>) -> Self {
Self::new_unchecked(iri.into_inner())
}
/// Builds an RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) from a string.
///
/// It is the caller's responsibility to ensure that `iri` is a valid IRI.
///
/// Except if you really know what you do, you should use [`parse`](#method.parse).
pub const fn new_unchecked(iri: &'a str) -> Self {
Self { iri }
}
pub const fn as_str(self) -> &'a str {
self.iri
}
pub fn into_owned(self) -> NamedNode {
NamedNode::new_unchecked(self.iri)
}
}
impl fmt::Display for NamedNodeRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::NamedNode::from(*self).fmt(f)
}
}
impl From<NamedNodeRef<'_>> for NamedNode {
fn from(node: NamedNodeRef<'_>) -> Self {
node.into_owned()
}
}
impl<'a> From<&'a NamedNode> for NamedNodeRef<'a> {
fn from(node: &'a NamedNode) -> Self {
node.as_ref()
}
}
impl<'a> From<NamedNodeRef<'a>> for rio::NamedNode<'a> {
fn from(node: NamedNodeRef<'a>) -> Self {
rio::NamedNode { iri: node.as_str() }
}
}
impl PartialEq<NamedNode> for NamedNodeRef<'_> {
fn eq(&self, other: &NamedNode) -> bool {
self.as_str() == other.as_str()
}
}
impl PartialEq<NamedNodeRef<'_>> for NamedNode {
fn eq(&self, other: &NamedNodeRef<'_>) -> bool {
self.as_str() == other.as_str()
}
}
impl PartialEq<str> for NamedNodeRef<'_> {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<NamedNodeRef<'_>> for str {
fn eq(&self, other: &NamedNodeRef<'_>) -> bool {
self == other.as_str()
}
}
impl PartialEq<&str> for NamedNodeRef<'_> {
fn eq(&self, other: &&str) -> bool {
self == *other
}
}
impl PartialEq<NamedNodeRef<'_>> for &str {
fn eq(&self, other: &NamedNodeRef<'_>) -> bool {
*self == other
}
}

@ -1,10 +1,11 @@
use crate::model::blank_node::BlankNode; use crate::model::blank_node::BlankNode;
use crate::model::literal::Literal; use crate::model::literal::Literal;
use crate::model::named_node::NamedNode; use crate::model::named_node::NamedNode;
use crate::model::{BlankNodeRef, LiteralRef, NamedNodeRef};
use rio_api::model as rio; use rio_api::model as rio;
use std::fmt; use std::fmt;
/// The union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). /// The owned union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node).
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum NamedOrBlankNode { pub enum NamedOrBlankNode {
NamedNode(NamedNode), NamedNode(NamedNode),
@ -13,51 +14,136 @@ pub enum NamedOrBlankNode {
impl NamedOrBlankNode { impl NamedOrBlankNode {
pub fn is_named_node(&self) -> bool { pub fn is_named_node(&self) -> bool {
match self { self.as_ref().is_named_node()
NamedOrBlankNode::NamedNode(_) => true,
NamedOrBlankNode::BlankNode(_) => false,
}
} }
pub fn is_blank_node(&self) -> bool { pub fn is_blank_node(&self) -> bool {
self.as_ref().is_blank_node()
}
pub fn as_ref(&self) -> NamedOrBlankNodeRef<'_> {
match self { match self {
NamedOrBlankNode::NamedNode(_) => false, Self::NamedNode(node) => NamedOrBlankNodeRef::NamedNode(node.as_ref()),
NamedOrBlankNode::BlankNode(_) => true, Self::BlankNode(node) => NamedOrBlankNodeRef::BlankNode(node.as_ref()),
} }
} }
} }
impl fmt::Display for NamedOrBlankNode { impl fmt::Display for NamedOrBlankNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { self.as_ref().fmt(f)
NamedOrBlankNode::NamedNode(node) => node.fmt(f),
NamedOrBlankNode::BlankNode(node) => node.fmt(f),
}
} }
} }
impl From<NamedNode> for NamedOrBlankNode { impl From<NamedNode> for NamedOrBlankNode {
fn from(node: NamedNode) -> Self { fn from(node: NamedNode) -> Self {
NamedOrBlankNode::NamedNode(node) Self::NamedNode(node)
}
}
impl From<NamedNodeRef<'_>> for NamedOrBlankNode {
fn from(node: NamedNodeRef<'_>) -> Self {
node.into_owned().into()
} }
} }
impl From<BlankNode> for NamedOrBlankNode { impl From<BlankNode> for NamedOrBlankNode {
fn from(node: BlankNode) -> Self { fn from(node: BlankNode) -> Self {
NamedOrBlankNode::BlankNode(node) Self::BlankNode(node)
}
}
impl From<BlankNodeRef<'_>> for NamedOrBlankNode {
fn from(node: BlankNodeRef<'_>) -> Self {
node.into_owned().into()
}
}
/// The borrowed union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node).
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub enum NamedOrBlankNodeRef<'a> {
NamedNode(NamedNodeRef<'a>),
BlankNode(BlankNodeRef<'a>),
}
impl<'a> NamedOrBlankNodeRef<'a> {
pub fn is_named_node(&self) -> bool {
match self {
Self::NamedNode(_) => true,
Self::BlankNode(_) => false,
}
}
pub fn is_blank_node(&self) -> bool {
match self {
Self::NamedNode(_) => false,
Self::BlankNode(_) => true,
}
}
pub fn into_owned(self) -> NamedOrBlankNode {
match self {
Self::NamedNode(node) => NamedOrBlankNode::NamedNode(node.into_owned()),
Self::BlankNode(node) => NamedOrBlankNode::BlankNode(node.into_owned()),
}
} }
} }
impl<'a> From<&'a NamedOrBlankNode> for rio::NamedOrBlankNode<'a> { impl fmt::Display for NamedOrBlankNodeRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::BlankNode(node) => node.fmt(f),
}
}
}
impl<'a> From<NamedNodeRef<'a>> for NamedOrBlankNodeRef<'a> {
fn from(node: NamedNodeRef<'a>) -> Self {
Self::NamedNode(node)
}
}
impl<'a> From<&'a NamedNode> for NamedOrBlankNodeRef<'a> {
fn from(node: &'a NamedNode) -> Self {
node.as_ref().into()
}
}
impl<'a> From<BlankNodeRef<'a>> for NamedOrBlankNodeRef<'a> {
fn from(node: BlankNodeRef<'a>) -> Self {
Self::BlankNode(node)
}
}
impl<'a> From<&'a BlankNode> for NamedOrBlankNodeRef<'a> {
fn from(node: &'a BlankNode) -> Self {
node.as_ref().into()
}
}
impl<'a> From<&'a NamedOrBlankNode> for NamedOrBlankNodeRef<'a> {
fn from(node: &'a NamedOrBlankNode) -> Self { fn from(node: &'a NamedOrBlankNode) -> Self {
node.as_ref()
}
}
impl<'a> From<NamedOrBlankNodeRef<'a>> for NamedOrBlankNode {
fn from(node: NamedOrBlankNodeRef<'a>) -> Self {
node.into_owned()
}
}
impl<'a> From<NamedOrBlankNodeRef<'a>> for rio::NamedOrBlankNode<'a> {
fn from(node: NamedOrBlankNodeRef<'a>) -> Self {
match node { match node {
NamedOrBlankNode::NamedNode(node) => rio::NamedNode::from(node).into(), NamedOrBlankNodeRef::NamedNode(node) => rio::NamedNode::from(node).into(),
NamedOrBlankNode::BlankNode(node) => rio::BlankNode::from(node).into(), NamedOrBlankNodeRef::BlankNode(node) => rio::BlankNode::from(node).into(),
} }
} }
} }
/// An RDF [term](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term) /// An owned RDF [term](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term)
/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal). /// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal).
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum Term { pub enum Term {
@ -68,75 +154,207 @@ pub enum Term {
impl Term { impl Term {
pub fn is_named_node(&self) -> bool { pub fn is_named_node(&self) -> bool {
match self { self.as_ref().is_named_node()
Term::NamedNode(_) => true,
_ => false,
}
} }
pub fn is_blank_node(&self) -> bool { pub fn is_blank_node(&self) -> bool {
match self { self.as_ref().is_blank_node()
Term::BlankNode(_) => true,
_ => false,
}
} }
pub fn is_literal(&self) -> bool { pub fn is_literal(&self) -> bool {
self.as_ref().is_literal()
}
pub fn as_ref(&self) -> TermRef<'_> {
match self { match self {
Term::Literal(_) => true, Self::NamedNode(node) => TermRef::NamedNode(node.as_ref()),
_ => false, Self::BlankNode(node) => TermRef::BlankNode(node.as_ref()),
Self::Literal(literal) => TermRef::Literal(literal.as_ref()),
} }
} }
} }
impl fmt::Display for Term { impl fmt::Display for Term {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { self.as_ref().fmt(f)
Term::NamedNode(node) => node.fmt(f),
Term::BlankNode(node) => node.fmt(f),
Term::Literal(literal) => literal.fmt(f),
}
} }
} }
impl From<NamedNode> for Term { impl From<NamedNode> for Term {
fn from(node: NamedNode) -> Self { fn from(node: NamedNode) -> Self {
Term::NamedNode(node) Self::NamedNode(node)
}
}
impl From<NamedNodeRef<'_>> for Term {
fn from(node: NamedNodeRef<'_>) -> Self {
node.into_owned().into()
} }
} }
impl From<BlankNode> for Term { impl From<BlankNode> for Term {
fn from(node: BlankNode) -> Self { fn from(node: BlankNode) -> Self {
Term::BlankNode(node) Self::BlankNode(node)
}
}
impl From<BlankNodeRef<'_>> for Term {
fn from(node: BlankNodeRef<'_>) -> Self {
node.into_owned().into()
} }
} }
impl From<Literal> for Term { impl From<Literal> for Term {
fn from(literal: Literal) -> Self { fn from(literal: Literal) -> Self {
Term::Literal(literal) Self::Literal(literal)
}
}
impl From<LiteralRef<'_>> for Term {
fn from(literal: LiteralRef<'_>) -> Self {
literal.into_owned().into()
} }
} }
impl From<NamedOrBlankNode> for Term { impl From<NamedOrBlankNode> for Term {
fn from(resource: NamedOrBlankNode) -> Self { fn from(node: NamedOrBlankNode) -> Self {
match resource { match node {
NamedOrBlankNode::NamedNode(node) => node.into(), NamedOrBlankNode::NamedNode(node) => node.into(),
NamedOrBlankNode::BlankNode(node) => node.into(), NamedOrBlankNode::BlankNode(node) => node.into(),
} }
} }
} }
impl<'a> From<&'a Term> for rio::Term<'a> { impl From<NamedOrBlankNodeRef<'_>> for Term {
fn from(node: NamedOrBlankNodeRef<'_>) -> Self {
node.into_owned().into()
}
}
/// A borrowed RDF [term](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-term)
/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and [literals](https://www.w3.org/TR/rdf11-concepts/#dfn-literal).
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub enum TermRef<'a> {
NamedNode(NamedNodeRef<'a>),
BlankNode(BlankNodeRef<'a>),
Literal(LiteralRef<'a>),
}
impl<'a> TermRef<'a> {
pub fn is_named_node(&self) -> bool {
match self {
Self::NamedNode(_) => true,
_ => false,
}
}
pub fn is_blank_node(&self) -> bool {
match self {
Self::BlankNode(_) => true,
_ => false,
}
}
pub fn is_literal(&self) -> bool {
match self {
Self::Literal(_) => true,
_ => false,
}
}
pub fn into_owned(self) -> Term {
match self {
Self::NamedNode(node) => Term::NamedNode(node.into_owned()),
Self::BlankNode(node) => Term::BlankNode(node.into_owned()),
Self::Literal(literal) => Term::Literal(literal.into_owned()),
}
}
}
impl fmt::Display for TermRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::BlankNode(node) => node.fmt(f),
Self::Literal(node) => node.fmt(f),
}
}
}
impl<'a> From<NamedNodeRef<'a>> for TermRef<'a> {
fn from(node: NamedNodeRef<'a>) -> Self {
Self::NamedNode(node)
}
}
impl<'a> From<&'a NamedNode> for TermRef<'a> {
fn from(node: &'a NamedNode) -> Self {
node.as_ref().into()
}
}
impl<'a> From<BlankNodeRef<'a>> for TermRef<'a> {
fn from(node: BlankNodeRef<'a>) -> Self {
Self::BlankNode(node)
}
}
impl<'a> From<&'a BlankNode> for TermRef<'a> {
fn from(node: &'a BlankNode) -> Self {
node.as_ref().into()
}
}
impl<'a> From<LiteralRef<'a>> for TermRef<'a> {
fn from(literal: LiteralRef<'a>) -> Self {
Self::Literal(literal)
}
}
impl<'a> From<&'a Literal> for TermRef<'a> {
fn from(literal: &'a Literal) -> Self {
literal.as_ref().into()
}
}
impl<'a> From<NamedOrBlankNodeRef<'a>> for TermRef<'a> {
fn from(node: NamedOrBlankNodeRef<'a>) -> Self {
match node {
NamedOrBlankNodeRef::NamedNode(node) => node.into(),
NamedOrBlankNodeRef::BlankNode(node) => node.into(),
}
}
}
impl<'a> From<&'a NamedOrBlankNode> for TermRef<'a> {
fn from(node: &'a NamedOrBlankNode) -> Self {
node.as_ref().into()
}
}
impl<'a> From<&'a Term> for TermRef<'a> {
fn from(node: &'a Term) -> Self { fn from(node: &'a Term) -> Self {
node.as_ref()
}
}
impl<'a> From<TermRef<'a>> for Term {
fn from(node: TermRef<'a>) -> Self {
node.into_owned()
}
}
impl<'a> From<TermRef<'a>> for rio::Term<'a> {
fn from(node: TermRef<'a>) -> Self {
match node { match node {
Term::NamedNode(node) => rio::NamedNode::from(node).into(), TermRef::NamedNode(node) => rio::NamedNode::from(node).into(),
Term::BlankNode(node) => rio::BlankNode::from(node).into(), TermRef::BlankNode(node) => rio::BlankNode::from(node).into(),
Term::Literal(node) => rio::Literal::from(node).into(), TermRef::Literal(node) => rio::Literal::from(node).into(),
} }
} }
} }
/// A [RDF triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) /// An owned [RDF triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple)
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Triple { pub struct Triple {
/// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple /// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple
@ -202,25 +420,97 @@ impl Triple {
graph_name: graph_name.into(), graph_name: graph_name.into(),
} }
} }
pub fn as_ref(&self) -> TripleRef<'_> {
TripleRef {
subject: self.subject.as_ref(),
predicate: self.predicate.as_ref(),
object: self.object.as_ref(),
}
}
} }
impl fmt::Display for Triple { impl fmt::Display for Triple {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::Triple::from(self).fmt(f) self.as_ref().fmt(f)
}
}
/// A borrowed [RDF triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple)
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub struct TripleRef<'a> {
/// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple
pub subject: NamedOrBlankNodeRef<'a>,
/// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple
pub predicate: NamedNodeRef<'a>,
/// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple
pub object: TermRef<'a>,
}
impl<'a> TripleRef<'a> {
/// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple)
pub fn new(
subject: impl Into<NamedOrBlankNodeRef<'a>>,
predicate: impl Into<NamedNodeRef<'a>>,
object: impl Into<TermRef<'a>>,
) -> Self {
Self {
subject: subject.into(),
predicate: predicate.into(),
object: object.into(),
}
}
/// Encodes that this triple is in a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset)
pub fn in_graph(self, graph_name: impl Into<GraphNameRef<'a>>) -> QuadRef<'a> {
QuadRef {
subject: self.subject,
predicate: self.predicate,
object: self.object,
graph_name: graph_name.into(),
}
}
pub fn into_owned(self) -> Triple {
Triple {
subject: self.subject.into_owned(),
predicate: self.predicate.into_owned(),
object: self.object.into_owned(),
}
}
}
impl fmt::Display for TripleRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::Triple::from(*self).fmt(f)
}
}
impl<'a> From<&'a Triple> for TripleRef<'a> {
fn from(triple: &'a Triple) -> Self {
triple.as_ref()
} }
} }
impl<'a> From<&'a Triple> for rio::Triple<'a> { impl<'a> From<TripleRef<'a>> for Triple {
fn from(node: &'a Triple) -> Self { fn from(triple: TripleRef<'a>) -> Self {
triple.into_owned()
}
}
impl<'a> From<TripleRef<'a>> for rio::Triple<'a> {
fn from(triple: TripleRef<'a>) -> Self {
rio::Triple { rio::Triple {
subject: (&node.subject).into(), subject: triple.subject.into(),
predicate: (&node.predicate).into(), predicate: triple.predicate.into(),
object: (&node.object).into(), object: triple.object.into(),
} }
} }
} }
/// A possible graph name. /// A possible owned graph name.
/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and the [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph). /// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and the [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph).
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphName { pub enum GraphName {
@ -231,34 +521,29 @@ pub enum GraphName {
impl GraphName { impl GraphName {
pub fn is_named_node(&self) -> bool { pub fn is_named_node(&self) -> bool {
match self { self.as_ref().is_named_node()
GraphName::NamedNode(_) => true,
_ => false,
}
} }
pub fn is_blank_node(&self) -> bool { pub fn is_blank_node(&self) -> bool {
match self { self.as_ref().is_blank_node()
GraphName::BlankNode(_) => true,
_ => false,
}
} }
pub fn is_default_graph(&self) -> bool { pub fn is_default_graph(&self) -> bool {
self.as_ref().is_default_graph()
}
pub fn as_ref(&self) -> GraphNameRef<'_> {
match self { match self {
GraphName::DefaultGraph => true, Self::NamedNode(node) => GraphNameRef::NamedNode(node.as_ref()),
_ => false, Self::BlankNode(node) => GraphNameRef::BlankNode(node.as_ref()),
Self::DefaultGraph => GraphNameRef::DefaultGraph,
} }
} }
} }
impl fmt::Display for GraphName { impl fmt::Display for GraphName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { self.as_ref().fmt(f)
GraphName::NamedNode(node) => node.fmt(f),
GraphName::BlankNode(node) => node.fmt(f),
GraphName::DefaultGraph => write!(f, "DEFAULT"),
}
} }
} }
@ -268,12 +553,24 @@ impl From<NamedNode> for GraphName {
} }
} }
impl From<NamedNodeRef<'_>> for GraphName {
fn from(node: NamedNodeRef<'_>) -> Self {
node.into_owned().into()
}
}
impl From<BlankNode> for GraphName { impl From<BlankNode> for GraphName {
fn from(node: BlankNode) -> Self { fn from(node: BlankNode) -> Self {
GraphName::BlankNode(node) GraphName::BlankNode(node)
} }
} }
impl From<BlankNodeRef<'_>> for GraphName {
fn from(node: BlankNodeRef<'_>) -> Self {
node.into_owned().into()
}
}
impl From<NamedOrBlankNode> for GraphName { impl From<NamedOrBlankNode> for GraphName {
fn from(node: NamedOrBlankNode) -> Self { fn from(node: NamedOrBlankNode) -> Self {
match node { match node {
@ -283,6 +580,12 @@ impl From<NamedOrBlankNode> for GraphName {
} }
} }
impl From<NamedOrBlankNodeRef<'_>> for GraphName {
fn from(node: NamedOrBlankNodeRef<'_>) -> Self {
node.into_owned().into()
}
}
impl From<Option<NamedOrBlankNode>> for GraphName { impl From<Option<NamedOrBlankNode>> for GraphName {
fn from(name: Option<NamedOrBlankNode>) -> Self { fn from(name: Option<NamedOrBlankNode>) -> Self {
if let Some(node) = name { if let Some(node) = name {
@ -303,17 +606,138 @@ impl From<GraphName> for Option<NamedOrBlankNode> {
} }
} }
impl<'a> From<&'a GraphName> for Option<rio::NamedOrBlankNode<'a>> { /// A possible borrowed graph name.
fn from(name: &'a GraphName) -> Self { /// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and the [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph).
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub enum GraphNameRef<'a> {
NamedNode(NamedNodeRef<'a>),
BlankNode(BlankNodeRef<'a>),
DefaultGraph,
}
impl<'a> GraphNameRef<'a> {
pub fn is_named_node(&self) -> bool {
match self {
GraphNameRef::NamedNode(_) => true,
_ => false,
}
}
pub fn is_blank_node(&self) -> bool {
match self {
GraphNameRef::BlankNode(_) => true,
_ => false,
}
}
pub fn is_default_graph(&self) -> bool {
match self {
GraphNameRef::DefaultGraph => true,
_ => false,
}
}
pub fn into_owned(self) -> GraphName {
match self {
Self::NamedNode(node) => GraphName::NamedNode(node.into_owned()),
Self::BlankNode(node) => GraphName::BlankNode(node.into_owned()),
Self::DefaultGraph => GraphName::DefaultGraph,
}
}
}
impl fmt::Display for GraphNameRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NamedNode(node) => node.fmt(f),
Self::BlankNode(node) => node.fmt(f),
Self::DefaultGraph => write!(f, "DEFAULT"),
}
}
}
impl<'a> From<NamedNodeRef<'a>> for GraphNameRef<'a> {
fn from(node: NamedNodeRef<'a>) -> Self {
Self::NamedNode(node)
}
}
impl<'a> From<&'a NamedNode> for GraphNameRef<'a> {
fn from(node: &'a NamedNode) -> Self {
node.as_ref().into()
}
}
impl<'a> From<BlankNodeRef<'a>> for GraphNameRef<'a> {
fn from(node: BlankNodeRef<'a>) -> Self {
Self::BlankNode(node)
}
}
impl<'a> From<&'a BlankNode> for GraphNameRef<'a> {
fn from(node: &'a BlankNode) -> Self {
node.as_ref().into()
}
}
impl<'a> From<NamedOrBlankNodeRef<'a>> for GraphNameRef<'a> {
fn from(node: NamedOrBlankNodeRef<'a>) -> Self {
match node {
NamedOrBlankNodeRef::NamedNode(node) => node.into(),
NamedOrBlankNodeRef::BlankNode(node) => node.into(),
}
}
}
impl<'a> From<&'a NamedOrBlankNode> for GraphNameRef<'a> {
fn from(node: &'a NamedOrBlankNode) -> Self {
node.as_ref().into()
}
}
impl<'a> From<&'a GraphName> for GraphNameRef<'a> {
fn from(node: &'a GraphName) -> Self {
node.as_ref()
}
}
impl<'a> From<GraphNameRef<'a>> for GraphName {
fn from(node: GraphNameRef<'a>) -> Self {
node.into_owned()
}
}
impl<'a> From<Option<NamedOrBlankNodeRef<'a>>> for GraphNameRef<'a> {
fn from(name: Option<NamedOrBlankNodeRef<'a>>) -> Self {
if let Some(node) = name {
node.into()
} else {
GraphNameRef::DefaultGraph
}
}
}
impl<'a> From<GraphNameRef<'a>> for Option<NamedOrBlankNodeRef<'a>> {
fn from(name: GraphNameRef<'a>) -> Self {
match name { match name {
GraphName::NamedNode(node) => Some(rio::NamedNode::from(node).into()), GraphNameRef::NamedNode(node) => Some(node.into()),
GraphName::BlankNode(node) => Some(rio::BlankNode::from(node).into()), GraphNameRef::BlankNode(node) => Some(node.into()),
GraphName::DefaultGraph => None, GraphNameRef::DefaultGraph => None,
}
}
}
impl<'a> From<GraphNameRef<'a>> for Option<rio::NamedOrBlankNode<'a>> {
fn from(name: GraphNameRef<'a>) -> Self {
match name {
GraphNameRef::NamedNode(node) => Some(rio::NamedNode::from(node).into()),
GraphNameRef::BlankNode(node) => Some(rio::BlankNode::from(node).into()),
GraphNameRef::DefaultGraph => None,
} }
} }
} }
/// A [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) /// An owned [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset)
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Quad { pub struct Quad {
/// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple /// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple
@ -394,27 +818,83 @@ impl Quad {
pub fn destruct(self) -> (NamedOrBlankNode, NamedNode, Term, GraphName) { pub fn destruct(self) -> (NamedOrBlankNode, NamedNode, Term, GraphName) {
(self.subject, self.predicate, self.object, self.graph_name) (self.subject, self.predicate, self.object, self.graph_name)
} }
pub fn as_ref(&self) -> QuadRef<'_> {
QuadRef {
subject: self.subject.as_ref(),
predicate: self.predicate.as_ref(),
object: self.object.as_ref(),
graph_name: self.graph_name.as_ref(),
}
}
} }
impl fmt::Display for Quad { impl fmt::Display for Quad {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::Quad::from(self).fmt(f) self.as_ref().fmt(f)
} }
} }
impl<'a> From<&'a Quad> for rio::Quad<'a> { impl From<Quad> for Triple {
fn from(node: &'a Quad) -> Self { fn from(quad: Quad) -> Self {
rio::Quad { Self {
subject: (&node.subject).into(), subject: quad.subject,
predicate: (&node.predicate).into(), predicate: quad.predicate,
object: (&node.object).into(), object: quad.object,
graph_name: (&node.graph_name).into(),
} }
} }
} }
impl From<Quad> for Triple { /// A borrowed [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset)
fn from(quad: Quad) -> Self { #[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub struct QuadRef<'a> {
/// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple
pub subject: NamedOrBlankNodeRef<'a>,
/// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple
pub predicate: NamedNodeRef<'a>,
/// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple
pub object: TermRef<'a>,
/// The name of the RDF [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) in which the triple is.
pub graph_name: GraphNameRef<'a>,
}
impl<'a> QuadRef<'a> {
/// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset)
pub fn new(
subject: impl Into<NamedOrBlankNodeRef<'a>>,
predicate: impl Into<NamedNodeRef<'a>>,
object: impl Into<TermRef<'a>>,
graph_name: impl Into<GraphNameRef<'a>>,
) -> Self {
Self {
subject: subject.into(),
predicate: predicate.into(),
object: object.into(),
graph_name: graph_name.into(),
}
}
pub fn into_owned(self) -> Quad {
Quad {
subject: self.subject.into_owned(),
predicate: self.predicate.into_owned(),
object: self.object.into_owned(),
graph_name: self.graph_name.into_owned(),
}
}
}
impl fmt::Display for QuadRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rio::Quad::from(*self).fmt(f)
}
}
impl<'a> From<QuadRef<'a>> for TripleRef<'a> {
fn from(quad: QuadRef<'a>) -> Self {
Self { Self {
subject: quad.subject, subject: quad.subject,
predicate: quad.predicate, predicate: quad.predicate,
@ -422,3 +902,26 @@ impl From<Quad> for Triple {
} }
} }
} }
impl<'a> From<&'a Quad> for QuadRef<'a> {
fn from(quad: &'a Quad) -> Self {
quad.as_ref()
}
}
impl<'a> From<QuadRef<'a>> for Quad {
fn from(quad: QuadRef<'a>) -> Self {
quad.into_owned()
}
}
impl<'a> From<QuadRef<'a>> for rio::Quad<'a> {
fn from(quad: QuadRef<'a>) -> Self {
rio::Quad {
subject: quad.subject.into(),
predicate: quad.predicate.into(),
object: quad.object.into(),
graph_name: quad.graph_name.into(),
}
}
}

@ -2,212 +2,204 @@
pub mod rdf { pub mod rdf {
//! [RDF 1.1](https://www.w3.org/TR/rdf11-concepts/) vocabulary //! [RDF 1.1](https://www.w3.org/TR/rdf11-concepts/) vocabulary
use crate::model::named_node::NamedNode; use crate::model::named_node::NamedNodeRef;
use lazy_static::lazy_static;
lazy_static! {
/// The class of containers of alternatives. /// The class of containers of alternatives.
pub static ref ALT: NamedNode = pub const ALT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt");
/// The class of unordered containers. /// The class of unordered containers.
pub static ref BAG: NamedNode = pub const BAG: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag");
/// The first item in the subject RDF list. /// The first item in the subject RDF list.
pub static ref FIRST: NamedNode = pub const FIRST: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#first");
/// The class of HTML literal values. /// The class of HTML literal values.
pub static ref HTML: NamedNode = pub const HTML: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML");
/// The class of language-tagged string literal values. /// The class of language-tagged string literal values.
pub static ref LANG_STRING: NamedNode = pub const LANG_STRING: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString");
/// The class of RDF Lists. /// The class of RDF Lists.
pub static ref LIST: NamedNode = pub const LIST: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#List"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#List");
pub static ref NIL: NamedNode = pub const NIL: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil");
/// The object of the subject RDF statement. /// The object of the subject RDF statement.
pub static ref OBJECT: NamedNode = pub const OBJECT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#object"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#object");
/// The predicate of the subject RDF statement. /// The predicate of the subject RDF statement.
pub static ref PREDICATE: NamedNode = pub const PREDICATE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate");
/// The class of RDF properties. /// The class of RDF properties.
pub static ref PROPERTY: NamedNode = pub const PROPERTY: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Property");
/// The rest of the subject RDF list after the first item. /// The rest of the subject RDF list after the first item.
pub static ref REST: NamedNode = pub const REST: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest");
/// The class of ordered containers. /// The class of ordered containers.
pub static ref SEQ: NamedNode = pub const SEQ: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq");
/// The class of RDF statements. /// The class of RDF statements.
pub static ref STATEMENT: NamedNode = pub const STATEMENT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement");
/// The subject of the subject RDF statement. /// The subject of the subject RDF statement.
pub static ref SUBJECT: NamedNode = pub const SUBJECT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#subject"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#subject");
/// The subject is an instance of a class. /// The subject is an instance of a class.
pub static ref TYPE: NamedNode = pub const TYPE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
/// Idiomatic property used for structured values. /// Idiomatic property used for structured values.
pub static ref VALUE: NamedNode = pub const VALUE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#value"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#value");
/// The class of XML literal values. /// The class of XML literal values.
pub static ref XML_LITERAL: NamedNode = pub const XML_LITERAL: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"); NamedNodeRef::new_unchecked("http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral");
}
} }
pub mod rdfs { pub mod rdfs {
//! [RDFS](https://www.w3.org/TR/rdf-schema/) vocabulary //! [RDFS](https://www.w3.org/TR/rdf-schema/) vocabulary
use crate::model::named_node::NamedNode; use crate::model::named_node::NamedNodeRef;
use lazy_static::lazy_static;
lazy_static! {
/// The class of classes. /// The class of classes.
pub static ref CLASS: NamedNode = pub const CLASS: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Class"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Class");
/// A description of the subject resource. /// A description of the subject resource.
pub static ref COMMENT: NamedNode = pub const COMMENT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#comment"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#comment");
/// The class of RDF containers. /// The class of RDF containers.
pub static ref CONTAINER: NamedNode = pub const CONTAINER: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Container"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Container");
/// The class of container membership properties, rdf:_1, rdf:_2, ..., all of which are sub-properties of 'member'. /// The class of container membership properties, rdf:_1, rdf:_2, ..., all of which are sub-properties of 'member'.
pub static ref CONTAINER_MEMBERSHIP_PROPERTY: NamedNode = pub const CONTAINER_MEMBERSHIP_PROPERTY: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty"); "http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty",
);
/// The class of RDF datatypes. /// The class of RDF datatypes.
pub static ref DATATYPE: NamedNode = pub const DATATYPE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Datatype"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Datatype");
/// A domain of the subject property. /// A domain of the subject property.
pub static ref DOMAIN: NamedNode = pub const DOMAIN: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#domain"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#domain");
/// The definition of the subject resource. /// The definition of the subject resource.
pub static ref IS_DEFINED_BY: NamedNode = pub const IS_DEFINED_BY: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#isDefinedBy"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#isDefinedBy");
/// A human-readable name for the subject. /// A human-readable name for the subject.
pub static ref LABEL: NamedNode = pub const LABEL: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#label"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#label");
/// The class of literal values, e.g. textual strings and integers. /// The class of literal values, e.g. textual strings and integers.
pub static ref LITERAL: NamedNode = pub const LITERAL: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Literal"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Literal");
/// A member of the subject resource. /// A member of the subject resource.
pub static ref MEMBER: NamedNode = pub const MEMBER: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#member"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#member");
/// A range of the subject property. /// A range of the subject property.
pub static ref RANGE: NamedNode = pub const RANGE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#range"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#range");
/// The class resource, everything. /// The class resource, everything.
pub static ref RESOURCE: NamedNode = pub const RESOURCE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Resource"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#Resource");
/// Further information about the subject resource. /// Further information about the subject resource.
pub static ref SEE_ALSO: NamedNode = pub const SEE_ALSO: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#seeAlso"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#seeAlso");
/// The subject is a subclass of a class. /// The subject is a subclass of a class.
pub static ref SUB_CLASS_OF: NamedNode = pub const SUB_CLASS_OF: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#subClassOf"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#subClassOf");
/// The subject is a subproperty of a property. /// The subject is a subproperty of a property.
pub static ref SUB_PROPERTY_OF: NamedNode = pub const SUB_PROPERTY_OF: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2000/01/rdf-schema#subPropertyOf"); NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#subPropertyOf");
}
} }
pub mod xsd { pub mod xsd {
//! `NamedNode`s for [RDF compatible XSD datatypes](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-compatible-xsd-types) //! `NamedNode`s for [RDF compatible XSD datatypes](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-compatible-xsd-types)
use crate::model::named_node::NamedNode; use crate::model::named_node::NamedNodeRef;
use lazy_static::lazy_static;
lazy_static! {
/// true, false /// true, false
pub static ref BOOLEAN: NamedNode = pub const BOOLEAN: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#boolean"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#boolean");
/// 128…+127 (8 bit) /// 128…+127 (8 bit)
pub static ref BYTE: NamedNode = pub const BYTE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#byte"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#byte");
/// Dates (yyyy-mm-dd) with or without timezone /// Dates (yyyy-mm-dd) with or without timezone
pub static ref DATE: NamedNode = pub const DATE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#date"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#date");
/// Duration of time (days, hours, minutes, seconds only) /// Duration of time (days, hours, minutes, seconds only)
pub static ref DAY_TIME_DURATION: NamedNode = pub const DAY_TIME_DURATION: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#dayTimeDuration"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#dayTimeDuration");
/// Date and time with or without timezone /// Date and time with or without timezone
pub static ref DATE_TIME: NamedNode = pub const DATE_TIME: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#dateTime"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#dateTime");
/// Date and time with required timezone /// Date and time with required timezone
pub static ref DATE_TIME_STAMP: NamedNode = pub const DATE_TIME_STAMP: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#dateTimeStamp"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#dateTimeStamp");
/// Arbitrary-precision decimal numbers /// Arbitrary-precision decimal numbers
pub static ref DECIMAL: NamedNode = pub const DECIMAL: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#decimal"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#decimal");
/// 64-bit floating point numbers incl. ±Inf, ±0, NaN /// 64-bit floating point numbers incl. ±Inf, ±0, NaN
pub static ref DOUBLE: NamedNode = pub const DOUBLE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#double"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#double");
/// Duration of time /// Duration of time
pub static ref DURATION: NamedNode = pub const DURATION: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#duration"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#duration");
/// 32-bit floating point numbers incl. ±Inf, ±0, NaN /// 32-bit floating point numbers incl. ±Inf, ±0, NaN
pub static ref FLOAT: NamedNode = pub const FLOAT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#float"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#float");
/// Gregorian calendar day of the month /// Gregorian calendar day of the month
pub static ref G_DAY: NamedNode = pub const G_DAY: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#gDay"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#gDay");
/// Gregorian calendar month /// Gregorian calendar month
pub static ref G_MONTH: NamedNode = pub const G_MONTH: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#gMonth"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#gMonth");
/// Gregorian calendar month and day /// Gregorian calendar month and day
pub static ref G_MONTH_DAY: NamedNode = pub const G_MONTH_DAY: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#gMonthDay"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#gMonthDay");
/// Gregorian calendar year /// Gregorian calendar year
pub static ref G_YEAR: NamedNode = pub const G_YEAR: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#gYear"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#gYear");
/// Gregorian calendar year and month /// Gregorian calendar year and month
pub static ref G_YEAR_MONTH: NamedNode = pub const G_YEAR_MONTH: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#gYearMonth"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#gYearMonth");
/// -2147483648…+2147483647 (32 bit) /// -2147483648…+2147483647 (32 bit)
pub static ref INT: NamedNode = pub const INT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#int"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#int");
/// Arbitrary-size integer numbers /// Arbitrary-size integer numbers
pub static ref INTEGER: NamedNode = pub const INTEGER: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#integer"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#integer");
/// -9223372036854775808…+9223372036854775807 (64 bit) /// -9223372036854775808…+9223372036854775807 (64 bit)
pub static ref LONG: NamedNode = pub const LONG: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#long"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#long");
/// Integer numbers <0 /// Integer numbers <0
pub static ref NEGATIVE_INTEGER: NamedNode = pub const NEGATIVE_INTEGER: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#negativeInteger"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#negativeInteger");
/// Integer numbers ≥0 /// Integer numbers ≥0
pub static ref NON_NEGATIVE_INTEGER: NamedNode = pub const NON_NEGATIVE_INTEGER: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#nonNegativeInteger"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#nonNegativeInteger");
/// Integer numbers ≤0 /// Integer numbers ≤0
pub static ref NON_POSITIVE_INTEGER: NamedNode = pub const NON_POSITIVE_INTEGER: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#nonPositiveInteger"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#nonPositiveInteger");
/// Integer numbers >0 /// Integer numbers >0
pub static ref POSITIVE_INTEGER: NamedNode = pub const POSITIVE_INTEGER: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#positiveInteger"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#positiveInteger");
/// Times (hh:mm:ss.sss…) with or without timezone /// Times (hh:mm:ss.sss…) with or without timezone
pub static ref TIME: NamedNode = pub const TIME: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#time"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#time");
/// -32768…+32767 (16 bit) /// -32768…+32767 (16 bit)
pub static ref SHORT: NamedNode = pub const SHORT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#short"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#short");
/// Character strings (but not all Unicode character strings) /// Character strings (but not all Unicode character strings)
pub static ref STRING: NamedNode = pub const STRING: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#string"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#string");
/// 0…255 (8 bit) /// 0…255 (8 bit)
pub static ref UNSIGNED_BYTE: NamedNode = pub const UNSIGNED_BYTE: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#unsignedByte"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#unsignedByte");
/// 0…4294967295 (32 bit) /// 0…4294967295 (32 bit)
pub static ref UNSIGNED_INT: NamedNode = pub const UNSIGNED_INT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#unsignedInt"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#unsignedInt");
/// 0…18446744073709551615 (64 bit) /// 0…18446744073709551615 (64 bit)
pub static ref UNSIGNED_LONG: NamedNode = pub const UNSIGNED_LONG: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#unsignedLong"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#unsignedLong");
/// 0…65535 (16 bit) /// 0…65535 (16 bit)
pub static ref UNSIGNED_SHORT: NamedNode = pub const UNSIGNED_SHORT: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#unsignedShort"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#unsignedShort");
/// Duration of time (months and years only) /// Duration of time (months and years only)
pub static ref YEAR_MONTH_DURATION: NamedNode = pub const YEAR_MONTH_DURATION: NamedNodeRef<'_> =
NamedNode::new_unchecked("http://www.w3.org/2001/XMLSchema#yearMonthDuration"); NamedNodeRef::new_unchecked("http://www.w3.org/2001/XMLSchema#yearMonthDuration");
}
} }

@ -30,6 +30,12 @@ impl From<NamedNode> for NamedNodeOrVariable {
} }
} }
impl From<NamedNodeRef<'_>> for NamedNodeOrVariable {
fn from(node: NamedNodeRef<'_>) -> Self {
NamedNodeOrVariable::NamedNode(node.into())
}
}
impl From<Variable> for NamedNodeOrVariable { impl From<Variable> for NamedNodeOrVariable {
fn from(var: Variable) -> Self { fn from(var: Variable) -> Self {
NamedNodeOrVariable::Variable(var) NamedNodeOrVariable::Variable(var)
@ -57,6 +63,12 @@ impl From<NamedNode> for TermOrVariable {
} }
} }
impl From<NamedNodeRef<'_>> for TermOrVariable {
fn from(node: NamedNodeRef<'_>) -> Self {
TermOrVariable::Term(node.into())
}
}
impl From<BlankNode> for TermOrVariable { impl From<BlankNode> for TermOrVariable {
fn from(node: BlankNode) -> Self { fn from(node: BlankNode) -> Self {
TermOrVariable::Term(node.into()) TermOrVariable::Term(node.into())

@ -1065,7 +1065,12 @@ where
let bnode = let bnode =
BlankNode::new(self.to_simple_string(self.eval_expression(id, tuple)?)?) BlankNode::new(self.to_simple_string(self.eval_expression(id, tuple)?)?)
.ok()?; .ok()?;
Some(self.dataset.as_ref().encode_blank_node(&bnode).ok()?) Some(
self.dataset
.as_ref()
.encode_blank_node(bnode.as_ref())
.ok()?,
)
} }
None => Some(EncodedTerm::InlineBlankNode { None => Some(EncodedTerm::InlineBlankNode {
id: random::<u128>(), id: random::<u128>(),
@ -1741,7 +1746,7 @@ where
put_variable_value( put_variable_value(
variable, variable,
&variables, &variables,
encoder.encode_term(term).map_err(|e| e.into())?, encoder.encode_term(term.as_ref()).map_err(|e| e.into())?,
&mut encoded_terms, &mut encoded_terms,
) )
} }

@ -1052,7 +1052,7 @@ parser! {
} }
//[78] //[78]
rule Verb() -> NamedNodeOrVariable = VarOrIri() / "a" { rdf::TYPE.clone().into() } rule Verb() -> NamedNodeOrVariable = VarOrIri() / "a" { rdf::TYPE.into() }
//[79] //[79]
rule ObjectList() -> FocusedTriplePattern<Vec<TermOrVariable>> = o:ObjectList_item() **<1,> ("," _) { rule ObjectList() -> FocusedTriplePattern<Vec<TermOrVariable>> = o:ObjectList_item() **<1,> ("," _) {
@ -1172,7 +1172,7 @@ parser! {
//[94] //[94]
rule PathPrimary() -> PropertyPath = rule PathPrimary() -> PropertyPath =
v:iri() { v.into() } / v:iri() { v.into() } /
"a" { rdf::TYPE.clone().into() } / "a" { NamedNode::from(rdf::TYPE).into() } /
"!" _ p:PathNegatedPropertySet() { p } / "!" _ p:PathNegatedPropertySet() { p } /
"(" _ p:Path() _ ")" { p } "(" _ p:Path() _ ")" { p }
@ -1209,9 +1209,9 @@ parser! {
//[96] //[96]
rule PathOneInPropertySet() -> Either<NamedNode,NamedNode> = rule PathOneInPropertySet() -> Either<NamedNode,NamedNode> =
"^" _ v:iri() { Either::Right(v) } / "^" _ v:iri() { Either::Right(v) } /
"^" _ "a" { Either::Right(rdf::TYPE.clone()) } / "^" _ "a" { Either::Right(rdf::TYPE.into()) } /
v:iri() { Either::Left(v) } / v:iri() { Either::Left(v) } /
"a" { Either::Left(rdf::TYPE.clone()) } "a" { Either::Left(rdf::TYPE.into()) }
//[98] //[98]
rule TriplesNode() -> FocusedTriplePattern<TermOrVariable> = Collection() / BlankNodePropertyList() rule TriplesNode() -> FocusedTriplePattern<TermOrVariable> = Collection() / BlankNodePropertyList()
@ -1252,11 +1252,11 @@ parser! {
//[102] //[102]
rule Collection() -> FocusedTriplePattern<TermOrVariable> = "(" _ o:Collection_item()+ ")" { rule Collection() -> FocusedTriplePattern<TermOrVariable> = "(" _ o:Collection_item()+ ")" {
let mut patterns: Vec<TriplePattern> = Vec::default(); let mut patterns: Vec<TriplePattern> = Vec::default();
let mut current_list_node = TermOrVariable::from(rdf::NIL.clone()); let mut current_list_node = TermOrVariable::from(rdf::NIL);
for objWithPatterns in o.into_iter().rev() { for objWithPatterns in o.into_iter().rev() {
let new_blank_node = TermOrVariable::from(BlankNode::default()); let new_blank_node = TermOrVariable::from(BlankNode::default());
patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::FIRST.clone(), objWithPatterns.focus.clone())); patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::FIRST, objWithPatterns.focus.clone()));
patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::REST.clone(), current_list_node)); patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::REST, current_list_node));
current_list_node = new_blank_node; current_list_node = new_blank_node;
patterns.extend_from_slice(&objWithPatterns.patterns); patterns.extend_from_slice(&objWithPatterns.patterns);
} }
@ -1270,11 +1270,11 @@ parser! {
//[103] //[103]
rule CollectionPath() -> FocusedTripleOrPathPattern<TermOrVariable> = "(" _ o:CollectionPath_item()+ _ ")" { rule CollectionPath() -> FocusedTripleOrPathPattern<TermOrVariable> = "(" _ o:CollectionPath_item()+ _ ")" {
let mut patterns: Vec<TripleOrPathPattern> = Vec::default(); let mut patterns: Vec<TripleOrPathPattern> = Vec::default();
let mut current_list_node = TermOrVariable::from(rdf::NIL.clone()); let mut current_list_node = TermOrVariable::from(rdf::NIL);
for objWithPatterns in o.into_iter().rev() { for objWithPatterns in o.into_iter().rev() {
let new_blank_node = TermOrVariable::from(BlankNode::default()); let new_blank_node = TermOrVariable::from(BlankNode::default());
patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::FIRST.clone(), objWithPatterns.focus.clone()).into()); patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::FIRST, objWithPatterns.focus.clone()).into());
patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::REST.clone(), current_list_node).into()); patterns.push(TriplePattern::new(new_blank_node.clone(), rdf::REST, current_list_node).into());
current_list_node = new_blank_node; current_list_node = new_blank_node;
patterns.extend_from_slice(&objWithPatterns.patterns); patterns.extend_from_slice(&objWithPatterns.patterns);
} }
@ -1315,7 +1315,7 @@ parser! {
l:NumericLiteral() { l.into() } / l:NumericLiteral() { l.into() } /
l:BooleanLiteral() { l.into() } / l:BooleanLiteral() { l.into() } /
b:BlankNode() { b.into() } / b:BlankNode() { b.into() } /
NIL() { rdf::NIL.clone().into() } NIL() { rdf::NIL.into() }
//[110] //[110]
rule Expression() -> Expression = e:ConditionalOrExpression() {e} rule Expression() -> Expression = e:ConditionalOrExpression() {e}
@ -1523,8 +1523,8 @@ parser! {
Ok(value) => Ok(value.into()), Ok(value) => Ok(value.into()),
Err(_) => Err("Invalid xsd:double()") Err(_) => Err("Invalid xsd:double()")
} } / } } /
d:$(DECIMAL()) { Literal::new_typed_literal(d, xsd::DECIMAL.clone()) } / d:$(DECIMAL()) { Literal::new_typed_literal(d, xsd::DECIMAL) } /
i:$(INTEGER()) { Literal::new_typed_literal(i, xsd::INTEGER.clone()) } i:$(INTEGER()) { Literal::new_typed_literal(i, xsd::INTEGER) }
//[132] //[132]
rule NumericLiteralPositive() -> Literal = rule NumericLiteralPositive() -> Literal =
@ -1532,8 +1532,8 @@ parser! {
Ok(value) => Ok(value.into()), Ok(value) => Ok(value.into()),
Err(_) => Err("Invalid xsd:double()") Err(_) => Err("Invalid xsd:double()")
} } / } } /
d:$(DECIMAL_POSITIVE()) { Literal::new_typed_literal(d, xsd::DECIMAL.clone()) } / d:$(DECIMAL_POSITIVE()) { Literal::new_typed_literal(d, xsd::DECIMAL) } /
i:$(INTEGER_POSITIVE()) { Literal::new_typed_literal(i, xsd::INTEGER.clone()) } i:$(INTEGER_POSITIVE()) { Literal::new_typed_literal(i, xsd::INTEGER) }
//[133] //[133]
@ -1542,8 +1542,8 @@ parser! {
Ok(value) => Ok(value.into()), Ok(value) => Ok(value.into()),
Err(_) => Err("Invalid xsd:double()") Err(_) => Err("Invalid xsd:double()")
} } / } } /
d:$(DECIMAL_NEGATIVE()) { Literal::new_typed_literal(d, xsd::DECIMAL.clone()) } / d:$(DECIMAL_NEGATIVE()) { Literal::new_typed_literal(d, xsd::DECIMAL) } /
i:$(INTEGER_NEGATIVE()) { Literal::new_typed_literal(i, xsd::INTEGER.clone()) } i:$(INTEGER_NEGATIVE()) { Literal::new_typed_literal(i, xsd::INTEGER) }
//[134] //[134]
rule BooleanLiteral() -> Literal = rule BooleanLiteral() -> Literal =

@ -992,17 +992,20 @@ impl<E: WriteEncoder<Error = EvaluationError>> PlanBuilder<E> {
fn build_named_node( fn build_named_node(
&mut self, &mut self,
term: &NamedNode, node: &NamedNode,
) -> Result<EncodedTerm<E::StrId>, EvaluationError> { ) -> Result<EncodedTerm<E::StrId>, EvaluationError> {
Ok(self.encoder.encode_named_node(term)?) Ok(self.encoder.encode_named_node(node.as_ref())?)
} }
fn build_literal(&mut self, term: &Literal) -> Result<EncodedTerm<E::StrId>, EvaluationError> { fn build_literal(
Ok(self.encoder.encode_literal(term)?) &mut self,
literal: &Literal,
) -> Result<EncodedTerm<E::StrId>, EvaluationError> {
Ok(self.encoder.encode_literal(literal.as_ref())?)
} }
fn build_term(&mut self, term: &Term) -> Result<EncodedTerm<E::StrId>, EvaluationError> { fn build_term(&mut self, term: &Term) -> Result<EncodedTerm<E::StrId>, EvaluationError> {
Ok(self.encoder.encode_term(term)?) Ok(self.encoder.encode_term(term.as_ref())?)
} }
} }

@ -40,7 +40,7 @@ use std::{fmt, io};
/// store.insert(quad.clone()); /// store.insert(quad.clone());
/// ///
/// // quad filter /// // quad filter
/// let results: Vec<Quad> = store.quads_for_pattern(Some(&ex.clone().into()), None, None, None).collect(); /// let results: Vec<Quad> = store.quads_for_pattern(Some(ex.as_ref().into()), None, None, None).collect();
/// assert_eq!(vec![quad], results); /// assert_eq!(vec![quad], results);
/// ///
/// // SPARQL query /// // SPARQL query
@ -168,10 +168,10 @@ impl MemoryStore {
/// ``` /// ```
pub fn quads_for_pattern( pub fn quads_for_pattern(
&self, &self,
subject: Option<&NamedOrBlankNode>, subject: Option<NamedOrBlankNodeRef<'_>>,
predicate: Option<&NamedNode>, predicate: Option<NamedNodeRef<'_>>,
object: Option<&Term>, object: Option<TermRef<'_>>,
graph_name: Option<&GraphName>, graph_name: Option<GraphNameRef<'_>>,
) -> impl Iterator<Item = Quad> { ) -> impl Iterator<Item = Quad> {
let quads = if let Some((subject, predicate, object, graph_name)) = let quads = if let Some((subject, predicate, object, graph_name)) =
get_encoded_quad_pattern(self, subject, predicate, object, graph_name) get_encoded_quad_pattern(self, subject, predicate, object, graph_name)
@ -188,8 +188,8 @@ impl MemoryStore {
} }
/// Checks if this store contains a given quad /// Checks if this store contains a given quad
pub fn contains(&self, quad: &Quad) -> bool { pub fn contains<'a>(&self, quad: impl Into<QuadRef<'a>>) -> bool {
self.get_encoded_quad(quad) self.get_encoded_quad(quad.into())
.unwrap_infallible() .unwrap_infallible()
.map_or(false, |q| self.contains_encoded(&q)) .map_or(false, |q| self.contains_encoded(&q))
} }
@ -250,11 +250,11 @@ impl MemoryStore {
for op in transaction.ops { for op in transaction.ops {
match op { match op {
TransactionOp::Insert(quad) => { TransactionOp::Insert(quad) => {
let quad = this.encode_quad(&quad).unwrap_infallible(); let quad = this.encode_quad(quad.as_ref()).unwrap_infallible();
indexes.insert_encoded(&quad).unwrap_infallible() indexes.insert_encoded(&quad).unwrap_infallible()
} }
TransactionOp::Delete(quad) => { TransactionOp::Delete(quad) => {
let quad = this.encode_quad(&quad).unwrap_infallible(); let quad = this.encode_quad(quad.as_ref()).unwrap_infallible();
indexes.remove_encoded(&quad).unwrap_infallible() indexes.remove_encoded(&quad).unwrap_infallible()
} }
} }
@ -285,15 +285,15 @@ impl MemoryStore {
/// ///
/// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind. /// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind.
/// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind. /// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind.
pub fn load_graph( pub fn load_graph<'a>(
&self, &self,
reader: impl BufRead, reader: impl BufRead,
format: GraphFormat, format: GraphFormat,
to_graph_name: &GraphName, to_graph_name: impl Into<GraphNameRef<'a>>,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
let mut store = self; let mut store = self;
load_graph(&mut store, reader, format, to_graph_name, base_iri)?; load_graph(&mut store, reader, format, to_graph_name.into(), base_iri)?;
Ok(()) Ok(())
} }
@ -335,13 +335,13 @@ impl MemoryStore {
#[allow(clippy::needless_pass_by_value)] #[allow(clippy::needless_pass_by_value)]
pub fn insert(&self, quad: Quad) { pub fn insert(&self, quad: Quad) {
let mut this = self; let mut this = self;
let quad = this.encode_quad(&quad).unwrap_infallible(); let quad = this.encode_quad(quad.as_ref()).unwrap_infallible();
this.insert_encoded(&quad).unwrap_infallible(); this.insert_encoded(&quad).unwrap_infallible();
} }
/// Removes a quad from this store. /// Removes a quad from this store.
pub fn remove(&self, quad: &Quad) { pub fn remove<'a>(&self, quad: impl Into<QuadRef<'a>>) {
if let Some(quad) = self.get_encoded_quad(quad).unwrap_infallible() { if let Some(quad) = self.get_encoded_quad(quad.into()).unwrap_infallible() {
let mut this = self; let mut this = self;
this.remove_encoded(&quad).unwrap_infallible(); this.remove_encoded(&quad).unwrap_infallible();
} }
@ -378,14 +378,14 @@ impl MemoryStore {
/// ///
/// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind. /// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind.
/// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind. /// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind.
pub fn dump_graph( pub fn dump_graph<'a>(
&self, &self,
writer: impl Write, writer: impl Write,
format: GraphFormat, format: GraphFormat,
from_graph_name: &GraphName, from_graph_name: impl Into<GraphNameRef<'a>>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
dump_graph( dump_graph(
self.quads_for_pattern(None, None, None, Some(from_graph_name)) self.quads_for_pattern(None, None, None, Some(from_graph_name.into()))
.map(|q| Ok(q.into())), .map(|q| Ok(q.into())),
writer, writer,
format, format,
@ -973,13 +973,14 @@ impl MemoryTransaction {
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results); /// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results);
/// # Result::<_, oxigraph::sparql::EvaluationError>::Ok(()) /// # Result::<_, oxigraph::sparql::EvaluationError>::Ok(())
/// ``` /// ```
pub fn load_graph( pub fn load_graph<'a>(
&mut self, &mut self,
reader: impl BufRead, reader: impl BufRead,
format: GraphFormat, format: GraphFormat,
to_graph_name: &GraphName, to_graph_name: impl Into<GraphNameRef<'a>>,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
let to_graph_name = to_graph_name.into();
let mut parser = GraphParser::from_format(format); let mut parser = GraphParser::from_format(format);
if let Some(base_iri) = base_iri { if let Some(base_iri) = base_iri {
parser = parser parser = parser
@ -987,9 +988,8 @@ impl MemoryTransaction {
.map_err(invalid_input_error)?; .map_err(invalid_input_error)?;
} }
for triple in parser.read_triples(reader)? { for triple in parser.read_triples(reader)? {
self.ops.push(TransactionOp::Insert( self.ops
triple?.in_graph(to_graph_name.clone()), .push(TransactionOp::Insert(triple?.in_graph(to_graph_name)));
));
} }
Ok(()) Ok(())
} }

@ -17,16 +17,12 @@ pub use crate::store::rocksdb::RocksDbStore;
pub use crate::store::sled::SledStore; pub use crate::store::sled::SledStore;
use crate::error::{invalid_data_error, invalid_input_error}; use crate::error::{invalid_data_error, invalid_input_error};
use crate::io::{DatasetFormat, GraphFormat}; use crate::io::{DatasetFormat, DatasetSerializer, GraphFormat, GraphSerializer};
use crate::model::*; use crate::model::*;
use crate::store::numeric_encoder::*; use crate::store::numeric_encoder::*;
use rio_api::formatter::{QuadsFormatter, TriplesFormatter};
use rio_api::parser::{QuadsParser, TriplesParser}; use rio_api::parser::{QuadsParser, TriplesParser};
use rio_turtle::{ use rio_turtle::{NQuadsParser, NTriplesParser, TriGParser, TurtleError, TurtleParser};
NQuadsFormatter, NQuadsParser, NTriplesFormatter, NTriplesParser, TriGFormatter, TriGParser, use rio_xml::{RdfXmlError, RdfXmlParser};
TurtleError, TurtleFormatter, TurtleParser,
};
use rio_xml::{RdfXmlError, RdfXmlFormatter, RdfXmlParser};
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::Infallible; use std::convert::Infallible;
use std::io; use std::io;
@ -55,7 +51,7 @@ fn load_graph<S: WritableEncodedStore + StrContainer>(
store: &mut S, store: &mut S,
reader: impl BufRead, reader: impl BufRead,
format: GraphFormat, format: GraphFormat,
to_graph_name: &GraphName, to_graph_name: GraphNameRef<'_>,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<(), StoreOrParseError<S::Error, io::Error>> { ) -> Result<(), StoreOrParseError<S::Error, io::Error>> {
let base_iri = base_iri.unwrap_or(""); let base_iri = base_iri.unwrap_or("");
@ -75,7 +71,7 @@ fn load_graph<S: WritableEncodedStore + StrContainer>(
fn load_from_triple_parser<S: WritableEncodedStore + StrContainer, P: TriplesParser>( fn load_from_triple_parser<S: WritableEncodedStore + StrContainer, P: TriplesParser>(
store: &mut S, store: &mut S,
parser: Result<P, P::Error>, parser: Result<P, P::Error>,
to_graph_name: &GraphName, to_graph_name: GraphNameRef<'_>,
) -> Result<(), StoreOrParseError<S::Error, io::Error>> ) -> Result<(), StoreOrParseError<S::Error, io::Error>>
where where
StoreOrParseError<S::Error, P::Error>: From<P::Error>, StoreOrParseError<S::Error, P::Error>: From<P::Error>,
@ -107,34 +103,11 @@ fn dump_graph(
writer: impl Write, writer: impl Write,
format: GraphFormat, format: GraphFormat,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
match format { let mut writer = GraphSerializer::from_format(format).triple_writer(writer)?;
GraphFormat::NTriples => {
let mut formatter = NTriplesFormatter::new(writer);
for triple in triples {
formatter.format(&(&triple?).into())?;
}
formatter.finish();
}
GraphFormat::Turtle => {
let mut formatter = TurtleFormatter::new(writer);
for triple in triples { for triple in triples {
formatter.format(&(&triple?).into())?; writer.write(&triple?)?;
}
formatter.finish()?;
}
GraphFormat::RdfXml => {
let mut formatter = RdfXmlFormatter::new(writer).map_err(map_xml_err)?;
for triple in triples {
formatter.format(&(&triple?).into()).map_err(map_xml_err)?;
}
formatter.finish().map_err(map_xml_err)?;
} }
} writer.finish()
Ok(())
}
fn map_xml_err(e: RdfXmlError) -> io::Error {
io::Error::new(io::ErrorKind::Other, e) // TODO: drop
} }
fn load_dataset<S: WritableEncodedStore + StrContainer>( fn load_dataset<S: WritableEncodedStore + StrContainer>(
@ -181,23 +154,11 @@ fn dump_dataset(
writer: impl Write, writer: impl Write,
format: DatasetFormat, format: DatasetFormat,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
match format { let mut writer = DatasetSerializer::from_format(format).quad_writer(writer)?;
DatasetFormat::NQuads => {
let mut formatter = NQuadsFormatter::new(writer);
for quad in quads { for quad in quads {
formatter.format(&(&quad?).into())?; writer.write(&quad?)?;
}
formatter.finish();
} }
DatasetFormat::TriG => { writer.finish()
let mut formatter = TriGFormatter::new(writer);
for quad in quads {
formatter.format(&(&quad?).into())?;
}
formatter.finish()?;
}
}
Ok(())
} }
enum StoreOrParseError<S, P> { enum StoreOrParseError<S, P> {
@ -249,10 +210,10 @@ type QuadPattern<I> = (
fn get_encoded_quad_pattern<E: ReadEncoder>( fn get_encoded_quad_pattern<E: ReadEncoder>(
encoder: &E, encoder: &E,
subject: Option<&NamedOrBlankNode>, subject: Option<NamedOrBlankNodeRef<'_>>,
predicate: Option<&NamedNode>, predicate: Option<NamedNodeRef<'_>>,
object: Option<&Term>, object: Option<TermRef<'_>>,
graph_name: Option<&GraphName>, graph_name: Option<GraphNameRef<'_>>,
) -> Result<Option<QuadPattern<E::StrId>>, E::Error> { ) -> Result<Option<QuadPattern<E::StrId>>, E::Error> {
Ok(Some(( Ok(Some((
if let Some(subject) = transpose( if let Some(subject) = transpose(

@ -787,7 +787,7 @@ impl StrContainer for MemoryStrStore {
pub(crate) trait ReadEncoder: WithStoreError { pub(crate) trait ReadEncoder: WithStoreError {
fn get_encoded_named_node( fn get_encoded_named_node(
&self, &self,
named_node: &NamedNode, named_node: NamedNodeRef<'_>,
) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> { ) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> {
Ok(Some(EncodedTerm::NamedNode { Ok(Some(EncodedTerm::NamedNode {
iri_id: if let Some(iri_id) = self.get_encoded_str(named_node.as_str())? { iri_id: if let Some(iri_id) = self.get_encoded_str(named_node.as_str())? {
@ -800,7 +800,7 @@ pub(crate) trait ReadEncoder: WithStoreError {
fn get_encoded_blank_node( fn get_encoded_blank_node(
&self, &self,
blank_node: &BlankNode, blank_node: BlankNodeRef<'_>,
) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> { ) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> {
Ok(Some(if let Some(id) = blank_node.id() { Ok(Some(if let Some(id) = blank_node.id() {
EncodedTerm::InlineBlankNode { id } EncodedTerm::InlineBlankNode { id }
@ -817,7 +817,7 @@ pub(crate) trait ReadEncoder: WithStoreError {
fn get_encoded_literal( fn get_encoded_literal(
&self, &self,
literal: &Literal, literal: LiteralRef<'_>,
) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> { ) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> {
Ok(Some( Ok(Some(
match match literal.datatype().as_str() { match match literal.datatype().as_str() {
@ -905,57 +905,57 @@ pub(crate) trait ReadEncoder: WithStoreError {
fn get_encoded_named_or_blank_node( fn get_encoded_named_or_blank_node(
&self, &self,
term: &NamedOrBlankNode, term: NamedOrBlankNodeRef<'_>,
) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> { ) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> {
match term { match term {
NamedOrBlankNode::NamedNode(named_node) => self.get_encoded_named_node(named_node), NamedOrBlankNodeRef::NamedNode(named_node) => self.get_encoded_named_node(named_node),
NamedOrBlankNode::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node), NamedOrBlankNodeRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node),
} }
} }
fn get_encoded_term( fn get_encoded_term(
&self, &self,
term: &Term, term: TermRef<'_>,
) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> { ) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> {
match term { match term {
Term::NamedNode(named_node) => self.get_encoded_named_node(named_node), TermRef::NamedNode(named_node) => self.get_encoded_named_node(named_node),
Term::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node), TermRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node),
Term::Literal(literal) => self.get_encoded_literal(literal), TermRef::Literal(literal) => self.get_encoded_literal(literal),
} }
} }
fn get_encoded_graph_name( fn get_encoded_graph_name(
&self, &self,
name: &GraphName, name: GraphNameRef<'_>,
) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> { ) -> Result<Option<EncodedTerm<Self::StrId>>, Self::Error> {
match name { match name {
GraphName::NamedNode(named_node) => self.get_encoded_named_node(named_node), GraphNameRef::NamedNode(named_node) => self.get_encoded_named_node(named_node),
GraphName::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node), GraphNameRef::BlankNode(blank_node) => self.get_encoded_blank_node(blank_node),
GraphName::DefaultGraph => Ok(Some(EncodedTerm::DefaultGraph)), GraphNameRef::DefaultGraph => Ok(Some(EncodedTerm::DefaultGraph)),
} }
} }
fn get_encoded_quad( fn get_encoded_quad(
&self, &self,
quad: &Quad, quad: QuadRef<'_>,
) -> Result<Option<EncodedQuad<Self::StrId>>, Self::Error> { ) -> Result<Option<EncodedQuad<Self::StrId>>, Self::Error> {
Ok(Some(EncodedQuad { Ok(Some(EncodedQuad {
subject: if let Some(subject) = self.get_encoded_named_or_blank_node(&quad.subject)? { subject: if let Some(subject) = self.get_encoded_named_or_blank_node(quad.subject)? {
subject subject
} else { } else {
return Ok(None); return Ok(None);
}, },
predicate: if let Some(predicate) = self.get_encoded_named_node(&quad.predicate)? { predicate: if let Some(predicate) = self.get_encoded_named_node(quad.predicate)? {
predicate predicate
} else { } else {
return Ok(None); return Ok(None);
}, },
object: if let Some(object) = self.get_encoded_term(&quad.object)? { object: if let Some(object) = self.get_encoded_term(quad.object)? {
object object
} else { } else {
return Ok(None); return Ok(None);
}, },
graph_name: if let Some(graph_name) = self.get_encoded_graph_name(&quad.graph_name)? { graph_name: if let Some(graph_name) = self.get_encoded_graph_name(quad.graph_name)? {
graph_name graph_name
} else { } else {
return Ok(None); return Ok(None);
@ -976,14 +976,14 @@ impl<S: StrLookup> ReadEncoder for S {
pub(crate) trait WriteEncoder: WithStoreError { pub(crate) trait WriteEncoder: WithStoreError {
fn encode_named_node( fn encode_named_node(
&mut self, &mut self,
named_node: &NamedNode, named_node: NamedNodeRef<'_>,
) -> Result<EncodedTerm<Self::StrId>, Self::Error> { ) -> Result<EncodedTerm<Self::StrId>, Self::Error> {
self.encode_rio_named_node(named_node.into()) self.encode_rio_named_node(named_node.into())
} }
fn encode_blank_node( fn encode_blank_node(
&mut self, &mut self,
blank_node: &BlankNode, blank_node: BlankNodeRef<'_>,
) -> Result<EncodedTerm<Self::StrId>, Self::Error> { ) -> Result<EncodedTerm<Self::StrId>, Self::Error> {
if let Some(id) = blank_node.id() { if let Some(id) = blank_node.id() {
Ok(EncodedTerm::InlineBlankNode { id }) Ok(EncodedTerm::InlineBlankNode { id })
@ -996,58 +996,58 @@ pub(crate) trait WriteEncoder: WithStoreError {
fn encode_literal( fn encode_literal(
&mut self, &mut self,
literal: &Literal, literal: LiteralRef<'_>,
) -> Result<EncodedTerm<Self::StrId>, Self::Error> { ) -> Result<EncodedTerm<Self::StrId>, Self::Error> {
self.encode_rio_literal(literal.into()) self.encode_rio_literal(literal.into())
} }
fn encode_named_or_blank_node( fn encode_named_or_blank_node(
&mut self, &mut self,
term: &NamedOrBlankNode, term: NamedOrBlankNodeRef<'_>,
) -> Result<EncodedTerm<Self::StrId>, Self::Error> { ) -> Result<EncodedTerm<Self::StrId>, Self::Error> {
match term { match term {
NamedOrBlankNode::NamedNode(named_node) => self.encode_named_node(named_node), NamedOrBlankNodeRef::NamedNode(named_node) => self.encode_named_node(named_node),
NamedOrBlankNode::BlankNode(blank_node) => self.encode_blank_node(blank_node), NamedOrBlankNodeRef::BlankNode(blank_node) => self.encode_blank_node(blank_node),
} }
} }
fn encode_term(&mut self, term: &Term) -> Result<EncodedTerm<Self::StrId>, Self::Error> { fn encode_term(&mut self, term: TermRef<'_>) -> Result<EncodedTerm<Self::StrId>, Self::Error> {
match term { match term {
Term::NamedNode(named_node) => self.encode_named_node(named_node), TermRef::NamedNode(named_node) => self.encode_named_node(named_node),
Term::BlankNode(blank_node) => self.encode_blank_node(blank_node), TermRef::BlankNode(blank_node) => self.encode_blank_node(blank_node),
Term::Literal(literal) => self.encode_literal(literal), TermRef::Literal(literal) => self.encode_literal(literal),
} }
} }
fn encode_graph_name( fn encode_graph_name(
&mut self, &mut self,
name: &GraphName, name: GraphNameRef<'_>,
) -> Result<EncodedTerm<Self::StrId>, Self::Error> { ) -> Result<EncodedTerm<Self::StrId>, Self::Error> {
match name { match name {
GraphName::NamedNode(named_node) => self.encode_named_node(named_node), GraphNameRef::NamedNode(named_node) => self.encode_named_node(named_node),
GraphName::BlankNode(blank_node) => self.encode_blank_node(blank_node), GraphNameRef::BlankNode(blank_node) => self.encode_blank_node(blank_node),
GraphName::DefaultGraph => Ok(EncodedTerm::DefaultGraph), GraphNameRef::DefaultGraph => Ok(EncodedTerm::DefaultGraph),
} }
} }
fn encode_quad(&mut self, quad: &Quad) -> Result<EncodedQuad<Self::StrId>, Self::Error> { fn encode_quad(&mut self, quad: QuadRef<'_>) -> Result<EncodedQuad<Self::StrId>, Self::Error> {
Ok(EncodedQuad { Ok(EncodedQuad {
subject: self.encode_named_or_blank_node(&quad.subject)?, subject: self.encode_named_or_blank_node(quad.subject)?,
predicate: self.encode_named_node(&quad.predicate)?, predicate: self.encode_named_node(quad.predicate)?,
object: self.encode_term(&quad.object)?, object: self.encode_term(quad.object)?,
graph_name: self.encode_graph_name(&quad.graph_name)?, graph_name: self.encode_graph_name(quad.graph_name)?,
}) })
} }
fn encode_triple_in_graph( fn encode_triple_in_graph(
&mut self, &mut self,
triple: &Triple, triple: TripleRef<'_>,
graph_name: EncodedTerm<Self::StrId>, graph_name: EncodedTerm<Self::StrId>,
) -> Result<EncodedQuad<Self::StrId>, Self::Error> { ) -> Result<EncodedQuad<Self::StrId>, Self::Error> {
Ok(EncodedQuad { Ok(EncodedQuad {
subject: self.encode_named_or_blank_node(&triple.subject)?, subject: self.encode_named_or_blank_node(triple.subject)?,
predicate: self.encode_named_node(&triple.predicate)?, predicate: self.encode_named_node(triple.predicate)?,
object: self.encode_term(&triple.object)?, object: self.encode_term(triple.object)?,
graph_name, graph_name,
}) })
} }
@ -1433,16 +1433,19 @@ fn test_encoding() {
Literal::new_language_tagged_literal("foo-FR", "FR") Literal::new_language_tagged_literal("foo-FR", "FR")
.unwrap() .unwrap()
.into(), .into(),
Literal::new_typed_literal("-1.32", xsd::DECIMAL.clone()).into(), Literal::new_typed_literal("-1.32", xsd::DECIMAL).into(),
Literal::new_typed_literal("2020-01-01T01:01:01Z", xsd::DATE_TIME.clone()).into(), Literal::new_typed_literal("2020-01-01T01:01:01Z", xsd::DATE_TIME).into(),
Literal::new_typed_literal("2020-01-01", xsd::DATE.clone()).into(), Literal::new_typed_literal("2020-01-01", xsd::DATE).into(),
Literal::new_typed_literal("01:01:01Z", xsd::TIME.clone()).into(), Literal::new_typed_literal("01:01:01Z", xsd::TIME).into(),
Literal::new_typed_literal("PT1S", xsd::DURATION.clone()).into(), Literal::new_typed_literal("PT1S", xsd::DURATION).into(),
Literal::new_typed_literal("-foo", NamedNode::new_unchecked("http://foo.com")).into(), Literal::new_typed_literal("-foo", NamedNode::new_unchecked("http://foo.com")).into(),
]; ];
for term in terms { for term in terms {
let encoded = store.encode_term(&term).unwrap(); let encoded = store.encode_term(term.as_ref()).unwrap();
assert_eq!(Some(encoded), store.get_encoded_term(&term).unwrap()); assert_eq!(
Some(encoded),
store.get_encoded_term(term.as_ref()).unwrap()
);
assert_eq!(term, store.decode_term(encoded).unwrap()); assert_eq!(term, store.decode_term(encoded).unwrap());
} }
} }

@ -125,10 +125,10 @@ impl RocksDbStore {
/// See `MemoryStore` for a usage example. /// See `MemoryStore` for a usage example.
pub fn quads_for_pattern( pub fn quads_for_pattern(
&self, &self,
subject: Option<&NamedOrBlankNode>, subject: Option<NamedOrBlankNodeRef<'_>>,
predicate: Option<&NamedNode>, predicate: Option<NamedNodeRef<'_>>,
object: Option<&Term>, object: Option<TermRef<'_>>,
graph_name: Option<&GraphName>, graph_name: Option<GraphNameRef<'_>>,
) -> impl Iterator<Item = Result<Quad, io::Error>> { ) -> impl Iterator<Item = Result<Quad, io::Error>> {
match get_encoded_quad_pattern(self, subject, predicate, object, graph_name) { match get_encoded_quad_pattern(self, subject, predicate, object, graph_name) {
Ok(Some((subject, predicate, object, graph_name))) => QuadsIter::Quads { Ok(Some((subject, predicate, object, graph_name))) => QuadsIter::Quads {
@ -141,8 +141,8 @@ impl RocksDbStore {
} }
/// Checks if this store contains a given quad /// Checks if this store contains a given quad
pub fn contains(&self, quad: &Quad) -> Result<bool, io::Error> { pub fn contains<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> {
if let Some(quad) = self.get_encoded_quad(quad)? { if let Some(quad) = self.get_encoded_quad(quad.into())? {
self.contains_encoded(&quad) self.contains_encoded(&quad)
} else { } else {
Ok(false) Ok(false)
@ -194,15 +194,21 @@ impl RocksDbStore {
/// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind. /// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind.
/// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind. /// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind.
/// Errors related to data loading into the store use the other error kinds. /// Errors related to data loading into the store use the other error kinds.
pub fn load_graph( pub fn load_graph<'a>(
&self, &self,
reader: impl BufRead, reader: impl BufRead,
format: GraphFormat, format: GraphFormat,
to_graph_name: &GraphName, to_graph_name: impl Into<GraphNameRef<'a>>,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
let mut transaction = self.auto_batch_writer(); let mut transaction = self.auto_batch_writer();
load_graph(&mut transaction, reader, format, to_graph_name, base_iri)?; load_graph(
&mut transaction,
reader,
format,
to_graph_name.into(),
base_iri,
)?;
Ok(transaction.apply()?) Ok(transaction.apply()?)
} }
@ -228,16 +234,16 @@ impl RocksDbStore {
} }
/// Adds a quad to this store. /// Adds a quad to this store.
pub fn insert(&self, quad: &Quad) -> Result<(), io::Error> { pub fn insert<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<(), io::Error> {
let mut transaction = self.auto_batch_writer(); let mut transaction = self.auto_batch_writer();
let quad = transaction.encode_quad(quad)?; let quad = transaction.encode_quad(quad.into())?;
transaction.insert_encoded(&quad)?; transaction.insert_encoded(&quad)?;
transaction.apply() transaction.apply()
} }
/// Removes a quad from this store. /// Removes a quad from this store.
pub fn remove(&self, quad: &Quad) -> Result<(), io::Error> { pub fn remove<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<(), io::Error> {
if let Some(quad) = self.get_encoded_quad(quad)? { if let Some(quad) = self.get_encoded_quad(quad.into())? {
let mut transaction = self.auto_batch_writer(); let mut transaction = self.auto_batch_writer();
transaction.remove_encoded(&quad)?; transaction.remove_encoded(&quad)?;
transaction.apply() transaction.apply()
@ -249,14 +255,14 @@ impl RocksDbStore {
/// Dumps a store graph into a file. /// Dumps a store graph into a file.
/// ///
/// See `MemoryStore` for a usage example. /// See `MemoryStore` for a usage example.
pub fn dump_graph( pub fn dump_graph<'a>(
&self, &self,
writer: impl Write, writer: impl Write,
format: GraphFormat, format: GraphFormat,
from_graph_name: &GraphName, from_graph_name: impl Into<GraphNameRef<'a>>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
dump_graph( dump_graph(
self.quads_for_pattern(None, None, None, Some(from_graph_name)) self.quads_for_pattern(None, None, None, Some(from_graph_name.into()))
.map(|q| Ok(q?.into())), .map(|q| Ok(q?.into())),
writer, writer,
format, format,
@ -696,14 +702,14 @@ impl RocksDbTransaction<'_> {
/// ///
/// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind. /// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind.
/// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind. /// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind.
pub fn load_graph( pub fn load_graph<'a>(
&mut self, &mut self,
reader: impl BufRead, reader: impl BufRead,
syntax: GraphFormat, syntax: GraphFormat,
to_graph_name: &GraphName, to_graph_name: impl Into<GraphNameRef<'a>>,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
load_graph(self, reader, syntax, to_graph_name, base_iri)?; load_graph(self, reader, syntax, to_graph_name.into(), base_iri)?;
Ok(()) Ok(())
} }
@ -728,15 +734,15 @@ impl RocksDbTransaction<'_> {
} }
/// Adds a quad to this store during the transaction. /// Adds a quad to this store during the transaction.
pub fn insert(&mut self, quad: &Quad) -> Result<(), io::Error> { pub fn insert<'a>(&mut self, quad: impl Into<QuadRef<'a>>) -> Result<(), io::Error> {
let quad = self.encode_quad(quad)?; let quad = self.encode_quad(quad.into())?;
self.insert_encoded(&quad) self.insert_encoded(&quad)
} }
/// Removes a quad from this store during the transaction. /// Removes a quad from this store during the transaction.
pub fn remove(&mut self, quad: &Quad) -> Result<(), io::Error> { pub fn remove<'a>(&mut self, quad: impl Into<QuadRef<'a>>) -> Result<(), io::Error> {
// Works because all strings could be encoded // Works because all strings could be encoded
if let Some(quad) = self.get_encoded_quad(quad).unwrap() { if let Some(quad) = self.get_encoded_quad(quad.into()).unwrap() {
self.remove_encoded(&quad) self.remove_encoded(&quad)
} else { } else {
Ok(()) Ok(())
@ -1060,29 +1066,34 @@ fn store() -> Result<(), io::Error> {
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, None, None) .quads_for_pattern(Some(main_s.as_ref()), None, None, None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), Some(&main_p), None, None) .quads_for_pattern(Some(main_s.as_ref()), Some(main_p.as_ref()), None, None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), Some(&main_p), Some(&main_o), None) .quads_for_pattern(
Some(main_s.as_ref()),
Some(main_p.as_ref()),
Some(main_o.as_ref()),
None
)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern( .quads_for_pattern(
Some(&main_s), Some(main_s.as_ref()),
Some(&main_p), Some(main_p.as_ref()),
Some(&main_o), Some(main_o.as_ref()),
Some(&GraphName::DefaultGraph) Some(GraphNameRef::DefaultGraph)
) )
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
@ -1090,58 +1101,63 @@ fn store() -> Result<(), io::Error> {
assert_eq!( assert_eq!(
store store
.quads_for_pattern( .quads_for_pattern(
Some(&main_s), Some(main_s.as_ref()),
Some(&main_p), Some(main_p.as_ref()),
None, None,
Some(&GraphName::DefaultGraph) Some(GraphNameRef::DefaultGraph)
) )
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, Some(&main_o), None) .quads_for_pattern(Some(main_s.as_ref()), None, Some(main_o.as_ref()), None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern( .quads_for_pattern(
Some(&main_s), Some(main_s.as_ref()),
None, None,
Some(&main_o), Some(main_o.as_ref()),
Some(&GraphName::DefaultGraph) Some(GraphNameRef::DefaultGraph)
) )
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, None, Some(&GraphName::DefaultGraph)) .quads_for_pattern(
Some(main_s.as_ref()),
None,
None,
Some(GraphNameRef::DefaultGraph)
)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, Some(&main_p), None, None) .quads_for_pattern(None, Some(main_p.as_ref()), None, None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, Some(&main_p), Some(&main_o), None) .quads_for_pattern(None, Some(main_p.as_ref()), Some(main_o.as_ref()), None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, None, Some(&main_o), None) .quads_for_pattern(None, None, Some(main_o.as_ref()), None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, None, None, Some(&GraphName::DefaultGraph)) .quads_for_pattern(None, None, None, Some(GraphNameRef::DefaultGraph))
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
@ -1149,9 +1165,9 @@ fn store() -> Result<(), io::Error> {
store store
.quads_for_pattern( .quads_for_pattern(
None, None,
Some(&main_p), Some(main_p.as_ref()),
Some(&main_o), Some(main_o.as_ref()),
Some(&GraphName::DefaultGraph) Some(GraphNameRef::DefaultGraph)
) )
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target

@ -126,10 +126,10 @@ impl SledStore {
/// See `MemoryStore` for a usage example. /// See `MemoryStore` for a usage example.
pub fn quads_for_pattern( pub fn quads_for_pattern(
&self, &self,
subject: Option<&NamedOrBlankNode>, subject: Option<NamedOrBlankNodeRef<'_>>,
predicate: Option<&NamedNode>, predicate: Option<NamedNodeRef<'_>>,
object: Option<&Term>, object: Option<TermRef<'_>>,
graph_name: Option<&GraphName>, graph_name: Option<GraphNameRef<'_>>,
) -> impl Iterator<Item = Result<Quad, io::Error>> { ) -> impl Iterator<Item = Result<Quad, io::Error>> {
match get_encoded_quad_pattern(self, subject, predicate, object, graph_name) { match get_encoded_quad_pattern(self, subject, predicate, object, graph_name) {
Ok(Some((subject, predicate, object, graph_name))) => QuadsIter::Quads { Ok(Some((subject, predicate, object, graph_name))) => QuadsIter::Quads {
@ -142,8 +142,8 @@ impl SledStore {
} }
/// Checks if this store contains a given quad /// Checks if this store contains a given quad
pub fn contains(&self, quad: &Quad) -> Result<bool, io::Error> { pub fn contains<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<bool, io::Error> {
if let Some(quad) = self.get_encoded_quad(quad)? { if let Some(quad) = self.get_encoded_quad(quad.into())? {
self.contains_encoded(&quad) self.contains_encoded(&quad)
} else { } else {
Ok(false) Ok(false)
@ -205,15 +205,15 @@ impl SledStore {
/// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind. /// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind.
/// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind. /// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind.
/// Errors related to data loading into the store use the other error kinds. /// Errors related to data loading into the store use the other error kinds.
pub fn load_graph( pub fn load_graph<'a>(
&self, &self,
reader: impl BufRead, reader: impl BufRead,
format: GraphFormat, format: GraphFormat,
to_graph_name: &GraphName, to_graph_name: impl Into<GraphNameRef<'a>>,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
let mut this = self; let mut this = self;
load_graph(&mut this, reader, format, to_graph_name, base_iri)?; load_graph(&mut this, reader, format, to_graph_name.into(), base_iri)?;
Ok(()) Ok(())
} }
@ -239,15 +239,15 @@ impl SledStore {
} }
/// Adds a quad to this store. /// Adds a quad to this store.
pub fn insert(&self, quad: &Quad) -> Result<(), io::Error> { pub fn insert<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<(), io::Error> {
let mut this = self; let mut this = self;
let quad = this.encode_quad(quad)?; let quad = this.encode_quad(quad.into())?;
this.insert_encoded(&quad) this.insert_encoded(&quad)
} }
/// Removes a quad from this store. /// Removes a quad from this store.
pub fn remove(&self, quad: &Quad) -> Result<(), io::Error> { pub fn remove<'a>(&self, quad: impl Into<QuadRef<'a>>) -> Result<(), io::Error> {
if let Some(quad) = self.get_encoded_quad(quad)? { if let Some(quad) = self.get_encoded_quad(quad.into())? {
let mut this = self; let mut this = self;
this.remove_encoded(&quad) this.remove_encoded(&quad)
} else { } else {
@ -258,14 +258,14 @@ impl SledStore {
/// Dumps a store graph into a file. /// Dumps a store graph into a file.
/// ///
/// See `MemoryStore` for a usage example. /// See `MemoryStore` for a usage example.
pub fn dump_graph( pub fn dump_graph<'a>(
&self, &self,
writer: impl Write, writer: impl Write,
format: GraphFormat, format: GraphFormat,
from_graph_name: &GraphName, from_graph_name: impl Into<GraphNameRef<'a>>,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
dump_graph( dump_graph(
self.quads_for_pattern(None, None, None, Some(from_graph_name)) self.quads_for_pattern(None, None, None, Some(from_graph_name.into()))
.map(|q| Ok(q?.into())), .map(|q| Ok(q?.into())),
writer, writer,
format, format,
@ -601,15 +601,15 @@ impl SledTransaction<'_> {
/// ///
/// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind. /// Errors related to parameter validation like the base IRI use the `INVALID_INPUT` error kind.
/// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind. /// Errors related to a bad syntax in the loaded file use the `INVALID_DATA` error kind.
pub fn load_graph( pub fn load_graph<'a>(
&self, &self,
reader: impl BufRead, reader: impl BufRead,
format: GraphFormat, format: GraphFormat,
to_graph_name: &GraphName, to_graph_name: impl Into<GraphNameRef<'a>>,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<(), SledUnabortableTransactionError> { ) -> Result<(), SledUnabortableTransactionError> {
let mut this = self; let mut this = self;
load_graph(&mut this, reader, format, to_graph_name, base_iri)?; load_graph(&mut this, reader, format, to_graph_name.into(), base_iri)?;
Ok(()) Ok(())
} }
@ -635,16 +635,22 @@ impl SledTransaction<'_> {
} }
/// Adds a quad to this store during the transaction. /// Adds a quad to this store during the transaction.
pub fn insert(&self, quad: &Quad) -> Result<(), SledUnabortableTransactionError> { pub fn insert<'a>(
&self,
quad: impl Into<QuadRef<'a>>,
) -> Result<(), SledUnabortableTransactionError> {
let mut this = self; let mut this = self;
let quad = this.encode_quad(quad)?; let quad = this.encode_quad(quad.into())?;
this.insert_encoded(&quad) this.insert_encoded(&quad)
} }
/// Removes a quad from this store during the transaction. /// Removes a quad from this store during the transaction.
pub fn remove(&self, quad: &Quad) -> Result<(), SledUnabortableTransactionError> { pub fn remove<'a>(
&self,
quad: impl Into<QuadRef<'a>>,
) -> Result<(), SledUnabortableTransactionError> {
let mut this = self; let mut this = self;
if let Some(quad) = this.get_encoded_quad(quad)? { if let Some(quad) = this.get_encoded_quad(quad.into())? {
this.remove_encoded(&quad) this.remove_encoded(&quad)
} else { } else {
Ok(()) Ok(())
@ -1080,29 +1086,34 @@ fn store() -> Result<(), io::Error> {
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, None, None) .quads_for_pattern(Some(main_s.as_ref()), None, None, None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), Some(&main_p), None, None) .quads_for_pattern(Some(main_s.as_ref()), Some(main_p.as_ref()), None, None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), Some(&main_p), Some(&main_o), None) .quads_for_pattern(
Some(main_s.as_ref()),
Some(main_p.as_ref()),
Some(main_o.as_ref()),
None
)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern( .quads_for_pattern(
Some(&main_s), Some(main_s.as_ref()),
Some(&main_p), Some(main_p.as_ref()),
Some(&main_o), Some(main_o.as_ref()),
Some(&GraphName::DefaultGraph) Some(GraphNameRef::DefaultGraph)
) )
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
@ -1110,58 +1121,63 @@ fn store() -> Result<(), io::Error> {
assert_eq!( assert_eq!(
store store
.quads_for_pattern( .quads_for_pattern(
Some(&main_s), Some(main_s.as_ref()),
Some(&main_p), Some(main_p.as_ref()),
None, None,
Some(&GraphName::DefaultGraph) Some(GraphNameRef::DefaultGraph)
) )
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, Some(&main_o), None) .quads_for_pattern(Some(main_s.as_ref()), None, Some(main_o.as_ref()), None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern( .quads_for_pattern(
Some(&main_s), Some(main_s.as_ref()),
None, None,
Some(&main_o), Some(main_o.as_ref()),
Some(&GraphName::DefaultGraph) Some(GraphNameRef::DefaultGraph)
) )
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, None, Some(&GraphName::DefaultGraph)) .quads_for_pattern(
Some(main_s.as_ref()),
None,
None,
Some(GraphNameRef::DefaultGraph)
)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, Some(&main_p), None, None) .quads_for_pattern(None, Some(main_p.as_ref()), None, None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, Some(&main_p), Some(&main_o), None) .quads_for_pattern(None, Some(main_p.as_ref()), Some(main_o.as_ref()), None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, None, Some(&main_o), None) .quads_for_pattern(None, None, Some(main_o.as_ref()), None)
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, None, None, Some(&GraphName::DefaultGraph)) .quads_for_pattern(None, None, None, Some(GraphNameRef::DefaultGraph))
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
all_o all_o
); );
@ -1169,9 +1185,9 @@ fn store() -> Result<(), io::Error> {
store store
.quads_for_pattern( .quads_for_pattern(
None, None,
Some(&main_p), Some(main_p.as_ref()),
Some(&main_o), Some(main_o.as_ref()),
Some(&GraphName::DefaultGraph) Some(GraphNameRef::DefaultGraph)
) )
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
target target

@ -47,10 +47,10 @@ impl PyMemoryStore {
extract_quads_pattern(subject, predicate, object, graph_name)?; extract_quads_pattern(subject, predicate, object, graph_name)?;
Ok(QuadIter { Ok(QuadIter {
inner: Box::new(self.inner.quads_for_pattern( inner: Box::new(self.inner.quads_for_pattern(
subject.as_ref(), subject.as_ref().map(|t| t.into()),
predicate.as_ref(), predicate.as_ref().map(|t| t.into()),
object.as_ref(), object.as_ref().map(|t| t.into()),
graph_name.as_ref(), graph_name.as_ref().map(|t| t.into()),
)), )),
}) })
} }

@ -214,7 +214,7 @@ impl PyLiteral {
#[getter] #[getter]
fn datatype(&self) -> PyNamedNode { fn datatype(&self) -> PyNamedNode {
self.inner.datatype().clone().into() self.inner.datatype().into_owned().into()
} }
} }

@ -49,10 +49,10 @@ impl PySledStore {
extract_quads_pattern(subject, predicate, object, graph_name)?; extract_quads_pattern(subject, predicate, object, graph_name)?;
Ok(QuadIter { Ok(QuadIter {
inner: Box::new(self.inner.quads_for_pattern( inner: Box::new(self.inner.quads_for_pattern(
subject.as_ref(), subject.as_ref().map(|t| t.into()),
predicate.as_ref(), predicate.as_ref().map(|t| t.into()),
object.as_ref(), object.as_ref().map(|t| t.into()),
graph_name.as_ref(), graph_name.as_ref().map(|t| t.into()),
)), )),
}) })
} }

@ -14,7 +14,6 @@ publish = false
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
chrono = "0.4" chrono = "0.4"
lazy_static = "1"
oxigraph = { path = "../lib" } oxigraph = { path = "../lib" }
[dev-dependencies] [dev-dependencies]

@ -72,57 +72,50 @@ impl Iterator for TestManifest {
fn next(&mut self) -> Option<Result<Test>> { fn next(&mut self) -> Option<Result<Test>> {
match self.tests_to_do.pop() { match self.tests_to_do.pop() {
Some(Term::NamedNode(test_node)) => { Some(Term::NamedNode(test_node)) => {
let test_subject = NamedOrBlankNode::from(test_node.clone()); let kind = match object_for_subject_predicate(&self.graph, &test_node, rdf::TYPE) {
let kind =
match object_for_subject_predicate(&self.graph, &test_subject, &rdf::TYPE) {
Some(Term::NamedNode(c)) => c, Some(Term::NamedNode(c)) => c,
_ => return self.next(), //We ignore the test _ => return self.next(), //We ignore the test
}; };
let name = match object_for_subject_predicate(&self.graph, &test_subject, &mf::NAME) let name = match object_for_subject_predicate(&self.graph, &test_node, mf::NAME) {
{
Some(Term::Literal(c)) => Some(c.value().to_string()), Some(Term::Literal(c)) => Some(c.value().to_string()),
_ => None, _ => None,
}; };
let comment = match object_for_subject_predicate( let comment =
&self.graph, match object_for_subject_predicate(&self.graph, &test_node, rdfs::COMMENT) {
&test_subject,
&rdfs::COMMENT,
) {
Some(Term::Literal(c)) => Some(c.value().to_string()), Some(Term::Literal(c)) => Some(c.value().to_string()),
_ => None, _ => None,
}; };
let (action, query, data, graph_data, service_data) = let (action, query, data, graph_data, service_data) =
match object_for_subject_predicate(&self.graph, &test_subject, &*mf::ACTION) { match object_for_subject_predicate(&self.graph, &test_node, mf::ACTION) {
Some(Term::NamedNode(n)) => { Some(Term::NamedNode(n)) => {
(Some(n.into_string()), None, None, vec![], vec![]) (Some(n.into_string()), None, None, vec![], vec![])
} }
Some(Term::BlankNode(n)) => { Some(Term::BlankNode(n)) => {
let n = n.into();
let query = let query =
match object_for_subject_predicate(&self.graph, &n, &qt::QUERY) { match object_for_subject_predicate(&self.graph, &n, qt::QUERY) {
Some(Term::NamedNode(q)) => Some(q.into_string()), Some(Term::NamedNode(q)) => Some(q.into_string()),
_ => None, _ => None,
}; };
let data = let data = match object_for_subject_predicate(&self.graph, &n, qt::DATA)
match object_for_subject_predicate(&self.graph, &n, &qt::DATA) { {
Some(Term::NamedNode(q)) => Some(q.into_string()), Some(Term::NamedNode(q)) => Some(q.into_string()),
_ => None, _ => None,
}; };
let graph_data = let graph_data =
objects_for_subject_predicate(&self.graph, &n, &qt::GRAPH_DATA) objects_for_subject_predicate(&self.graph, &n, qt::GRAPH_DATA)
.filter_map(|g| match g { .filter_map(|g| match g {
Term::NamedNode(q) => Some(q.into_string()), Term::NamedNode(q) => Some(q.into_string()),
_ => None, _ => None,
}) })
.collect(); .collect();
let service_data = let service_data =
objects_for_subject_predicate(&self.graph, &n, &qt::SERVICE_DATA) objects_for_subject_predicate(&self.graph, &n, qt::SERVICE_DATA)
.filter_map(|g| match g { .filter_map(|g| match g {
Term::NamedNode(g) => Some(g.into()), Term::NamedNode(g) => Some(g.into()),
Term::BlankNode(g) => Some(g.into()), Term::BlankNode(g) => Some(g.into()),
_ => None, _ => None,
}) })
.filter_map(|g| { .filter_map(|g: NamedOrBlankNode| {
if let ( if let (
Some(Term::NamedNode(endpoint)), Some(Term::NamedNode(endpoint)),
Some(Term::NamedNode(data)), Some(Term::NamedNode(data)),
@ -130,13 +123,9 @@ impl Iterator for TestManifest {
object_for_subject_predicate( object_for_subject_predicate(
&self.graph, &self.graph,
&g, &g,
&qt::ENDPOINT, qt::ENDPOINT,
),
object_for_subject_predicate(
&self.graph,
&g,
&qt::DATA,
), ),
object_for_subject_predicate(&self.graph, &g, qt::DATA),
) { ) {
Some((endpoint.into_string(), data.into_string())) Some((endpoint.into_string(), data.into_string()))
} else { } else {
@ -148,14 +137,11 @@ impl Iterator for TestManifest {
} }
Some(_) => return Some(Err(anyhow!("invalid action"))), Some(_) => return Some(Err(anyhow!("invalid action"))),
None => { None => {
return Some(Err(anyhow!( return Some(Err(anyhow!("action not found for test {}", test_node)));
"action not found for test {}",
test_subject
)));
} }
}; };
let result = let result = match object_for_subject_predicate(&self.graph, &test_node, mf::RESULT)
match object_for_subject_predicate(&self.graph, &test_subject, &*mf::RESULT) { {
Some(Term::NamedNode(n)) => Some(n.into_string()), Some(Term::NamedNode(n)) => Some(n.into_string()),
Some(_) => return Some(Err(anyhow!("invalid result"))), Some(_) => return Some(Err(anyhow!("invalid result"))),
None => None, None => None,
@ -177,7 +163,8 @@ impl Iterator for TestManifest {
None => { None => {
match self.manifests_to_do.pop() { match self.manifests_to_do.pop() {
Some(url) => { Some(url) => {
let manifest = NamedOrBlankNode::from(NamedNode::new(url.clone()).unwrap()); let manifest =
NamedOrBlankNodeRef::from(NamedNodeRef::new(url.as_str()).unwrap());
if let Err(error) = if let Err(error) =
load_to_store(&url, &self.graph, &&GraphName::DefaultGraph) load_to_store(&url, &self.graph, &&GraphName::DefaultGraph)
{ {
@ -185,7 +172,7 @@ impl Iterator for TestManifest {
} }
// New manifests // New manifests
match object_for_subject_predicate(&self.graph, &manifest, &*mf::INCLUDE) { match object_for_subject_predicate(&self.graph, manifest, mf::INCLUDE) {
Some(Term::BlankNode(list)) => { Some(Term::BlankNode(list)) => {
self.manifests_to_do.extend( self.manifests_to_do.extend(
RdfListIterator::iter(&self.graph, list.into()).filter_map( RdfListIterator::iter(&self.graph, list.into()).filter_map(
@ -201,7 +188,7 @@ impl Iterator for TestManifest {
} }
// New tests // New tests
match object_for_subject_predicate(&self.graph, &manifest, &*mf::ENTRIES) { match object_for_subject_predicate(&self.graph, manifest, mf::ENTRIES) {
Some(Term::BlankNode(list)) => { Some(Term::BlankNode(list)) => {
self.tests_to_do self.tests_to_do
.extend(RdfListIterator::iter(&self.graph, list.into())); .extend(RdfListIterator::iter(&self.graph, list.into()));
@ -240,10 +227,10 @@ impl<'a> Iterator for RdfListIterator<'a> {
fn next(&mut self) -> Option<Term> { fn next(&mut self) -> Option<Term> {
match self.current_node.clone() { match self.current_node.clone() {
Some(current) => { Some(current) => {
let result = object_for_subject_predicate(&self.graph, &current, &rdf::FIRST); let result = object_for_subject_predicate(&self.graph, &current, rdf::FIRST);
self.current_node = self.current_node =
match object_for_subject_predicate(&self.graph, &current, &rdf::REST) { match object_for_subject_predicate(&self.graph, &current, rdf::REST) {
Some(Term::NamedNode(ref n)) if *n == *rdf::NIL => None, Some(Term::NamedNode(n)) if n == rdf::NIL => None,
Some(Term::NamedNode(n)) => Some(n.into()), Some(Term::NamedNode(n)) => Some(n.into()),
Some(Term::BlankNode(n)) => Some(n.into()), Some(Term::BlankNode(n)) => Some(n.into()),
_ => None, _ => None,
@ -255,20 +242,20 @@ impl<'a> Iterator for RdfListIterator<'a> {
} }
} }
fn object_for_subject_predicate( fn object_for_subject_predicate<'a>(
store: &MemoryStore, store: &MemoryStore,
subject: &NamedOrBlankNode, subject: impl Into<NamedOrBlankNodeRef<'a>>,
predicate: &NamedNode, predicate: impl Into<NamedNodeRef<'a>>,
) -> Option<Term> { ) -> Option<Term> {
objects_for_subject_predicate(store, subject, predicate).next() objects_for_subject_predicate(store, subject, predicate).next()
} }
fn objects_for_subject_predicate( fn objects_for_subject_predicate<'a>(
store: &MemoryStore, store: &MemoryStore,
subject: &NamedOrBlankNode, subject: impl Into<NamedOrBlankNodeRef<'a>>,
predicate: &NamedNode, predicate: impl Into<NamedNodeRef<'a>>,
) -> impl Iterator<Item = Term> { ) -> impl Iterator<Item = Term> {
store store
.quads_for_pattern(Some(subject), Some(predicate), None, None) .quads_for_pattern(Some(subject.into()), Some(predicate.into()), None, None)
.map(|t| t.object) .map(|t| t.object)
} }

@ -200,13 +200,13 @@ fn to_dataset(result: QueryResult, with_order: bool) -> Result<MemoryStore> {
let result_set = BlankNode::default(); let result_set = BlankNode::default();
store.insert(Quad::new( store.insert(Quad::new(
result_set.clone(), result_set.clone(),
rdf::TYPE.clone(), rdf::TYPE,
rs::RESULT_SET.clone(), rs::RESULT_SET,
None, None,
)); ));
store.insert(Quad::new( store.insert(Quad::new(
result_set, result_set,
rs::BOOLEAN.clone(), rs::BOOLEAN,
Literal::from(value), Literal::from(value),
None, None,
)); ));
@ -217,14 +217,14 @@ fn to_dataset(result: QueryResult, with_order: bool) -> Result<MemoryStore> {
let result_set = BlankNode::default(); let result_set = BlankNode::default();
store.insert(Quad::new( store.insert(Quad::new(
result_set.clone(), result_set.clone(),
rdf::TYPE.clone(), rdf::TYPE,
rs::RESULT_SET.clone(), rs::RESULT_SET,
None, None,
)); ));
for variable in solutions.variables() { for variable in solutions.variables() {
store.insert(Quad::new( store.insert(Quad::new(
result_set.clone(), result_set.clone(),
rs::RESULT_VARIABLE.clone(), rs::RESULT_VARIABLE,
Literal::new_simple_literal(variable.as_str()), Literal::new_simple_literal(variable.as_str()),
None, None,
)); ));
@ -234,7 +234,7 @@ fn to_dataset(result: QueryResult, with_order: bool) -> Result<MemoryStore> {
let solution_id = BlankNode::default(); let solution_id = BlankNode::default();
store.insert(Quad::new( store.insert(Quad::new(
result_set.clone(), result_set.clone(),
rs::SOLUTION.clone(), rs::SOLUTION,
solution_id.clone(), solution_id.clone(),
None, None,
)); ));
@ -242,19 +242,14 @@ fn to_dataset(result: QueryResult, with_order: bool) -> Result<MemoryStore> {
let binding = BlankNode::default(); let binding = BlankNode::default();
store.insert(Quad::new( store.insert(Quad::new(
solution_id.clone(), solution_id.clone(),
rs::BINDING.clone(), rs::BINDING,
binding.clone(), binding.clone(),
None, None,
)); ));
store.insert(Quad::new( store.insert(Quad::new(binding.clone(), rs::VALUE, value.clone(), None));
binding.clone(),
rs::VALUE.clone(),
value.clone(),
None,
));
store.insert(Quad::new( store.insert(Quad::new(
binding, binding,
rs::VARIABLE.clone(), rs::VARIABLE,
Literal::new_simple_literal(variable.as_str()), Literal::new_simple_literal(variable.as_str()),
None, None,
)); ));
@ -262,7 +257,7 @@ fn to_dataset(result: QueryResult, with_order: bool) -> Result<MemoryStore> {
if with_order { if with_order {
store.insert(Quad::new( store.insert(Quad::new(
solution_id, solution_id,
rs::INDEX.clone(), rs::INDEX,
Literal::from((i + 1) as i128), Literal::from((i + 1) as i128),
None, None,
)); ));
@ -374,28 +369,19 @@ impl StaticQueryResults {
fn from_dataset(dataset: MemoryStore) -> StaticQueryResults { fn from_dataset(dataset: MemoryStore) -> StaticQueryResults {
if let Some(result_set) = dataset if let Some(result_set) = dataset
.quads_for_pattern( .quads_for_pattern(None, Some(rdf::TYPE), Some(rs::RESULT_SET.into()), None)
None,
Some(&rdf::TYPE),
Some(&rs::RESULT_SET.clone().into()),
None,
)
.map(|q| q.subject) .map(|q| q.subject)
.next() .next()
{ {
if let Some(bool) = dataset if let Some(bool) = object_for_subject_predicate(&dataset, &result_set, rs::BOOLEAN) {
.quads_for_pattern(Some(&result_set), Some(&rs::BOOLEAN), None, None)
.map(|q| q.object)
.next()
{
// Boolean query // Boolean query
StaticQueryResults::Boolean(bool == Literal::from(true).into()) StaticQueryResults::Boolean(bool == Literal::from(true).into())
} else { } else {
// Regular query // Regular query
let mut variables: Vec<Variable> = dataset let mut variables: Vec<Variable> =
.quads_for_pattern(Some(&result_set), Some(&rs::RESULT_VARIABLE), None, None) objects_for_subject_predicate(&dataset, &result_set, rs::RESULT_VARIABLE)
.filter_map(|q| { .filter_map(|object| {
if let Term::Literal(l) = q.object { if let Term::Literal(l) = object {
Some(Variable::new(l.value())) Some(Variable::new(l.value()))
} else { } else {
None None
@ -404,35 +390,28 @@ impl StaticQueryResults {
.collect(); .collect();
variables.sort(); variables.sort();
let mut solutions: Vec<_> = dataset let mut solutions: Vec<_> =
.quads_for_pattern(Some(&result_set), Some(&rs::SOLUTION), None, None) objects_for_subject_predicate(&dataset, &result_set, rs::SOLUTION)
.filter_map(|q| { .filter_map(|object| {
if let Term::BlankNode(solution) = q.object { if let Term::BlankNode(solution) = object {
let solution = solution.into(); let mut bindings =
let mut bindings = dataset objects_for_subject_predicate(&dataset, &solution, rs::BINDING)
.quads_for_pattern(Some(&solution), Some(&rs::BINDING), None, None) .filter_map(|object| {
.filter_map(|q| { if let Term::BlankNode(binding) = object {
if let Term::BlankNode(binding) = q.object { if let (
let binding = binding.into(); Some(Term::Literal(variable)),
if let (Some(Term::Literal(variable)), Some(value)) = ( Some(value),
dataset ) = (
.quads_for_pattern( object_for_subject_predicate(
Some(&binding), &dataset,
Some(&rs::VARIABLE), &binding,
None, rs::VARIABLE,
None, ),
) object_for_subject_predicate(
.map(|q| q.object) &dataset,
.next(), &binding,
dataset rs::VALUE,
.quads_for_pattern( ),
Some(&binding),
Some(&rs::VALUE),
None,
None,
)
.map(|q| q.object)
.next(),
) { ) {
Some((Variable::new(variable.value()), value)) Some((Variable::new(variable.value()), value))
} else { } else {
@ -444,16 +423,15 @@ impl StaticQueryResults {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
bindings.sort_by(|(a, _), (b, _)| a.cmp(&b)); bindings.sort_by(|(a, _), (b, _)| a.cmp(&b));
let index = dataset let index =
.quads_for_pattern(Some(&solution), Some(&rs::INDEX), None, None) object_for_subject_predicate(&dataset, &solution, rs::INDEX)
.filter_map(|q| { .and_then(|object| {
if let Term::Literal(l) = q.object { if let Term::Literal(l) = object {
u64::from_str(l.value()).ok() u64::from_str(l.value()).ok()
} else { } else {
None None
} }
}) });
.next();
Some((bindings, index)) Some((bindings, index))
} else { } else {
None None
@ -478,3 +456,21 @@ impl StaticQueryResults {
} }
} }
} }
fn object_for_subject_predicate<'a>(
store: &MemoryStore,
subject: impl Into<NamedOrBlankNodeRef<'a>>,
predicate: impl Into<NamedNodeRef<'a>>,
) -> Option<Term> {
objects_for_subject_predicate(store, subject, predicate).next()
}
fn objects_for_subject_predicate<'a>(
store: &MemoryStore,
subject: impl Into<NamedOrBlankNodeRef<'a>>,
predicate: impl Into<NamedNodeRef<'a>>,
) -> impl Iterator<Item = Term> {
store
.quads_for_pattern(Some(subject.into()), Some(predicate.into()), None, None)
.map(|t| t.object)
}

@ -1,73 +1,64 @@
pub mod rs { pub mod rs {
use lazy_static::lazy_static; use oxigraph::model::NamedNodeRef;
use oxigraph::model::NamedNode;
lazy_static! { pub const RESULT_SET: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref RESULT_SET: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/result-set#ResultSet",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#ResultSet") );
.unwrap(); pub const RESULT_VARIABLE: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref RESULT_VARIABLE: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/result-set#resultVariable",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#resultVariable") );
.unwrap(); pub const SOLUTION: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref SOLUTION: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/result-set#solution",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#solution") );
.unwrap(); pub const BINDING: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref BINDING: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/result-set#binding",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#binding") );
.unwrap(); pub const VALUE: NamedNodeRef<'_> =
pub static ref VALUE: NamedNode = NamedNodeRef::new_unchecked("http://www.w3.org/2001/sw/DataAccess/tests/result-set#value");
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#value").unwrap(); pub const VARIABLE: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref VARIABLE: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/result-set#variable",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#variable") );
.unwrap(); pub const INDEX: NamedNodeRef<'_> =
pub static ref INDEX: NamedNode = NamedNodeRef::new_unchecked("http://www.w3.org/2001/sw/DataAccess/tests/result-set#index");
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#index").unwrap(); pub const BOOLEAN: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref BOOLEAN: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/result-set#boolean",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#boolean") );
.unwrap();
}
} }
pub mod mf { pub mod mf {
use lazy_static::lazy_static; use oxigraph::model::NamedNodeRef;
use oxigraph::model::NamedNode;
lazy_static! { pub const INCLUDE: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref INCLUDE: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#include",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#include") );
.unwrap(); pub const ENTRIES: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref ENTRIES: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#entries",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#entries") );
.unwrap(); pub const NAME: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref NAME: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#name",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#name") );
.unwrap(); pub const ACTION: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref ACTION: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#action",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#action") );
.unwrap(); pub const RESULT: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref RESULT: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#result",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#result") );
.unwrap();
}
} }
pub mod qt { pub mod qt {
use lazy_static::lazy_static; use oxigraph::model::NamedNodeRef;
use oxigraph::model::NamedNode;
lazy_static! { pub const QUERY: NamedNodeRef<'_> =
pub static ref QUERY: NamedNode = NamedNodeRef::new_unchecked("http://www.w3.org/2001/sw/DataAccess/tests/test-query#query");
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-query#query").unwrap(); pub const DATA: NamedNodeRef<'_> =
pub static ref DATA: NamedNode = NamedNodeRef::new_unchecked("http://www.w3.org/2001/sw/DataAccess/tests/test-query#data");
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-query#data").unwrap(); pub const GRAPH_DATA: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref GRAPH_DATA: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/test-query#graphData",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-query#graphData") );
.unwrap(); pub const SERVICE_DATA: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref SERVICE_DATA: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/test-query#serviceData",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-query#serviceData") );
.unwrap(); pub const ENDPOINT: NamedNodeRef<'_> = NamedNodeRef::new_unchecked(
pub static ref ENDPOINT: NamedNode = "http://www.w3.org/2001/sw/DataAccess/tests/test-query#endpoint",
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-query#endpoint") );
.unwrap();
}
} }

@ -6,7 +6,7 @@ use http_client::h1::H1Client;
use http_client::HttpClient; use http_client::HttpClient;
use http_types::{headers, Method, Request, Result}; use http_types::{headers, Method, Request, Result};
use oxigraph::io::GraphFormat; use oxigraph::io::GraphFormat;
use oxigraph::model::NamedNode; use oxigraph::model::NamedNodeRef;
use oxigraph::RocksDbStore; use oxigraph::RocksDbStore;
use serde_json::Value; use serde_json::Value;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
@ -230,11 +230,11 @@ impl WikibaseLoader {
} }
fn load_entity_data(&self, uri: &str, data: impl Read) -> Result<()> { fn load_entity_data(&self, uri: &str, data: impl Read) -> Result<()> {
let graph_name = NamedNode::new(uri)?.into(); let graph_name = NamedNodeRef::new(uri)?.into();
self.store.transaction(|transaction| { self.store.transaction(|transaction| {
let to_remove = self let to_remove = self
.store .store
.quads_for_pattern(None, None, None, Some(&graph_name)) .quads_for_pattern(None, None, None, Some(graph_name))
.collect::<std::result::Result<Vec<_>, _>>()?; .collect::<std::result::Result<Vec<_>, _>>()?;
for q in to_remove { for q in to_remove {
transaction.remove(&q)?; transaction.remove(&q)?;
@ -243,7 +243,7 @@ impl WikibaseLoader {
transaction.load_graph( transaction.load_graph(
BufReader::new(data), BufReader::new(data),
GraphFormat::NTriples, GraphFormat::NTriples,
&NamedNode::new(uri)?.into(), NamedNodeRef::new(uri)?,
None, None,
)?; )?;
Ok(()) Ok(())

Loading…
Cancel
Save