Allows to reuse it in other crates like spargebrapull/190/head
parent
4337349aad
commit
f5545f1948
@ -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. |
@ -1,6 +1,6 @@ |
|||||||
//! Interning of RDF elements using Rodeo
|
//! Interning of RDF elements using Rodeo
|
||||||
|
|
||||||
use crate::model::*; |
use crate::*; |
||||||
use lasso::{Key, Rodeo, Spur}; |
use lasso::{Key, Rodeo, Spur}; |
||||||
use std::collections::HashMap; |
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,6 +1,6 @@ |
|||||||
//! This crate provides implementation of [Sophia](https://docs.rs/sophia/) traits for the `model` module.
|
//! 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 sophia_api::term::*; |
||||||
use std::fmt; |
use std::fmt; |
||||||
|
|
@ -1,7 +1,7 @@ |
|||||||
use crate::model::blank_node::BlankNode; |
use crate::blank_node::BlankNode; |
||||||
use crate::model::literal::Literal; |
use crate::literal::Literal; |
||||||
use crate::model::named_node::NamedNode; |
use crate::named_node::NamedNode; |
||||||
use crate::model::{BlankNodeRef, LiteralRef, NamedNodeRef}; |
use crate::{BlankNodeRef, LiteralRef, NamedNodeRef}; |
||||||
use std::fmt; |
use std::fmt; |
||||||
use std::sync::Arc; |
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 {} |
@ -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; |
|
Loading…
Reference in new issue