Makes Oxigraph model standalone as oxrdf

Allows to reuse it in other crates like spargebra
pull/190/head
Tpt 3 years ago
parent 4337349aad
commit f5545f1948
  1. 13
      Cargo.lock
  2. 1
      Cargo.toml
  3. 3
      lib/Cargo.toml
  4. 24
      lib/oxrdf/Cargo.toml
  5. 47
      lib/oxrdf/README.md
  6. 32
      lib/oxrdf/src/blank_node.rs
  7. 26
      lib/oxrdf/src/dataset.rs
  8. 14
      lib/oxrdf/src/graph.rs
  9. 2
      lib/oxrdf/src/interning.rs
  10. 51
      lib/oxrdf/src/lib.rs
  11. 169
      lib/oxrdf/src/literal.rs
  12. 8
      lib/oxrdf/src/named_node.rs
  13. 20
      lib/oxrdf/src/parser.rs
  14. 2
      lib/oxrdf/src/sophia.rs
  15. 8
      lib/oxrdf/src/triple.rs
  16. 121
      lib/oxrdf/src/variable.rs
  17. 6
      lib/oxrdf/src/vocab.rs
  18. 108
      lib/src/model.rs
  19. 28
      lib/src/model/mod.rs
  20. 1
      lib/src/sparql/eval.rs
  21. 2
      lib/src/sparql/io/csv.rs
  22. 2
      lib/src/sparql/io/json.rs
  23. 2
      lib/src/sparql/io/xml.rs
  24. 6
      lib/src/sparql/mod.rs
  25. 124
      lib/src/sparql/model.rs
  26. 2
      lib/src/sparql/plan.rs
  27. 2
      lib/src/sparql/plan_builder.rs
  28. 2
      lib/src/storage/numeric_encoder.rs

13
Cargo.lock generated

@ -845,6 +845,7 @@ dependencies = [
"oxhttp",
"oxilangtag",
"oxiri",
"oxrdf",
"oxrocksdb-sys",
"quick-xml",
"rand",
@ -908,6 +909,18 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e54fb37480ffa01a9af93f991ba229b3091f2e6ac84c8f6df2c509356cc473"
[[package]]
name = "oxrdf"
version = "0.1.0"
dependencies = [
"lasso",
"oxilangtag",
"oxiri",
"rand",
"rio_api",
"sophia_api",
]
[[package]]
name = "oxrocksdb-sys"
version = "0.3.0-dev"

@ -2,6 +2,7 @@
members = [
"js",
"lib",
"lib/oxrdf",
"python",
"rocksdb-sys",
"server",

@ -18,7 +18,7 @@ all-features = true
[features]
default = []
sophia = ["sophia_api"]
sophia = ["sophia_api", "oxrdf/sophia_api"]
http_client = ["oxhttp", "oxhttp/rustls"]
[dependencies]
@ -42,6 +42,7 @@ lazy_static = "1"
sophia_api = { version = "0.7", optional = true }
json-event-parser = "0.1"
num_cpus = "1"
oxrdf = { version = "0.1", path="oxrdf" }
spargebra = { version = "0.1", path="../spargebra", features = ["rdf-star"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]

@ -0,0 +1,24 @@
[package]
name = "oxrdf"
version = "0.1.0"
authors = ["Tpt <thomas@pellissier-tanon.fr>"]
license = "MIT OR Apache-2.0"
readme = "README.md"
keywords = ["RDF"]
repository = "https://github.com/oxigraph/oxigraph/tree/master/lib/oxrdf"
homepage = "https://oxigraph.org/"
description = """
A library providing basic data structures related to RDF
"""
edition = "2021"
[dependencies]
rand = "0.8"
oxilangtag = "0.1"
oxiri = "0.1"
rio_api = "0.6"
lasso = {version="0.6", features=["multi-threaded", "inline-more"]}
sophia_api = { version = "0.7", optional = true }
[package.metadata.docs.rs]
all-features = true

@ -0,0 +1,47 @@
OxRDF
=====
[![Latest Version](https://img.shields.io/crates/v/oxrdf.svg)](https://crates.io/crates/oxrdf)
[![Released API docs](https://docs.rs/oxrdf/badge.svg)](https://docs.rs/oxrdf)
[![Crates.io downloads](https://img.shields.io/crates/d/oxrdf)](https://crates.io/crates/oxrdf)
[![actions status](https://github.com/oxigraph/oxigraph/workflows/build/badge.svg)](https://github.com/oxigraph/oxigraph/actions)
[![Gitter](https://badges.gitter.im/oxigraph/community.svg)](https://gitter.im/oxigraph/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
OxRDF is a simple library providing datastructures encoding [RDF 1.1 concepts](https://www.w3.org/TR/rdf11-concepts/).
This crate is intended to be a basic building block of other crates like [Oxigraph](https://crates.io/crates/oxigraph) or [Spargebra](https://crates.io/crates/spargebra).
Inspired by [RDF/JS](https://rdf.js.org/data-model-spec/) and [Apache Commons RDF](http://commons.apache.org/proper/commons-rdf/).
Usage example:
```rust
use oxrdf::*;
let mut graph = Graph::default();
// insertion
let ex = NamedNodeRef::new("http://example.com")?;
let triple = TripleRef::new(ex, ex, ex);
graph.insert(triple);
// simple filter
let results: Vec<_> = graph.triples_for_subject(ex).collect();
assert_eq!(vec![triple], results);
```
## License
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](../LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](../LICENSE-MIT) or
http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Futures by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

@ -14,13 +14,13 @@ use std::str;
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation:
/// ```
/// use oxigraph::model::BlankNode;
/// use oxrdf::BlankNode;
///
/// assert_eq!(
/// "_:a122",
/// BlankNode::new("a122")?.to_string()
/// );
/// # Result::<_,oxigraph::model::BlankNodeIdParseError>::Ok(())
/// # Result::<_,oxrdf::BlankNodeIdParseError>::Ok(())
/// ```
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct BlankNode(BlankNodeContent);
@ -62,8 +62,8 @@ impl BlankNode {
/// Creates a blank node from a unique numerical id
///
/// 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 {
let id = id.into();
#[inline]
pub fn new_from_unique_id(id: u128) -> Self {
Self(BlankNodeContent::Anonymous {
id,
str: IdStr::new(id),
@ -124,13 +124,13 @@ impl Default for BlankNode {
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation:
/// ```
/// use oxigraph::model::BlankNodeRef;
/// use oxrdf::BlankNodeRef;
///
/// assert_eq!(
/// "_:a122",
/// BlankNodeRef::new("a122")?.to_string()
/// );
/// # Result::<_,oxigraph::model::BlankNodeIdParseError>::Ok(())
/// # Result::<_,oxrdf::BlankNodeIdParseError>::Ok(())
/// ```
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub struct BlankNodeRef<'a>(BlankNodeRefContent<'a>);
@ -179,9 +179,17 @@ impl<'a> BlankNodeRef<'a> {
}
}
/// Returns the internal numerical ID of this blank node, if it exists
/// Returns the internal numerical ID of this blank node if it has been created using [`BlankNode::new_from_unique_id`]
///
/// ```
/// use oxrdf::BlankNode;
///
/// assert_eq!(BlankNode::new_from_unique_id(128).as_ref().unique_id(), Some(128));
/// assert_eq!(BlankNode::new("128")?.as_ref().unique_id(), None);
/// # Result::<_,oxrdf::BlankNodeIdParseError>::Ok(())
/// ```
#[inline]
pub(crate) fn id(&self) -> Option<u128> {
pub fn unique_id(&self) -> Option<u128> {
match self.0 {
BlankNodeRefContent::Named(_) => None,
BlankNodeRefContent::Anonymous { id, .. } => Some(id),
@ -349,13 +357,13 @@ mod tests {
#[test]
fn as_str_partial() {
let b = BlankNode::new_from_unique_id(0x42_u128);
let b = BlankNode::new_from_unique_id(0x42);
assert_eq!(b.as_str(), "42");
}
#[test]
fn as_str_full() {
let b = BlankNode::new_from_unique_id(0x7777_6666_5555_4444_3333_2222_1111_0000_u128);
let b = BlankNode::new_from_unique_id(0x7777_6666_5555_4444_3333_2222_1111_0000);
assert_eq!(b.as_str(), "77776666555544443333222211110000");
}
@ -374,11 +382,11 @@ mod tests {
fn new_numerical() {
assert_eq!(
BlankNode::new("100a").unwrap(),
BlankNode::new_from_unique_id(0x100a_u128),
BlankNode::new_from_unique_id(0x100a),
);
assert_ne!(
BlankNode::new("100A").unwrap(),
BlankNode::new_from_unique_id(0x100a_u128)
BlankNode::new_from_unique_id(0x100a)
);
}

@ -2,7 +2,7 @@
//!
//! Usage example:
//! ```
//! use oxigraph::model::*;
//! use oxrdf::*;
//!
//! let mut dataset = Dataset::default();
//!
@ -23,9 +23,9 @@
//!
//! See also [`Graph`](super::Graph) if you only care about plain triples.
use crate::model::interning::*;
use crate::model::SubjectRef;
use crate::model::*;
use crate::interning::*;
use crate::SubjectRef;
use crate::*;
use std::collections::hash_map::DefaultHasher;
use std::collections::BTreeSet;
use std::collections::{HashMap, HashSet};
@ -40,7 +40,7 @@ use std::hash::{Hash, Hasher};
///
/// Usage example:
/// ```
/// use oxigraph::model::*;
/// use oxrdf::*;
///
/// let mut dataset = Dataset::default();
///
@ -108,7 +108,7 @@ impl Dataset {
/// Provides a read-only view on a [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-graph) contained in this dataset.
///
/// ```
/// use oxigraph::model::*;
/// use oxrdf::*;
///
/// let mut dataset = Dataset::default();
/// let ex = NamedNodeRef::new("http://example.com")?;
@ -131,7 +131,7 @@ impl Dataset {
/// Provides a read/write view on a [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-graph) contained in this dataset.
///
/// ```
/// use oxigraph::model::*;
/// use oxrdf::*;
///
/// let mut dataset = Dataset::default();
/// let ex = NamedNodeRef::new("http://example.com")?;
@ -491,7 +491,7 @@ impl Dataset {
///
/// Usage example ([Dataset isomorphim](https://www.w3.org/TR/rdf11-concepts/#dfn-dataset-isomorphism)):
/// ```
/// use oxigraph::model::*;
/// use oxrdf::*;
///
/// let iri = NamedNodeRef::new("http://example.com")?;
///
@ -504,8 +504,8 @@ impl Dataset {
/// let mut graph2 = Graph::new();
/// let bnode2 = BlankNode::default();
/// let g2 = BlankNode::default();
/// graph1.insert(QuadRef::new(iri, iri, &bnode2, &g2));
/// graph1.insert(QuadRef::new(&bnode2, iri, iri, &g2));
/// graph2.insert(QuadRef::new(iri, iri, &bnode2, &g2));
/// graph2.insert(QuadRef::new(&bnode2, iri, iri, &g2));
///
/// assert_ne!(graph1, graph2);
/// graph1.canonicalize();
@ -808,7 +808,7 @@ impl Dataset {
old_bnode: InternedBlankNode,
hashes: &HashMap<InternedBlankNode, u64>,
) -> BlankNode {
BlankNode::new_from_unique_id(hashes[&old_bnode])
BlankNode::new_from_unique_id(hashes[&old_bnode].into())
}
}
@ -884,7 +884,7 @@ impl fmt::Display for Dataset {
///
/// Usage example:
/// ```
/// use oxigraph::model::*;
/// use oxrdf::*;
///
/// let mut dataset = Dataset::default();
/// let ex = NamedNodeRef::new("http://example.com")?;
@ -1219,7 +1219,7 @@ impl<'a> fmt::Display for GraphView<'a> {
///
/// Usage example:
/// ```
/// use oxigraph::model::*;
/// use oxrdf::*;
///
/// let mut dataset = Dataset::default();
/// let ex = NamedNodeRef::new("http://example.com")?;

@ -2,7 +2,7 @@
//!
//! Usage example:
//! ```
//! use oxigraph::model::*;
//! use oxrdf::*;
//!
//! let mut graph = Graph::default();
//!
@ -19,8 +19,8 @@
//!
//! See also [`Dataset`](super::Dataset) if you want to get support of multiple RDF graphs at the same time.
use crate::model::dataset::*;
use crate::model::*;
use crate::dataset::*;
use crate::*;
use std::fmt;
/// An in-memory [RDF graph](https://www.w3.org/TR/rdf11-concepts/#dfn-graph).
@ -31,7 +31,7 @@ use std::fmt;
///
/// Usage example:
/// ```
/// use oxigraph::model::*;
/// use oxrdf::*;
///
/// let mut graph = Graph::default();
///
@ -181,7 +181,7 @@ impl Graph {
///
/// Usage example ([Graph isomorphim](https://www.w3.org/TR/rdf11-concepts/#dfn-graph-isomorphism)):
/// ```
/// use oxigraph::model::*;
/// use oxrdf::*;
///
/// let iri = NamedNodeRef::new("http://example.com")?;
///
@ -192,8 +192,8 @@ impl Graph {
///
/// let mut graph2 = Graph::new();
/// let bnode2 = BlankNode::default();
/// graph1.insert(TripleRef::new(iri, iri, &bnode2));
/// graph1.insert(TripleRef::new(&bnode2, iri, iri));
/// graph2.insert(TripleRef::new(iri, iri, &bnode2));
/// graph2.insert(TripleRef::new(&bnode2, iri, iri));
///
/// assert_ne!(graph1, graph2);
/// graph1.canonicalize();

@ -1,6 +1,6 @@
//! Interning of RDF elements using Rodeo
use crate::model::*;
use crate::*;
use lasso::{Key, Rodeo, Spur};
use std::collections::HashMap;

@ -0,0 +1,51 @@
//! OxRDF is a simple library providing datastructures encoding [RDF 1.1 concepts](https://www.w3.org/TR/rdf11-concepts/).
//!
//! This crate is intended to be a basic building block of other crates like [Oxigraph](https://crates.io/crates/oxigraph) or [Spargebra](https://crates.io/crates/spargebra).
//!
//! Inspired by [RDF/JS](https://rdf.js.org/data-model-spec/) and [Apache Commons RDF](http://commons.apache.org/proper/commons-rdf/).
//!
//! Usage example:
//!
//! Usage example:
//! ```
//! use oxrdf::*;
//!
//! let mut graph = Graph::default();
//!
//! // insertion
//! let ex = NamedNodeRef::new("http://example.com")?;
//! let triple = TripleRef::new(ex, ex, ex);
//! graph.insert(triple);
//!
//! // simple filter
//! let results: Vec<_> = graph.triples_for_subject(ex).collect();
//! assert_eq!(vec![triple], results);
//! # Result::<_,Box<dyn std::error::Error>>::Ok(())
//! ```
mod blank_node;
pub mod dataset;
pub mod graph;
mod interning;
mod literal;
mod named_node;
mod parser;
#[cfg(feature = "sophia_api")]
mod sophia;
mod triple;
mod variable;
pub mod vocab;
pub use crate::blank_node::{BlankNode, BlankNodeIdParseError, BlankNodeRef};
pub use crate::dataset::Dataset;
pub use crate::graph::Graph;
pub use crate::literal::{Literal, LiteralRef};
pub use crate::named_node::{NamedNode, NamedNodeRef};
pub use crate::parser::TermParseError;
pub use crate::triple::{
GraphName, GraphNameRef, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, QuadRef, Subject,
SubjectRef, Term, TermRef, Triple, TripleRef,
};
pub use crate::variable::{Variable, VariableNameParseError};
pub use oxilangtag::LanguageTagParseError;
pub use oxiri::IriParseError;

@ -1,8 +1,7 @@
use crate::model::named_node::NamedNode;
use crate::model::vocab::rdf;
use crate::model::vocab::xsd;
use crate::model::NamedNodeRef;
use crate::xsd::*;
use crate::named_node::NamedNode;
use crate::vocab::rdf;
use crate::vocab::xsd;
use crate::NamedNodeRef;
use oxilangtag::{LanguageTag, LanguageTagParseError};
use rio_api::model as rio;
use std::borrow::Cow;
@ -14,8 +13,8 @@ use std::option::Option;
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation:
/// ```
/// # use oxilangtag::LanguageTagParseError;
/// use oxigraph::model::Literal;
/// use oxigraph::model::vocab::xsd;
/// use oxrdf::Literal;
/// use oxrdf::vocab::xsd;
///
/// assert_eq!(
/// "\"foo\\nbar\"",
@ -265,15 +264,14 @@ impl From<u16> for Literal {
impl From<f32> for Literal {
#[inline]
fn from(value: f32) -> Self {
Float::from(value).into()
}
}
impl From<Float> for Literal {
#[inline]
fn from(value: Float) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
value: if value == f32::INFINITY {
"INF".to_string()
} else if value == f32::NEG_INFINITY {
"-INF".to_string()
} else {
value.to_string()
},
datatype: xsd::FLOAT.into(),
})
}
@ -282,147 +280,25 @@ impl From<Float> for Literal {
impl From<f64> for Literal {
#[inline]
fn from(value: f64) -> Self {
Double::from(value).into()
}
}
impl From<Double> for Literal {
#[inline]
fn from(value: Double) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
value: if value == f64::INFINITY {
"INF".to_string()
} else if value == f64::NEG_INFINITY {
"-INF".to_string()
} else {
value.to_string()
},
datatype: xsd::DOUBLE.into(),
})
}
}
impl From<Decimal> for Literal {
#[inline]
fn from(value: Decimal) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::DECIMAL.into(),
})
}
}
impl From<DateTime> for Literal {
#[inline]
fn from(value: DateTime) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::DATE_TIME.into(),
})
}
}
impl From<Time> for Literal {
#[inline]
fn from(value: Time) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::TIME.into(),
})
}
}
impl From<Date> for Literal {
#[inline]
fn from(value: Date) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::DATE.into(),
})
}
}
impl From<GYearMonth> for Literal {
#[inline]
fn from(value: GYearMonth) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::G_YEAR_MONTH.into(),
})
}
}
impl From<GYear> for Literal {
#[inline]
fn from(value: GYear) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::G_YEAR.into(),
})
}
}
impl From<GMonthDay> for Literal {
#[inline]
fn from(value: GMonthDay) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::G_MONTH_DAY.into(),
})
}
}
impl From<GMonth> for Literal {
#[inline]
fn from(value: GMonth) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::G_MONTH.into(),
})
}
}
impl From<GDay> for Literal {
#[inline]
fn from(value: GDay) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::G_DAY.into(),
})
}
}
impl From<Duration> for Literal {
#[inline]
fn from(value: Duration) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::DURATION.into(),
})
}
}
impl From<YearMonthDuration> for Literal {
#[inline]
fn from(value: YearMonthDuration) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::YEAR_MONTH_DURATION.into(),
})
}
}
impl From<DayTimeDuration> for Literal {
#[inline]
fn from(value: DayTimeDuration) -> Self {
Self(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::DAY_TIME_DURATION.into(),
})
}
}
/// A borrowed RDF [literal](https://www.w3.org/TR/rdf11-concepts/#dfn-literal)
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation:
/// ```
/// # use oxilangtag::LanguageTagParseError;
/// use oxigraph::model::LiteralRef;
/// use oxigraph::model::vocab::xsd;
/// use oxrdf::LiteralRef;
/// use oxrdf::vocab::xsd;
///
/// assert_eq!(
/// "\"foo\\nbar\"",
@ -433,7 +309,6 @@ impl From<DayTimeDuration> for Literal {
/// "\"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>);

@ -6,13 +6,13 @@ use std::fmt;
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation:
/// ```
/// use oxigraph::model::NamedNode;
/// use oxrdf::NamedNode;
///
/// assert_eq!(
/// "<http://example.com/foo>",
/// NamedNode::new("http://example.com/foo")?.to_string()
/// );
/// # Result::<_,oxigraph::model::IriParseError>::Ok(())
/// # Result::<_,oxrdf::IriParseError>::Ok(())
/// ```
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct NamedNode {
@ -95,13 +95,13 @@ impl PartialEq<NamedNode> for &str {
///
/// The default string formatter is returning an N-Triples, Turtle and SPARQL compatible representation:
/// ```
/// use oxigraph::model::NamedNodeRef;
/// use oxrdf::NamedNodeRef;
///
/// assert_eq!(
/// "<http://example.com/foo>",
/// NamedNodeRef::new("http://example.com/foo")?.to_string()
/// );
/// # Result::<_,oxigraph::model::IriParseError>::Ok(())
/// # Result::<_,oxrdf::IriParseError>::Ok(())
/// ```
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
pub struct NamedNodeRef<'a> {

@ -1,8 +1,8 @@
use crate::model::vocab::xsd;
use crate::model::{BlankNode, BlankNodeIdParseError, Literal, NamedNode, Subject, Term, Triple};
use crate::sparql::{Variable, VariableNameParseError};
use oxilangtag::LanguageTagParseError;
use oxiri::IriParseError;
use crate::vocab::xsd;
use crate::{
BlankNode, BlankNodeIdParseError, IriParseError, LanguageTagParseError, Literal, NamedNode,
Subject, Term, Triple, Variable, VariableNameParseError,
};
use std::char;
use std::error::Error;
use std::fmt;
@ -14,7 +14,7 @@ impl FromStr for NamedNode {
/// Parses a named node from its NTriples and Turtle serialization
///
/// ```
/// use oxigraph::model::NamedNode;
/// use oxrdf::NamedNode;
/// use std::str::FromStr;
///
/// assert_eq!(NamedNode::from_str("<http://example.com>").unwrap(), NamedNode::new("http://example.com").unwrap())
@ -36,7 +36,7 @@ impl FromStr for BlankNode {
/// Parses a blank node from its NTriples and Turtle serialization
///
/// ```
/// use oxigraph::model::BlankNode;
/// use oxrdf::BlankNode;
/// use std::str::FromStr;
///
/// assert_eq!(BlankNode::from_str("_:ex").unwrap(), BlankNode::new("ex").unwrap())
@ -58,7 +58,7 @@ impl FromStr for Literal {
/// Parses a literal from its NTriples or Turtle serialization
///
/// ```
/// use oxigraph::model::{Literal, NamedNode, vocab::xsd};
/// use oxrdf::{Literal, NamedNode, vocab::xsd};
/// use std::str::FromStr;
///
/// assert_eq!(Literal::from_str("\"ex\\n\"").unwrap(), Literal::new_simple_literal("ex\n"));
@ -84,7 +84,7 @@ impl FromStr for Term {
/// Parses a term from its NTriples or Turtle serialization
///
/// ```
/// use oxigraph::model::*;
/// use oxrdf::*;
/// use std::str::FromStr;
///
/// assert_eq!(Term::from_str("\"ex\"").unwrap(), Literal::new_simple_literal("ex").into());
@ -109,7 +109,7 @@ impl FromStr for Variable {
/// Parses a variable from its SPARQL serialization
///
/// ```
/// use oxigraph::sparql::Variable;
/// use oxrdf::Variable;
/// use std::str::FromStr;
///
/// assert_eq!(Variable::from_str("$foo").unwrap(), Variable::new("foo").unwrap())

@ -1,6 +1,6 @@
//! This crate provides implementation of [Sophia](https://docs.rs/sophia/) traits for the `model` module.
use crate::model::*;
use crate::*;
use sophia_api::term::*;
use std::fmt;

@ -1,7 +1,7 @@
use crate::model::blank_node::BlankNode;
use crate::model::literal::Literal;
use crate::model::named_node::NamedNode;
use crate::model::{BlankNodeRef, LiteralRef, NamedNodeRef};
use crate::blank_node::BlankNode;
use crate::literal::Literal;
use crate::named_node::NamedNode;
use crate::{BlankNodeRef, LiteralRef, NamedNodeRef};
use std::fmt;
use std::sync::Arc;

@ -0,0 +1,121 @@
use std::error::Error;
use std::fmt;
/// A [SPARQL query](https://www.w3.org/TR/sparql11-query/) variable.
///
/// ```
/// use oxrdf::{Variable, VariableNameParseError};
///
/// assert_eq!(
/// "?foo",
/// Variable::new("foo")?.to_string()
/// );
/// # Result::<_,VariableNameParseError>::Ok(())
/// ```
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct Variable {
name: String,
}
impl Variable {
/// Creates a variable name from a unique identifier.
///
/// The variable identifier must be valid according to the SPARQL grammar.
pub fn new(name: impl Into<String>) -> Result<Self, VariableNameParseError> {
let name = name.into();
validate_variable_identifier(&name)?;
Ok(Self::new_unchecked(name))
}
/// Creates a variable name from a unique identifier without validation.
///
/// It is the caller's responsibility to ensure that `id` is a valid blank node identifier
/// according to the SPARQL grammar.
///
/// [`Variable::new()`] is a safe version of this constructor and should be used for untrusted data.
#[inline]
pub fn new_unchecked(name: impl Into<String>) -> Self {
Self { name: name.into() }
}
#[inline]
pub fn as_str(&self) -> &str {
&self.name
}
#[inline]
pub fn into_string(self) -> String {
self.name
}
}
impl fmt::Display for Variable {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "?{}", self.name)
}
}
fn validate_variable_identifier(id: &str) -> Result<(), VariableNameParseError> {
let mut chars = id.chars();
let front = chars.next().ok_or(VariableNameParseError {})?;
match front {
'0'..='9'
| '_'
| ':'
| 'A'..='Z'
| 'a'..='z'
| '\u{00C0}'..='\u{00D6}'
| '\u{00D8}'..='\u{00F6}'
| '\u{00F8}'..='\u{02FF}'
| '\u{0370}'..='\u{037D}'
| '\u{037F}'..='\u{1FFF}'
| '\u{200C}'..='\u{200D}'
| '\u{2070}'..='\u{218F}'
| '\u{2C00}'..='\u{2FEF}'
| '\u{3001}'..='\u{D7FF}'
| '\u{F900}'..='\u{FDCF}'
| '\u{FDF0}'..='\u{FFFD}'
| '\u{10000}'..='\u{EFFFF}' => (),
_ => return Err(VariableNameParseError {}),
}
for c in chars {
match c {
'0'..='9'
| '\u{00B7}'
| '\u{00300}'..='\u{036F}'
| '\u{203F}'..='\u{2040}'
| '_'
| 'A'..='Z'
| 'a'..='z'
| '\u{00C0}'..='\u{00D6}'
| '\u{00D8}'..='\u{00F6}'
| '\u{00F8}'..='\u{02FF}'
| '\u{0370}'..='\u{037D}'
| '\u{037F}'..='\u{1FFF}'
| '\u{200C}'..='\u{200D}'
| '\u{2070}'..='\u{218F}'
| '\u{2C00}'..='\u{2FEF}'
| '\u{3001}'..='\u{D7FF}'
| '\u{F900}'..='\u{FDCF}'
| '\u{FDF0}'..='\u{FFFD}'
| '\u{10000}'..='\u{EFFFF}' => (),
_ => return Err(VariableNameParseError {}),
}
}
Ok(())
}
/// An error raised during [`Variable`] name validation.
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct VariableNameParseError {}
impl fmt::Display for VariableNameParseError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "The variable name is invalid")
}
}
impl Error for VariableNameParseError {}

@ -2,7 +2,7 @@
pub mod rdf {
//! [RDF](https://www.w3.org/TR/rdf11-concepts/) vocabulary
use crate::model::named_node::NamedNodeRef;
use crate::named_node::NamedNodeRef;
/// The class of containers of alternatives.
pub const ALT: NamedNodeRef<'_> =
@ -58,7 +58,7 @@ pub mod rdf {
pub mod rdfs {
//! [RDFS](https://www.w3.org/TR/rdf-schema/) vocabulary
use crate::model::named_node::NamedNodeRef;
use crate::named_node::NamedNodeRef;
/// The class of classes.
pub const CLASS: NamedNodeRef<'_> =
@ -110,7 +110,7 @@ pub mod rdfs {
pub mod xsd {
//! [RDF compatible XSD datatypes](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-compatible-xsd-types)
use crate::model::named_node::NamedNodeRef;
use crate::named_node::NamedNodeRef;
/// Absolute or relative URIs and IRIs
pub const ANY_URI: NamedNodeRef<'_> =

@ -0,0 +1,108 @@
//! Implements data structures for [RDF 1.1 Concepts](https://www.w3.org/TR/rdf11-concepts/) using [Oxrdf](https://crates.io/crates/oxrdf).
use crate::xsd::*;
use oxrdf::vocab::xsd;
pub use oxrdf::{
dataset, graph, vocab, BlankNode, BlankNodeIdParseError, BlankNodeRef, Dataset, Graph,
GraphName, GraphNameRef, IriParseError, LanguageTagParseError, Literal, LiteralRef, NamedNode,
NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, QuadRef, Subject, SubjectRef, Term,
TermParseError, TermRef, Triple, TripleRef,
};
impl From<Float> for Literal {
#[inline]
fn from(value: Float) -> Self {
Self::new_typed_literal(value.to_string(), xsd::FLOAT)
}
}
impl From<Double> for Literal {
#[inline]
fn from(value: Double) -> Self {
Self::new_typed_literal(value.to_string(), xsd::DOUBLE)
}
}
impl From<Decimal> for Literal {
#[inline]
fn from(value: Decimal) -> Self {
Self::new_typed_literal(value.to_string(), xsd::DECIMAL)
}
}
impl From<DateTime> for Literal {
#[inline]
fn from(value: DateTime) -> Self {
Self::new_typed_literal(value.to_string(), xsd::DATE_TIME)
}
}
impl From<Time> for Literal {
#[inline]
fn from(value: Time) -> Self {
Self::new_typed_literal(value.to_string(), xsd::TIME)
}
}
impl From<Date> for Literal {
#[inline]
fn from(value: Date) -> Self {
Self::new_typed_literal(value.to_string(), xsd::DATE)
}
}
impl From<GYearMonth> for Literal {
#[inline]
fn from(value: GYearMonth) -> Self {
Self::new_typed_literal(value.to_string(), xsd::G_YEAR_MONTH)
}
}
impl From<GYear> for Literal {
#[inline]
fn from(value: GYear) -> Self {
Self::new_typed_literal(value.to_string(), xsd::G_YEAR)
}
}
impl From<GMonthDay> for Literal {
#[inline]
fn from(value: GMonthDay) -> Self {
Self::new_typed_literal(value.to_string(), xsd::G_MONTH_DAY)
}
}
impl From<GMonth> for Literal {
#[inline]
fn from(value: GMonth) -> Self {
Self::new_typed_literal(value.to_string(), xsd::G_MONTH)
}
}
impl From<GDay> for Literal {
#[inline]
fn from(value: GDay) -> Self {
Self::new_typed_literal(value.to_string(), xsd::G_DAY)
}
}
impl From<Duration> for Literal {
#[inline]
fn from(value: Duration) -> Self {
Self::new_typed_literal(value.to_string(), xsd::DURATION)
}
}
impl From<YearMonthDuration> for Literal {
#[inline]
fn from(value: YearMonthDuration) -> Self {
Self::new_typed_literal(value.to_string(), xsd::YEAR_MONTH_DURATION)
}
}
impl From<DayTimeDuration> for Literal {
#[inline]
fn from(value: DayTimeDuration) -> Self {
Self::new_typed_literal(value.to_string(), xsd::DAY_TIME_DURATION)
}
}

@ -1,28 +0,0 @@
//! Implements data structures for [RDF 1.1 Concepts](https://www.w3.org/TR/rdf11-concepts/).
//!
//! Inspired by [RDF/JS](https://rdf.js.org/data-model-spec/) and [Apache Commons RDF](http://commons.apache.org/proper/commons-rdf/)
mod blank_node;
pub mod dataset;
pub mod graph;
mod interning;
mod literal;
mod named_node;
mod parser;
#[cfg(feature = "sophia")]
mod sophia;
mod triple;
pub mod vocab;
pub use self::blank_node::{BlankNode, BlankNodeIdParseError, BlankNodeRef};
pub use self::dataset::Dataset;
pub use self::graph::Graph;
pub use self::literal::{Literal, LiteralRef};
pub use self::named_node::{NamedNode, NamedNodeRef};
pub use self::parser::TermParseError;
pub use self::triple::{
GraphName, GraphNameRef, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, QuadRef, Subject,
SubjectRef, Term, TermRef, Triple, TripleRef,
};
pub use oxilangtag::LanguageTagParseError;
pub use oxiri::IriParseError;

@ -14,6 +14,7 @@ use digest::Digest;
use md5::Md5;
use oxilangtag::LanguageTag;
use oxiri::Iri;
use oxrdf::Variable;
use rand::random;
use regex::{Regex, RegexBuilder};
use sha1::Sha1;

@ -2,7 +2,7 @@
use crate::io::read::{ParserError, SyntaxError};
use crate::model::{vocab::xsd, *};
use crate::sparql::model::Variable;
use oxrdf::Variable;
use std::io::{self, BufRead, Write};
use std::str::FromStr;

@ -4,8 +4,8 @@ use crate::io::read::{ParserError, SyntaxError};
use crate::model::vocab::rdf;
use crate::model::*;
use crate::sparql::error::EvaluationError;
use crate::sparql::model::Variable;
use json_event_parser::{JsonEvent, JsonReader, JsonWriter};
use oxrdf::Variable;
use std::collections::BTreeMap;
use std::io::{self, BufRead, Write};

@ -3,7 +3,7 @@
use crate::io::read::{ParserError, SyntaxError};
use crate::model::vocab::rdf;
use crate::model::*;
use crate::sparql::model::Variable;
use oxrdf::Variable;
use quick_xml::events::{BytesDecl, BytesEnd, BytesStart, BytesText, Event};
use quick_xml::Reader;
use quick_xml::Writer;

@ -20,15 +20,13 @@ use crate::sparql::dataset::DatasetView;
pub use crate::sparql::error::EvaluationError;
use crate::sparql::eval::SimpleEvaluator;
pub use crate::sparql::io::QueryResultsFormat;
pub use crate::sparql::model::{
QueryResults, QuerySolution, QuerySolutionIter, QueryTripleIter, Variable,
VariableNameParseError,
};
pub use crate::sparql::model::{QueryResults, QuerySolution, QuerySolutionIter, QueryTripleIter};
use crate::sparql::plan_builder::PlanBuilder;
pub use crate::sparql::service::ServiceHandler;
use crate::sparql::service::{EmptyServiceHandler, ErrorConversionServiceHandler};
pub(crate) use crate::sparql::update::evaluate_update;
use crate::storage::Storage;
pub use oxrdf::{Variable, VariableNameParseError};
pub use spargebra::ParseError;
use std::collections::HashMap;
use std::rc::Rc;

@ -3,10 +3,9 @@ use crate::io::GraphSerializer;
use crate::model::*;
use crate::sparql::error::EvaluationError;
use crate::sparql::io::{QueryResultsFormat, QueryResultsParser, QueryResultsSerializer};
use std::error::Error;
use std::io::{BufRead, Write};
use oxrdf::Variable;
use std::io::{self, BufRead, Write};
use std::rc::Rc;
use std::{fmt, io};
/// Results of a [SPARQL query](https://www.w3.org/TR/sparql11-query/).
pub enum QueryResults {
@ -321,125 +320,6 @@ impl Iterator for QueryTripleIter {
}
}
/// A SPARQL query variable.
///
/// ```
/// use oxigraph::sparql::Variable;
///
/// assert_eq!(
/// "?foo",
/// Variable::new("foo")?.to_string()
/// );
/// # Result::<_,oxigraph::sparql::VariableNameParseError>::Ok(())
/// ```
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct Variable {
name: String,
}
impl Variable {
/// Creates a variable name from a unique identifier.
///
/// The variable identifier must be valid according to the SPARQL grammar.
pub fn new(name: impl Into<String>) -> Result<Self, VariableNameParseError> {
let name = name.into();
validate_variable_identifier(&name)?;
Ok(Self::new_unchecked(name))
}
/// Creates a variable name from a unique identifier without validation.
///
/// It is the caller's responsibility to ensure that `id` is a valid blank node identifier
/// according to the SPARQL grammar.
///
/// [`Variable::new()`] is a safe version of this constructor and should be used for untrusted data.
#[inline]
pub fn new_unchecked(name: impl Into<String>) -> Self {
Self { name: name.into() }
}
#[inline]
pub fn as_str(&self) -> &str {
&self.name
}
#[inline]
pub fn into_string(self) -> String {
self.name
}
}
impl fmt::Display for Variable {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "?{}", self.name)
}
}
fn validate_variable_identifier(id: &str) -> Result<(), VariableNameParseError> {
let mut chars = id.chars();
let front = chars.next().ok_or(VariableNameParseError {})?;
match front {
'0'..='9'
| '_'
| ':'
| 'A'..='Z'
| 'a'..='z'
| '\u{00C0}'..='\u{00D6}'
| '\u{00D8}'..='\u{00F6}'
| '\u{00F8}'..='\u{02FF}'
| '\u{0370}'..='\u{037D}'
| '\u{037F}'..='\u{1FFF}'
| '\u{200C}'..='\u{200D}'
| '\u{2070}'..='\u{218F}'
| '\u{2C00}'..='\u{2FEF}'
| '\u{3001}'..='\u{D7FF}'
| '\u{F900}'..='\u{FDCF}'
| '\u{FDF0}'..='\u{FFFD}'
| '\u{10000}'..='\u{EFFFF}' => (),
_ => return Err(VariableNameParseError {}),
}
for c in chars {
match c {
'0'..='9'
| '\u{00B7}'
| '\u{00300}'..='\u{036F}'
| '\u{203F}'..='\u{2040}'
| '_'
| 'A'..='Z'
| 'a'..='z'
| '\u{00C0}'..='\u{00D6}'
| '\u{00D8}'..='\u{00F6}'
| '\u{00F8}'..='\u{02FF}'
| '\u{0370}'..='\u{037D}'
| '\u{037F}'..='\u{1FFF}'
| '\u{200C}'..='\u{200D}'
| '\u{2070}'..='\u{218F}'
| '\u{2C00}'..='\u{2FEF}'
| '\u{3001}'..='\u{D7FF}'
| '\u{F900}'..='\u{FDCF}'
| '\u{FDF0}'..='\u{FFFD}'
| '\u{10000}'..='\u{EFFFF}' => (),
_ => return Err(VariableNameParseError {}),
}
}
Ok(())
}
/// An error raised during [`Variable`] name validation.
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct VariableNameParseError {}
impl fmt::Display for VariableNameParseError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "The variable name is invalid")
}
}
impl Error for VariableNameParseError {}
#[test]
fn test_serialization_rountrip() -> Result<(), EvaluationError> {
use std::io::Cursor;

@ -1,6 +1,6 @@
use crate::model::NamedNode;
use crate::sparql::model::Variable;
use crate::storage::numeric_encoder::EncodedTerm;
use oxrdf::Variable;
use spargebra::algebra::GraphPattern;
use std::cmp::max;
use std::collections::btree_map::Entry;

@ -1,9 +1,9 @@
use crate::model::{LiteralRef, NamedNode as OxNamedNode, NamedNodeRef, Term as OxTerm};
use crate::sparql::dataset::DatasetView;
use crate::sparql::error::EvaluationError;
use crate::sparql::model::Variable as OxVariable;
use crate::sparql::plan::*;
use crate::storage::numeric_encoder::{EncodedTerm, EncodedTriple};
use oxrdf::Variable as OxVariable;
use rand::random;
use spargebra::algebra::*;
use spargebra::term::*;

@ -439,7 +439,7 @@ impl From<NamedNodeRef<'_>> for EncodedTerm {
impl From<BlankNodeRef<'_>> for EncodedTerm {
fn from(blank_node: BlankNodeRef<'_>) -> Self {
if let Some(id) = blank_node.id() {
if let Some(id) = blank_node.unique_id() {
Self::NumericalBlankNode { id }
} else {
let id = blank_node.as_str();

Loading…
Cancel
Save