Adds our own IRI normalization instead of relying on Url crate

pull/10/head
Tpt 5 years ago
parent cf0fddf2b4
commit 2f706a777f
  1. 2
      lib/Cargo.toml
  2. 2
      lib/src/lib.rs
  3. 2
      lib/src/model/graph.rs
  4. 632
      lib/src/model/iri.rs
  5. 9
      lib/src/model/literal.rs
  6. 3
      lib/src/model/mod.rs
  7. 19
      lib/src/model/named_node.rs
  8. 124
      lib/src/model/vocab.rs
  9. 10
      lib/src/repository.rs
  10. 18
      lib/src/sparql/parser.rs
  11. 39
      lib/src/sparql/sparql_grammar.rustpeg
  12. 14
      lib/src/sparql/xml_results.rs
  13. 2
      lib/src/store/memory.rs
  14. 12
      lib/src/store/numeric_encoder.rs
  15. 2
      lib/src/store/rocksdb.rs
  16. 95
      lib/tests/sparql_test_cases.rs

@ -18,9 +18,7 @@ travis-ci = { repository = "Tpt/rudf" }
[dependencies] [dependencies]
lazy_static = "1" lazy_static = "1"
rocksdb = { version = "0.12", optional = true } rocksdb = { version = "0.12", optional = true }
url = "2"
uuid = { version = "0.7", features = ["v4"] } uuid = { version = "0.7", features = ["v4"] }
bzip2 = "0.3"
byteorder = {version="1", features = ["i128"] } byteorder = {version="1", features = ["i128"] }
quick-xml = "0.15" quick-xml = "0.15"
ordered-float = "1" ordered-float = "1"

@ -18,7 +18,7 @@
//! let connection = repository.connection().unwrap(); //! let connection = repository.connection().unwrap();
//! //!
//! // insertion //! // insertion
//! let ex = NamedNode::new("http://example.com"); //! let ex = NamedNode::parse("http://example.com").unwrap();
//! let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None); //! let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
//! connection.insert(&quad); //! connection.insert(&quad);
//! //!

@ -14,7 +14,7 @@ use std::iter::FromIterator;
/// use rudf::model::SimpleGraph; /// use rudf::model::SimpleGraph;
/// ///
/// let mut graph = SimpleGraph::default(); /// let mut graph = SimpleGraph::default();
/// let ex = NamedNode::new("http://example.com"); /// let ex = NamedNode::parse("http://example.com").unwrap();
/// let triple = Triple::new(ex.clone(), ex.clone(), ex.clone()); /// let triple = Triple::new(ex.clone(), ex.clone(), ex.clone());
/// graph.insert(triple.clone()); /// graph.insert(triple.clone());
/// let results: Vec<Triple> = graph.triples_for_subject(&ex.into()).cloned().collect(); /// let results: Vec<Triple> = graph.triples_for_subject(&ex.into()).cloned().collect();

@ -0,0 +1,632 @@
use std::error::Error;
use std::fmt;
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Iri {
iri: String,
positions: IriElementsPositions,
}
impl Iri {
pub fn parse(iri: String) -> Result<Self, IriParseError> {
let base_positions =
parse_iri(iri.as_bytes(), 0).map_err(|position| IriParseError { position })?;
Ok(Self {
iri,
positions: base_positions,
})
}
pub fn resolve(&self, iri: &str) -> Result<Iri, IriParseError> {
let mut target_buffer = String::with_capacity(self.iri.len() + iri.len());
let positions = resolve_relative_iri(iri, &self.iri, &self.positions, &mut target_buffer)
.map_err(|position| IriParseError { position })?;
Ok(Self {
iri: target_buffer,
positions,
})
}
pub fn into_string(self) -> String {
self.iri
}
}
#[derive(Debug)]
pub struct IriParseError {
position: usize,
}
impl fmt::Display for IriParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Invalid IRI at char {}", self.position)
}
}
impl Error for IriParseError {}
type IriState = Result<usize, usize>; // usize = the end position
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
struct IriElementsPositions {
scheme_end: usize,
authority_end: usize,
path_end: usize,
query_end: usize,
fragment_end: usize,
}
// RFC 3986 5.2 Relative Resolution algorithm
fn resolve_relative_iri(
reference_iri: &str,
base_iri: &str,
base_positions: &IriElementsPositions,
target_buffer: &mut String,
) -> Result<IriElementsPositions, usize> {
let base_scheme = &base_iri[0..base_positions.scheme_end];
let base_authority = &base_iri[base_positions.scheme_end..base_positions.authority_end];
let base_path = &base_iri[base_positions.authority_end..base_positions.path_end];
let base_query = &base_iri[base_positions.path_end..base_positions.query_end];
let reference_positions = parse_iri_reference(reference_iri.as_bytes(), 0)?;
let r_scheme = &reference_iri[0..reference_positions.scheme_end];
let r_authority =
&reference_iri[reference_positions.scheme_end..reference_positions.authority_end];
let r_path = &reference_iri[reference_positions.authority_end..reference_positions.path_end];
let r_query = &reference_iri[reference_positions.path_end..reference_positions.query_end];
let r_fragment = &reference_iri[reference_positions.query_end..];
let scheme_end;
let authority_end;
let path_end;
let query_end;
let fragment_end;
// if defined(R.scheme) then
if !r_scheme.is_empty() {
// T.scheme = R.scheme;
target_buffer.push_str(r_scheme);
scheme_end = target_buffer.len();
// T.authority = R.authority;
target_buffer.push_str(r_authority);
authority_end = target_buffer.len();
// T.path = remove_dot_segments(R.path);
append_and_remove_dot_segments(r_path, target_buffer, target_buffer.len());
path_end = target_buffer.len();
// T.query = R.query;
target_buffer.push_str(r_query);
query_end = target_buffer.len();
// T.fragment = R.fragment;
target_buffer.push_str(r_fragment);
fragment_end = target_buffer.len();
} else {
// T.scheme = Base.scheme;
target_buffer.push_str(base_scheme);
scheme_end = target_buffer.len();
// if defined(R.authority) then
if !r_authority.is_empty() {
// T.authority = R.authority;
target_buffer.push_str(r_authority);
authority_end = target_buffer.len();
// T.path = remove_dot_segments(R.path);
append_and_remove_dot_segments(r_path, target_buffer, target_buffer.len());
path_end = target_buffer.len();
// T.query = R.query;
target_buffer.push_str(r_query);
query_end = target_buffer.len();
// T.fragment = R.fragment;
target_buffer.push_str(r_fragment);
fragment_end = target_buffer.len();
} else {
// T.authority = Base.authority;
target_buffer.push_str(base_authority);
authority_end = target_buffer.len();
// if (R.path == "") then
if r_path == "" {
// T.path = Base.path;
target_buffer.push_str(base_path);
path_end = target_buffer.len();
// if defined(R.query) then
if !r_query.is_empty() {
// T.query = R.query;
target_buffer.push_str(r_query);
} else {
// T.query = Base.query;
target_buffer.push_str(base_query);
}
query_end = target_buffer.len();
} else {
// if (R.path starts-with "/") then
if r_path.starts_with('/') {
// T.path = remove_dot_segments(R.path);
append_and_remove_dot_segments(r_path, target_buffer, target_buffer.len());
} else {
let path_start_in_target = target_buffer.len();
// T.path = merge(Base.path, R.path);
// T.path = remove_dot_segments(T.path);
if base_positions.authority_end > base_positions.scheme_end
&& base_positions.path_end == base_positions.authority_end
{
append_and_remove_dot_segments_with_extra_slash(
r_path,
target_buffer,
path_start_in_target,
);
} else {
let last_base_slash = base_path
.char_indices()
.rev()
.find(|(_, c)| *c == '/')
.map_or(0, |(i, _)| i)
+ base_positions.authority_end;
append_and_remove_dot_segments(
&base_iri[base_positions.authority_end..=last_base_slash],
target_buffer,
path_start_in_target,
);
if target_buffer.ends_with('/') {
target_buffer.pop();
append_and_remove_dot_segments_with_extra_slash(
r_path,
target_buffer,
path_start_in_target,
);
} else {
append_and_remove_dot_segments(
r_path,
target_buffer,
path_start_in_target,
);
}
}
}
path_end = target_buffer.len();
// T.query = R.query;
target_buffer.push_str(r_query);
query_end = target_buffer.len();
}
// T.fragment = R.fragment;
target_buffer.push_str(r_fragment);
fragment_end = target_buffer.len();
}
}
Ok(IriElementsPositions {
scheme_end,
authority_end,
path_end,
query_end,
fragment_end,
})
}
// RFC 3986 5.2.4 Remove Dot Segments
fn append_and_remove_dot_segments(
mut input: &str,
output: &mut String,
path_start_in_output: usize,
) {
while !input.is_empty() {
if input.starts_with("../") {
input = &input[3..];
} else if input.starts_with("./") || input.starts_with("/./") {
input = &input[2..];
} else if input == "/." {
input = "/";
} else if input.starts_with("/../") {
pop_last_segment(output, path_start_in_output);
input = &input[3..];
} else if input == "/.." {
pop_last_segment(output, path_start_in_output);
input = "/";
} else if input == "." || input == ".." {
input = "";
} else {
if input.starts_with('/') {
output.push('/');
input = &input[1..];
}
if let Some(i) = input.find('/') {
output.push_str(&input[..i]);
input = &input[i..];
} else {
output.push_str(input);
input = "";
}
}
}
}
fn pop_last_segment(buffer: &mut String, path_start_in_buffer: usize) {
if let Some((last_slash_position, _)) = buffer[path_start_in_buffer..]
.char_indices()
.rev()
.find(|(_, c)| *c == '/')
{
buffer.truncate(last_slash_position + path_start_in_buffer)
}
}
fn append_and_remove_dot_segments_with_extra_slash(
input: &str,
output: &mut String,
path_start_in_output: usize,
) {
if input.is_empty() {
output.push('/');
} else if input.starts_with("./") {
append_and_remove_dot_segments(&input[1..], output, path_start_in_output)
} else if input == "." {
append_and_remove_dot_segments("/", output, path_start_in_output)
} else if input.starts_with("../") {
pop_last_segment(output, path_start_in_output);
append_and_remove_dot_segments(&input[2..], output, path_start_in_output)
} else if input == ".." {
pop_last_segment(output, path_start_in_output);
append_and_remove_dot_segments("/", output, path_start_in_output)
} else {
output.push('/');
if let Some(i) = input.find('/') {
output.push_str(&input[..i]);
append_and_remove_dot_segments(&input[i..], output, path_start_in_output)
} else {
output.push_str(input);
}
}
}
fn parse_iri(value: &[u8], start: usize) -> Result<IriElementsPositions, usize> {
// IRI = scheme ":" ihier-part [ "?" iquery ] [ "#" ifragment ]
let scheme_end = parse_scheme(value, start)?;
if scheme_end >= value.len() || value[scheme_end] != b':' {
return Err(scheme_end);
}
let (authority_end, path_end) = parse_ihier_part(value, scheme_end + 1)?;
let query_end = if path_end < value.len() && value[path_end] == b'?' {
parse_iquery(value, path_end + 1)?
} else {
path_end
};
let fragment_end = if query_end < value.len() && value[query_end] == b'#' {
parse_ifragment(value, query_end + 1)?
} else {
query_end
};
Ok(IriElementsPositions {
scheme_end: scheme_end + 1,
authority_end,
path_end,
query_end,
fragment_end,
})
}
fn parse_ihier_part(value: &[u8], start: usize) -> Result<(usize, usize), usize> {
// (authority_end, path_end)
// ihier-part = "//" iauthority ipath-abempty / ipath-absolute / ipath-rootless / ipath-empty
if value[start..].starts_with(b"//") {
let authority_end = parse_iauthority(value, start + 2)?;
Ok((authority_end, parse_ipath_abempty(value, authority_end)?))
} else if value[start..].starts_with(b"/") {
Ok((start, parse_ipath_absolute(value, start)?))
} else {
match parse_ipath_rootless(value, start) {
Ok(i) => Ok((start, i)),
Err(i) => {
if i == start {
Ok((start, i)) // ipath empty
} else {
Err(i)
}
}
}
}
}
fn parse_iri_reference(value: &[u8], start: usize) -> Result<IriElementsPositions, usize> {
// IRI-reference = IRI / irelative-ref
match parse_iri(value, start) {
Ok(positions) => Ok(positions),
Err(_) => parse_irelative_ref(value, start),
}
}
fn parse_irelative_ref(value: &[u8], start: usize) -> Result<IriElementsPositions, usize> {
// irelative-ref = irelative-part [ "?" iquery ] [ "#" ifragment ]
let (authority_end, path_end) = parse_irelative_path(value, start)?;
let query_end = if path_end < value.len() && value[path_end] == b'?' {
parse_iquery(value, path_end + 1)?
} else {
path_end
};
let fragment_end = if query_end < value.len() && value[query_end] == b'#' {
parse_ifragment(&value, query_end + 1)?
} else {
query_end
};
Ok(IriElementsPositions {
scheme_end: start,
authority_end,
path_end,
query_end,
fragment_end,
})
}
fn parse_irelative_path(value: &[u8], start: usize) -> Result<(usize, usize), usize> {
// (authority_end, path_end)
// irelative-part = "//" iauthority ipath-abempty / ipath-absolute / ipath-noscheme / ipath-empty
if value[start..].starts_with(b"//") {
let authority_end = parse_iauthority(&value, start + 2)?;
Ok((authority_end, parse_ipath_abempty(value, authority_end)?))
} else if value[start..].starts_with(b"/") {
Ok((start, parse_ipath_absolute(value, start)?))
} else {
match parse_ipath_noscheme(value, start) {
Ok(i) => Ok((start, i)),
Err(i) => {
if i == start {
Ok((start, i)) // ipath empty
} else {
Err(i)
}
}
}
}
}
fn parse_scheme(value: &[u8], start: usize) -> IriState {
// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
if value.len() <= start || !is_alpha(value[start]) {
return Err(start);
}
for (i, c) in value[start..].iter().enumerate() {
match *c {
c if is_alpha(c) || is_digit(c) || c == b'+' || c == b'-' || c == b'.' => (),
_ => return Ok(start + i),
}
}
Err(value.len())
}
fn parse_iauthority(value: &[u8], start: usize) -> IriState {
// iauthority = [ iuserinfo "@" ] ihost [ ":" port ]
//TODO: implement properly
for (i, c) in value[start..].iter().enumerate() {
match *c {
b'/' | b'?' | b'#' => return Ok(start + i),
_ => (),
}
}
Ok(value.len())
}
fn parse_ipath_abempty(value: &[u8], start: usize) -> IriState {
// ipath-abempty = *( "/" isegment )
let mut i = start;
while i < value.len() {
match value[i] {
b'/' => {
i = parse_isegment(value, i + 1)?;
}
_ => return Ok(i),
}
}
Ok(value.len())
}
fn parse_ipath_absolute(value: &[u8], start: usize) -> IriState {
// ipath-absolute = "/" [ isegment-nz *( "/" isegment ) ] = "/" [ isegment-nz ipath-abempty ]
if !value[start..].starts_with(b"/") {
return Err(start);
}
match parse_isegment_nz(value, start + 1) {
Ok(i) => parse_ipath_abempty(value, i),
Err(i) => {
if i == start + 1 {
Ok(i) // optional
} else {
Err(i)
}
}
}
}
fn parse_ipath_noscheme(value: &[u8], start: usize) -> IriState {
// ipath-noscheme = isegment-nz-nc *( "/" isegment ) = isegment-nz-nc ipath-abempty
let i = parse_isegment_nz_nc(value, start)?;
parse_ipath_abempty(&value, i)
}
fn parse_ipath_rootless(value: &[u8], start: usize) -> IriState {
// ipath-rootless = isegment-nz *( "/" isegment ) = isegment-nz ipath-abempty
let i = parse_isegment_nz(value, start)?;
parse_ipath_abempty(value, i)
}
fn parse_isegment(value: &[u8], start: usize) -> IriState {
// isegment = *ipchar
//TODO: implement properly
for (i, c) in value[start..].iter().enumerate() {
match *c {
b'/' | b'?' | b'#' => return Ok(start + i),
_ => (),
}
}
Ok(value.len())
}
fn parse_isegment_nz(value: &[u8], start: usize) -> IriState {
// isegment-nz = 1*ipchar
let i = parse_isegment(value, start)?;
if i == start {
Err(0)
} else {
Ok(i)
}
}
fn parse_isegment_nz_nc(value: &[u8], start: usize) -> IriState {
// isegment-nz-nc = 1*( iunreserved / pct-encoded / sub-delims / "@" )
//TODO: implement properly
for (i, c) in value[start..].iter().enumerate() {
match *c {
b'/' | b'?' | b'#' | b':' => return if i == start { Err(i) } else { Ok(i) },
_ => (),
}
}
Ok(value.len())
}
fn parse_iquery(value: &[u8], start: usize) -> IriState {
// iquery = *( ipchar / iprivate / "/" / "?" )
//TODO: implement properly
for (i, c) in value[start..].iter().enumerate() {
if *c == b'#' {
return Ok(start + i);
}
}
Ok(value.len())
}
fn parse_ifragment(value: &[u8], _start: usize) -> IriState {
// ifragment = *( ipchar / "/" / "?" )
//TODO: implement properly
Ok(value.len())
}
fn is_alpha(b: u8) -> bool {
match b {
b'a'..=b'z' | b'A'..=b'Z' => true,
_ => false,
}
}
fn is_digit(b: u8) -> bool {
match b {
b'0'..=b'9' => true,
_ => false,
}
}
#[test]
fn test_parsing() {
let examples = [
"file://foo",
"ftp://ftp.is.co.za/rfc/rfc1808.txt",
"http://www.ietf.org/rfc/rfc2396.txt",
"ldap://[2001:db8::7]/c=GB?objectClass?one",
"mailto:John.Doe@example.com",
"news:comp.infosystems.www.servers.unix",
"tel:+1-816-555-1212",
"telnet://192.0.2.16:80/",
"urn:oasis:names:specification:docbook:dtd:xml:4.1.2",
"http://example.com",
"http://example.com/",
"http://example.com/foo",
"http://example.com/foo/bar",
"http://example.com/foo/bar/",
"http://example.com/foo/bar?q=1&r=2",
"http://example.com/foo/bar/?q=1&r=2",
"http://example.com#toto",
"http://example.com/#toto",
"http://example.com/foo#toto",
"http://example.com/foo/bar#toto",
"http://example.com/foo/bar/#toto",
"http://example.com/foo/bar?q=1&r=2#toto",
"http://example.com/foo/bar/?q=1&r=2#toto",
];
for e in &examples {
assert!(
Iri::parse(e.to_string()).is_ok(),
"{} is not recognized as an IRI",
e
);
}
}
#[test]
fn test_resolve_relative_iri() {
let base = "http://a/b/c/d;p?q";
let examples = [
("g:h", "g:h"),
("g", "http://a/b/c/g"),
("g/", "http://a/b/c/g/"),
("/g", "http://a/g"),
("//g", "http://g"),
("?y", "http://a/b/c/d;p?y"),
("g?y", "http://a/b/c/g?y"),
("#s", "http://a/b/c/d;p?q#s"),
("g#s", "http://a/b/c/g#s"),
("g?y#s", "http://a/b/c/g?y#s"),
(";x", "http://a/b/c/;x"),
("g;x", "http://a/b/c/g;x"),
("g;x?y#s", "http://a/b/c/g;x?y#s"),
("", "http://a/b/c/d;p?q"),
(".", "http://a/b/c/"),
("./", "http://a/b/c/"),
("./g", "http://a/b/c/g"),
("..", "http://a/b/"),
("../", "http://a/b/"),
("../g", "http://a/b/g"),
("../..", "http://a/"),
("../../", "http://a/"),
("../../g", "http://a/g"),
("../../../g", "http://a/g"),
("../../../../g", "http://a/g"),
("/./g", "http://a/g"),
("/../g", "http://a/g"),
("g.", "http://a/b/c/g."),
(".g", "http://a/b/c/.g"),
("g..", "http://a/b/c/g.."),
("..g", "http://a/b/c/..g"),
("./../g", "http://a/b/g"),
("./g/.", "http://a/b/c/g/"),
("g/./h", "http://a/b/c/g/h"),
("g/../h", "http://a/b/c/h"),
("g;x=1/./y", "http://a/b/c/g;x=1/y"),
("g;x=1/../y", "http://a/b/c/y"),
("g?y/./x", "http://a/b/c/g?y/./x"),
("g?y/../x", "http://a/b/c/g?y/../x"),
("g#s/./x", "http://a/b/c/g#s/./x"),
("g#s/../x", "http://a/b/c/g#s/../x"),
("http:g", "http:g"),
("./g:h", "http://a/b/c/g:h"),
];
let base = Iri::parse(base.to_owned()).unwrap();
for (input, output) in examples.iter() {
let result = base.resolve(input);
assert!(
result.is_ok(),
"Resolving of {} failed with error: {}",
input,
result.unwrap_err()
);
let result = result.unwrap().into_string();
assert_eq!(
result, *output,
"Resolving of {} is wrong. Found {} and expecting {}",
input, result, output
);
}
}

@ -133,14 +133,11 @@ impl Literal {
value: impl Into<String>, value: impl Into<String>,
language: impl Into<String>, language: impl Into<String>,
) -> Self { ) -> Self {
let language = language.into(); let mut language = language.into();
language.make_ascii_lowercase();
Literal(LiteralContent::LanguageTaggedString { Literal(LiteralContent::LanguageTaggedString {
value: value.into(), value: value.into(),
language: if language.bytes().all(|c| c.is_ascii_lowercase()) { language,
language
} else {
language.to_ascii_lowercase()
},
}) })
} }

@ -4,6 +4,7 @@
mod blank_node; mod blank_node;
mod graph; mod graph;
mod iri;
mod isomorphism; mod isomorphism;
mod literal; mod literal;
mod named_node; mod named_node;
@ -12,6 +13,8 @@ pub mod vocab;
pub use crate::model::blank_node::BlankNode; pub use crate::model::blank_node::BlankNode;
pub use crate::model::graph::SimpleGraph; pub use crate::model::graph::SimpleGraph;
pub(crate) use crate::model::iri::Iri;
pub(crate) use crate::model::iri::IriParseError;
pub use crate::model::literal::Literal; pub use crate::model::literal::Literal;
pub use crate::model::named_node::NamedNode; pub use crate::model::named_node::NamedNode;
pub use crate::model::triple::NamedOrBlankNode; pub use crate::model::triple::NamedOrBlankNode;

@ -1,18 +1,17 @@
use crate::model::Iri;
use crate::Result;
use rio_api::model as rio; use rio_api::model as rio;
use std::fmt; use std::fmt;
/// A RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) /// A RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri)
/// ///
/// The common way to build it is to use the `FromStr::from_str` trait method.
/// This method takes care of usual IRI normalization and validation.
///
/// 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:
/// ``` /// ```
/// use rudf::model::NamedNode; /// use rudf::model::NamedNode;
/// ///
/// assert_eq!( /// assert_eq!(
/// "<http://example.com/foo>", /// "<http://example.com/foo>",
/// NamedNode::new("http://example.com/foo").to_string() /// NamedNode::parse("http://example.com/foo").unwrap().to_string()
/// ) /// )
/// ``` /// ```
/// ///
@ -31,8 +30,16 @@ impl fmt::Display for NamedNode {
} }
impl NamedNode { impl NamedNode {
/// Builds a RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) /// Builds and validate a RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri)
pub fn new(iri: impl Into<String>) -> Self { pub fn parse(iri: impl Into<String>) -> Result<Self> {
Ok(Self::new_from_iri(Iri::parse(iri.into())?))
}
pub(crate) fn new_from_iri(iri: Iri) -> Self {
Self::new_from_string(iri.into_string())
}
pub(crate) fn new_from_string(iri: impl Into<String>) -> Self {
Self { iri: iri.into() } Self { iri: iri.into() }
} }

@ -8,54 +8,54 @@ pub mod rdf {
lazy_static! { lazy_static! {
/// The class of containers of alternatives. /// The class of containers of alternatives.
pub static ref ALT: NamedNode = pub static ref ALT: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt"); NamedNode::new_from_string("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 static ref BAG: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag"); NamedNode::new_from_string("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 static ref FIRST: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"); NamedNode::new_from_string("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 static ref HTML: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML"); NamedNode::new_from_string("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 static ref LANG_STRING: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"); NamedNode::new_from_string("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 static ref LIST: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#List"); NamedNode::new_from_string("http://www.w3.org/1999/02/22-rdf-syntax-ns#List");
pub static ref NIL: NamedNode = pub static ref NIL: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"); NamedNode::new_from_string("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 static ref OBJECT: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#object"); NamedNode::new_from_string("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 static ref PREDICATE: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate"); NamedNode::new_from_string("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 static ref PROPERTY: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"); NamedNode::new_from_string("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 static ref REST: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"); NamedNode::new_from_string("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 static ref SEQ: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq"); NamedNode::new_from_string("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 static ref STATEMENT: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement"); NamedNode::new_from_string("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 static ref SUBJECT: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#subject"); NamedNode::new_from_string("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 static ref TYPE: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); NamedNode::new_from_string("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 static ref VALUE: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#value"); NamedNode::new_from_string("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 static ref XML_LITERAL: NamedNode =
NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"); NamedNode::new_from_string("http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral");
} }
} }
@ -67,49 +67,49 @@ pub mod rdfs {
lazy_static! { lazy_static! {
/// The class of classes. /// The class of classes.
pub static ref CLASS: NamedNode = pub static ref CLASS: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#Class"); NamedNode::new_from_string("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 static ref COMMENT: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#comment"); NamedNode::new_from_string("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 static ref CONTAINER: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#Container"); NamedNode::new_from_string("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 static ref CONTAINER_MEMBERSHIP_PROPERTY: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty"); NamedNode::new_from_string("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 static ref DATATYPE: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#Datatype"); NamedNode::new_from_string("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 static ref DOMAIN: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#domain"); NamedNode::new_from_string("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 static ref IS_DEFINED_BY: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#isDefinedBy"); NamedNode::new_from_string("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 static ref LABEL: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#label"); NamedNode::new_from_string("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 static ref LITERAL: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#Literal"); NamedNode::new_from_string("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 static ref MEMBER: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#member"); NamedNode::new_from_string("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 static ref RANGE: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#range"); NamedNode::new_from_string("http://www.w3.org/2000/01/rdf-schema#range");
/// The class resource, everything. /// The class resource, everything.
pub static ref RESOURCE: NamedNode = pub static ref RESOURCE: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#Resource"); NamedNode::new_from_string("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 static ref SEE_ALSO: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#seeAlso"); NamedNode::new_from_string("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 static ref SUB_CLASS_OF: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#subClassOf"); NamedNode::new_from_string("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 static ref SUB_PROPERTY_OF: NamedNode =
NamedNode::new("http://www.w3.org/2000/01/rdf-schema#subPropertyOf"); NamedNode::new_from_string("http://www.w3.org/2000/01/rdf-schema#subPropertyOf");
} }
} }
@ -121,93 +121,93 @@ pub mod xsd {
lazy_static! { lazy_static! {
/// true, false /// true, false
pub static ref BOOLEAN: NamedNode = pub static ref BOOLEAN: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#boolean"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#boolean");
/// 128…+127 (8 bit) /// 128…+127 (8 bit)
pub static ref BYTE: NamedNode = pub static ref BYTE: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#byte"); NamedNode::new_from_string("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 static ref DATE: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#date"); NamedNode::new_from_string("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 static ref DAY_TIME_DURATION: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#dayTimeDuration"); NamedNode::new_from_string("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 static ref DATE_TIME: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#dateTime"); NamedNode::new_from_string("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 static ref DATE_TIME_STAMP: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#dateTimeStamp"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#dateTimeStamp");
/// Arbitrary-precision decimal numbers /// Arbitrary-precision decimal numbers
pub static ref DECIMAL: NamedNode = pub static ref DECIMAL: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#decimal"); NamedNode::new_from_string("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 static ref DOUBLE: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#double"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#double");
/// Duration of time /// Duration of time
pub static ref DURATION: NamedNode = pub static ref DURATION: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#duration"); NamedNode::new_from_string("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 static ref FLOAT: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#float"); NamedNode::new_from_string("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 static ref G_DAY: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#gDay"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#gDay");
/// Gregorian calendar month /// Gregorian calendar month
pub static ref G_MONTH: NamedNode = pub static ref G_MONTH: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#gMonth"); NamedNode::new_from_string("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 static ref G_MONTH_DAY: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#gMonthDay"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#gMonthDay");
/// Gregorian calendar year /// Gregorian calendar year
pub static ref G_YEAR: NamedNode = pub static ref G_YEAR: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#gYear"); NamedNode::new_from_string("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 static ref G_YEAR_MONTH: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#gYearMonth"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#gYearMonth");
/// -2147483648…+2147483647 (32 bit) /// -2147483648…+2147483647 (32 bit)
pub static ref INT: NamedNode = pub static ref INT: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#int"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#int");
/// Arbitrary-size integer numbers /// Arbitrary-size integer numbers
pub static ref INTEGER: NamedNode = pub static ref INTEGER: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#integer"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#integer");
/// -9223372036854775808…+9223372036854775807 (64 bit) /// -9223372036854775808…+9223372036854775807 (64 bit)
pub static ref LONG: NamedNode = pub static ref LONG: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#long"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#long");
/// Integer numbers <0 /// Integer numbers <0
pub static ref NEGATIVE_INTEGER: NamedNode = pub static ref NEGATIVE_INTEGER: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#negativeInteger"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#negativeInteger");
/// Integer numbers ≥0 /// Integer numbers ≥0
pub static ref NON_NEGATIVE_INTEGER: NamedNode = pub static ref NON_NEGATIVE_INTEGER: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#nonNegativeInteger"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#nonNegativeInteger");
/// Integer numbers ≤0 /// Integer numbers ≤0
pub static ref NON_POSITIVE_INTEGER: NamedNode = pub static ref NON_POSITIVE_INTEGER: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#nonPositiveInteger"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#nonPositiveInteger");
/// Integer numbers >0 /// Integer numbers >0
pub static ref POSITIVE_INTEGER: NamedNode = pub static ref POSITIVE_INTEGER: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#positiveInteger"); NamedNode::new_from_string("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 static ref TIME: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#time"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#time");
/// -32768…+32767 (16 bit) /// -32768…+32767 (16 bit)
pub static ref SHORT: NamedNode = pub static ref SHORT: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#short"); NamedNode::new_from_string("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 static ref STRING: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#string"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#string");
/// 0…255 (8 bit) /// 0…255 (8 bit)
pub static ref UNSIGNED_BYTE: NamedNode = pub static ref UNSIGNED_BYTE: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#unsignedByte"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#unsignedByte");
/// 0…4294967295 (32 bit) /// 0…4294967295 (32 bit)
pub static ref UNSIGNED_INT: NamedNode = pub static ref UNSIGNED_INT: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#unsignedInt"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#unsignedInt");
/// 0…18446744073709551615 (64 bit) /// 0…18446744073709551615 (64 bit)
pub static ref UNSIGNED_LONG: NamedNode = pub static ref UNSIGNED_LONG: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#unsignedLong"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#unsignedLong");
/// 0…65535 (16 bit) /// 0…65535 (16 bit)
pub static ref UNSIGNED_SHORT: NamedNode = pub static ref UNSIGNED_SHORT: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#unsignedShort"); NamedNode::new_from_string("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 static ref YEAR_MONTH_DURATION: NamedNode =
NamedNode::new("http://www.w3.org/2001/XMLSchema#yearMonthDuration"); NamedNode::new_from_string("http://www.w3.org/2001/XMLSchema#yearMonthDuration");
} }
} }

@ -21,7 +21,7 @@ use std::io::{BufRead, Read};
/// let connection = repository.connection().unwrap(); /// let connection = repository.connection().unwrap();
/// ///
/// // insertion /// // insertion
/// let ex = NamedNode::new("http://example.com"); /// let ex = NamedNode::parse("http://example.com").unwrap();
/// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None); /// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
/// connection.insert(&quad); /// connection.insert(&quad);
/// ///
@ -71,7 +71,7 @@ pub trait RepositoryConnection: Clone {
/// let connection = repository.connection().unwrap(); /// let connection = repository.connection().unwrap();
/// ///
/// // insertions /// // insertions
/// let ex = NamedNode::new("http://example.com"); /// let ex = NamedNode::parse("http://example.com").unwrap();
/// connection.insert(&Quad::new(ex.clone(), ex.clone(), ex.clone(), None)); /// connection.insert(&Quad::new(ex.clone(), ex.clone(), ex.clone(), None));
/// ///
/// // SPARQL query /// // SPARQL query
@ -94,7 +94,7 @@ pub trait RepositoryConnection: Clone {
/// let connection = repository.connection().unwrap(); /// let connection = repository.connection().unwrap();
/// ///
/// // insertion /// // insertion
/// let ex = NamedNode::new("http://example.com"); /// let ex = NamedNode::parse("http://example.com").unwrap();
/// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None); /// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
/// connection.insert(&quad); /// connection.insert(&quad);
/// ///
@ -128,7 +128,7 @@ pub trait RepositoryConnection: Clone {
/// ///
/// // quad filter /// // quad filter
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect(); /// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
/// let ex = NamedNode::new("http://example.com"); /// let ex = NamedNode::parse("http://example.com").unwrap();
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results.unwrap()); /// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results.unwrap());
/// ``` /// ```
fn load_graph( fn load_graph(
@ -155,7 +155,7 @@ pub trait RepositoryConnection: Clone {
/// ///
/// // quad filter /// // quad filter
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect(); /// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
/// let ex = NamedNode::new("http://example.com"); /// let ex = NamedNode::parse("http://example.com").unwrap();
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), Some(ex.into()))], results.unwrap()); /// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), Some(ex.into()))], results.unwrap());
/// ``` /// ```
fn load_dataset( fn load_dataset(

@ -22,8 +22,6 @@ mod grammar {
use std::io::BufReader; use std::io::BufReader;
use std::io::Read; use std::io::Read;
use std::str::Chars; use std::str::Chars;
use url::ParseOptions;
use url::Url;
struct FocusedTriplePattern<F> { struct FocusedTriplePattern<F> {
focus: F, focus: F,
@ -296,15 +294,19 @@ mod grammar {
} }
pub struct ParserState { pub struct ParserState {
base_uri: Option<Url>, base_iri: Option<Iri>,
namespaces: HashMap<String, String>, namespaces: HashMap<String, String>,
bnodes_map: BTreeMap<String, BlankNode>, bnodes_map: BTreeMap<String, BlankNode>,
aggregations: BTreeMap<Aggregation, Variable>, aggregations: BTreeMap<Aggregation, Variable>,
} }
impl ParserState { impl ParserState {
fn url_parser(&self) -> ParseOptions<'_> { fn parse_iri(&self, iri: &str) -> Result<Iri, IriParseError> {
Url::options().base_url(self.base_uri.as_ref()) if let Some(base_iri) = &self.base_iri {
base_iri.resolve(iri)
} else {
Iri::parse(iri.to_owned())
}
} }
fn new_aggregation(&mut self, agg: Aggregation) -> Variable { fn new_aggregation(&mut self, agg: Aggregation) -> Variable {
@ -533,11 +535,11 @@ mod grammar {
pub fn read_sparql_query<'a, R: Read + 'a>( pub fn read_sparql_query<'a, R: Read + 'a>(
source: R, source: R,
base_uri: Option<&'a str>, base_iri: Option<&'a str>,
) -> super::super::super::Result<QueryVariants> { ) -> super::super::super::Result<QueryVariants> {
let mut state = ParserState { let mut state = ParserState {
base_uri: if let Some(base_uri) = base_uri { base_iri: if let Some(base_iri) = base_iri {
Some(Url::parse(base_uri)?) Some(Iri::parse(base_iri.to_owned())?)
} else { } else {
None None
}, },

@ -19,19 +19,13 @@ Query -> QueryVariants = _ Prologue _ q:(SelectQuery / ConstructQuery / Describe
Prologue -> () = (BaseDecl _ / PrefixDecl _)* Prologue -> () = (BaseDecl _ / PrefixDecl _)*
//[5] //[5]
BaseDecl -> () = "BASE"i _ i:IRIREF {? BaseDecl -> () = "BASE"i _ i:IRIREF {
match state.url_parser().parse(&i) { state.base_iri = Some(i)
Ok(url) => {
state.base_uri = Some(url);
Ok(())
},
Err(error) => Err("IRI parsing failed")
}
} }
//[6] //[6]
PrefixDecl -> () = "PREFIX"i _ ns:PNAME_NS _ i:IRIREF { PrefixDecl -> () = "PREFIX"i _ ns:PNAME_NS _ i:IRIREF {
state.namespaces.insert(ns.into(), i); state.namespaces.insert(ns.into(), i.into_string());
} }
//[7] //[7]
@ -905,16 +899,17 @@ BooleanLiteral -> Literal =
String -> String = STRING_LITERAL_LONG1 / STRING_LITERAL_LONG2 / STRING_LITERAL1 / STRING_LITERAL2 String -> String = STRING_LITERAL_LONG1 / STRING_LITERAL_LONG2 / STRING_LITERAL1 / STRING_LITERAL2
//[136] //[136]
iri -> NamedNode = i:(IRIREF / PrefixedName) {? iri -> NamedNode = i:(IRIREF / PrefixedName) {
match state.url_parser().parse(&i) { NamedNode::new_from_iri(i)
Ok(url) => Ok(NamedNode::new(url.into_string())),
Err(error) => Err("IRI parsing failed")
}
} }
//[137] //[137]
PrefixedName -> String = PNAME_LN / PrefixedName -> Iri = PNAME_LN /
ns:PNAME_NS {? state.namespaces.get(ns).cloned().ok_or("Prefix not found") } ns:PNAME_NS {? if let Some(iri) = state.namespaces.get(ns).cloned() {
Iri::parse(iri).map_err(|_| "IRI parsing failed")
} else {
Err("Prefix not found")
} }
//[138] //[138]
BlankNode -> BlankNode = BlankNode -> BlankNode =
@ -922,8 +917,8 @@ BlankNode -> BlankNode =
ANON { BlankNode::default() } ANON { BlankNode::default() }
//[139] //[139]
IRIREF -> String = "<" i:$(([^\u{00}-\u{20}<>"{}|^\u{60}\u{5c}])*) ">" { IRIREF -> Iri = "<" i:$(([^\u{00}-\u{20}<>"{}|^\u{60}\u{5c}])*) ">" {?
i.to_owned() state.parse_iri(i).map_err(|_| "IRI parsing failed")
} }
//[140] //[140]
@ -932,8 +927,12 @@ PNAME_NS -> &'input str = ns:$(PN_PREFIX? ":") {
} }
//[141] //[141]
PNAME_LN -> String = ns:$(PNAME_NS) local:$(PN_LOCAL) {? PNAME_LN -> Iri = ns:$(PNAME_NS) local:$(PN_LOCAL) {?
state.namespaces.get(ns).map(|v| v.clone() + &unescape_pn_local(local)).ok_or("Prefix not found") if let Some(iri) = state.namespaces.get(ns).map(|v| v.clone() + &unescape_pn_local(local)) {
Iri::parse(iri).map_err(|_| "IRI parsing failed")
} else {
Err("Prefix not found")
}
} }
//[142] //[142]

@ -339,9 +339,12 @@ impl<R: BufRead> Iterator for ResultsIterator<R> {
} else if attr.key == b"datatype" { } else if attr.key == b"datatype" {
match attr.unescaped_value() { match attr.unescaped_value() {
Ok(val) => { Ok(val) => {
datatype = Some(NamedNode::new( match NamedNode::parse(
self.reader.decode(&val).to_string(), self.reader.decode(&val).to_string(),
)); ) {
Ok(iri) => datatype = Some(iri),
Err(error) => return Some(Err(error)),
}
} }
Err(error) => return Some(Err(error.into())), Err(error) => return Some(Err(error.into())),
} }
@ -360,7 +363,12 @@ impl<R: BufRead> Iterator for ResultsIterator<R> {
}, },
Event::Text(event) => match event.unescaped() { Event::Text(event) => match event.unescaped() {
Ok(data) => match state { Ok(data) => match state {
State::Uri => term = Some(NamedNode::new(self.reader.decode(&data)).into()), State::Uri => match NamedNode::parse(self.reader.decode(&data)) {
Ok(uri) => {
term = Some(uri.into());
}
Err(error) => return Some(Err(error)),
},
State::BNode => { State::BNode => {
term = Some( term = Some(
self.bnodes_map self.bnodes_map

@ -23,7 +23,7 @@ use std::sync::RwLockWriteGuard;
/// let connection = repository.connection().unwrap(); /// let connection = repository.connection().unwrap();
/// ///
/// // insertion /// // insertion
/// let ex = NamedNode::new("http://example.com"); /// let ex = NamedNode::parse("http://example.com").unwrap();
/// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None); /// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
/// connection.insert(&quad); /// connection.insert(&quad);
/// ///

@ -714,7 +714,7 @@ impl<S: StringStore> Encoder<S> {
//TODO: optimize //TODO: optimize
self.encode_literal(&Literal::new_typed_literal( self.encode_literal(&Literal::new_typed_literal(
value, value,
NamedNode::new(datatype.iri), NamedNode::new_from_string(datatype.iri),
)) ))
} }
} }
@ -781,7 +781,7 @@ impl<S: StringStore> Encoder<S> {
Err(format_err!("The default graph tag is not a valid term")) Err(format_err!("The default graph tag is not a valid term"))
} }
EncodedTerm::NamedNode { iri_id } => { EncodedTerm::NamedNode { iri_id } => {
Ok(NamedNode::new(self.string_store.get_str(iri_id)?).into()) Ok(NamedNode::new_from_string(self.string_store.get_str(iri_id)?).into())
} }
EncodedTerm::BlankNode(id) => Ok(BlankNode::from(id).into()), EncodedTerm::BlankNode(id) => Ok(BlankNode::from(id).into()),
EncodedTerm::StringLiteral { value_id } => { EncodedTerm::StringLiteral { value_id } => {
@ -800,7 +800,7 @@ impl<S: StringStore> Encoder<S> {
datatype_id, datatype_id,
} => Ok(Literal::new_typed_literal( } => Ok(Literal::new_typed_literal(
self.string_store.get_str(value_id)?, self.string_store.get_str(value_id)?,
NamedNode::new(self.string_store.get_str(datatype_id)?), NamedNode::new_from_string(self.string_store.get_str(datatype_id)?),
) )
.into()), .into()),
EncodedTerm::BooleanLiteral(value) => Ok(Literal::from(value).into()), EncodedTerm::BooleanLiteral(value) => Ok(Literal::from(value).into()),
@ -884,9 +884,9 @@ impl<T> From<PoisonError<T>> for MutexPoisonError {
fn test_encoding() { fn test_encoding() {
let encoder: Encoder<MemoryStringStore> = Encoder::default(); let encoder: Encoder<MemoryStringStore> = Encoder::default();
let terms: Vec<Term> = vec![ let terms: Vec<Term> = vec![
NamedNode::new("http://foo.com").into(), NamedNode::new_from_string("http://foo.com").into(),
NamedNode::new("http://bar.com").into(), NamedNode::new_from_string("http://bar.com").into(),
NamedNode::new("http://foo.com").into(), NamedNode::new_from_string("http://foo.com").into(),
BlankNode::default().into(), BlankNode::default().into(),
Literal::new_simple_literal("foo").into(), Literal::new_simple_literal("foo").into(),
Literal::from(true).into(), Literal::from(true).into(),

@ -33,7 +33,7 @@ use std::sync::Mutex;
/// let connection = repository.connection().unwrap(); /// let connection = repository.connection().unwrap();
/// ///
/// // insertion /// // insertion
/// let ex = NamedNode::new("http://example.com"); /// let ex = NamedNode::parse("http://example.com").unwrap();
/// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None); /// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
/// connection.insert(&quad); /// connection.insert(&quad);
/// ///

@ -18,10 +18,10 @@ fn sparql_w3c_syntax_testsuite() -> Result<()> {
let manifest_11_url = let manifest_11_url =
"http://www.w3.org/2009/sparql/docs/tests/data-sparql11/syntax-query/manifest.ttl"; "http://www.w3.org/2009/sparql/docs/tests/data-sparql11/syntax-query/manifest.ttl";
let test_blacklist = vec![ let test_blacklist = vec![
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql2/manifest#syntax-form-construct02"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql2/manifest#syntax-form-construct02").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql2/manifest#syntax-form-construct04"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql2/manifest#syntax-form-construct04").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql2/manifest#syntax-function-04"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql2/manifest#syntax-function-04").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql1/manifest#syntax-qname-04"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql1/manifest#syntax-qname-04").unwrap(),
]; ];
for test_result in TestManifest::new(manifest_10_url).chain(TestManifest::new(manifest_11_url)) for test_result in TestManifest::new(manifest_10_url).chain(TestManifest::new(manifest_11_url))
@ -85,29 +85,25 @@ fn sparql_w3c_query_evaluation_testsuite() -> Result<()> {
]; ];
let test_blacklist = vec![ let test_blacklist = vec![
//Multiple writing of the same xsd:integer. Our system does strong normalization. //Multiple writing of the same xsd:integer. Our system does strong normalization.
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-1"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-1").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-9"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-9").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#dawg-str-1"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#dawg-str-1").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#dawg-str-2"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#dawg-str-2").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-equals/manifest#eq-graph-1"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-equals/manifest#eq-graph-1").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-equals/manifest#eq-graph-2"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-equals/manifest#eq-graph-2").unwrap(),
//Multiple writing of the same xsd:double. Our system does strong normalization. //Multiple writing of the same xsd:double. Our system does strong normalization.
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm-simple"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm-simple").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm-eq"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm-eq").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm-not-eq"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm-not-eq").unwrap(),
//Simple literal vs xsd:string. We apply RDF 1.1 //Simple literal vs xsd:string. We apply RDF 1.1
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-2"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-2").unwrap(),
//URI normalization: we are not normalizing well //URI normalization: we are not normalizing well
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/i18n/manifest#normalization-1"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/i18n/manifest#normalization-2").unwrap(),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/i18n/manifest#normalization-2"),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/i18n/manifest#normalization-3"),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/i18n/manifest#kanji-1"),
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/i18n/manifest#kanji-2"),
//Test on curly brace scoping with OPTIONAL filter //Test on curly brace scoping with OPTIONAL filter
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/optional-filter/manifest#dawg-optional-filter-005-not-simplified"), NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/optional-filter/manifest#dawg-optional-filter-005-not-simplified").unwrap(),
//DATATYPE("foo"@en) returns rdf:langString in SPARQL 1.1 //DATATYPE("foo"@en) returns rdf:langString in SPARQL 1.1
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#dawg-datatype-2") NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#dawg-datatype-2").unwrap()
]; ];
for test_result in manifest_10_urls for test_result in manifest_10_urls
@ -127,7 +123,7 @@ fn sparql_w3c_query_evaluation_testsuite() -> Result<()> {
load_graph_to_repository( load_graph_to_repository(
&graph_data, &graph_data,
&repository.connection()?, &repository.connection()?,
Some(&NamedNode::new(graph_data).into()), Some(&NamedNode::parse(graph_data)?.into()),
)?; )?;
} }
match repository match repository
@ -260,21 +256,30 @@ mod rs {
lazy_static! { lazy_static! {
pub static ref RESULT_SET: NamedNode = pub static ref RESULT_SET: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#ResultSet"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/result-set#ResultSet")
pub static ref RESULT_VARIABLE: NamedNode = .unwrap();
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#resultVariable"); pub static ref RESULT_VARIABLE: NamedNode = NamedNode::parse(
"http://www.w3.org/2001/sw/DataAccess/tests/result-set#resultVariable"
)
.unwrap();
pub static ref SOLUTION: NamedNode = pub static ref SOLUTION: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#solution"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/result-set#solution")
.unwrap();
pub static ref BINDING: NamedNode = pub static ref BINDING: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#binding"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/result-set#binding")
.unwrap();
pub static ref VALUE: NamedNode = pub static ref VALUE: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#value"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/result-set#value")
.unwrap();
pub static ref VARIABLE: NamedNode = pub static ref VARIABLE: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#variable"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/result-set#variable")
.unwrap();
pub static ref INDEX: NamedNode = pub static ref INDEX: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#index"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/result-set#index")
.unwrap();
pub static ref BOOLEAN: NamedNode = pub static ref BOOLEAN: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/result-set#boolean"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/result-set#boolean")
.unwrap();
} }
} }
@ -409,15 +414,20 @@ pub mod mf {
lazy_static! { lazy_static! {
pub static ref INCLUDE: NamedNode = pub static ref INCLUDE: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#include"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#include")
.unwrap();
pub static ref ENTRIES: NamedNode = pub static ref ENTRIES: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#entries"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#entries")
.unwrap();
pub static ref NAME: NamedNode = pub static ref NAME: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#name"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#name")
.unwrap();
pub static ref ACTION: NamedNode = pub static ref ACTION: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#action"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#action")
.unwrap();
pub static ref RESULT: NamedNode = pub static ref RESULT: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#result"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#result")
.unwrap();
} }
} }
@ -427,11 +437,13 @@ pub mod qt {
lazy_static! { lazy_static! {
pub static ref QUERY: NamedNode = pub static ref QUERY: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-query#query"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/test-query#query")
.unwrap();
pub static ref DATA: NamedNode = pub static ref DATA: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-query#data"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/test-query#data").unwrap();
pub static ref GRAPH_DATA: NamedNode = pub static ref GRAPH_DATA: NamedNode =
NamedNode::new("http://www.w3.org/2001/sw/DataAccess/tests/test-query#graphData"); NamedNode::parse("http://www.w3.org/2001/sw/DataAccess/tests/test-query#graphData")
.unwrap();
} }
} }
@ -523,7 +535,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())); let manifest =
NamedOrBlankNode::from(NamedNode::parse(url.clone()).unwrap());
match load_graph(&url) { match load_graph(&url) {
Ok(g) => self.graph.extend(g.into_iter()), Ok(g) => self.graph.extend(g.into_iter()),
Err(e) => return Some(Err(e.into())), Err(e) => return Some(Err(e.into())),

Loading…
Cancel
Save