use std::error::Error;
use crate::graph::adapter::{DatasetGraph, PartialUnionGraph, UnionGraph};
use crate::quad::{iter_spog, Quad};
use crate::source::{IntoSource, QuadSource, StreamResult};
use crate::term::matcher::{GraphNameMatcher, TermMatcher};
use crate::term::{GraphName, SimpleTerm, Term};
use resiter::{filter::*, filter_map::*, flat_map::*, map::*};
mod _foreign_impl;
pub mod adapter;
#[cfg(any(test, feature = "test_macro"))]
#[macro_use]
pub mod test;
pub type DResult<D, T> = Result<T, <D as Dataset>::Error>;
#[deprecated(
since = "0.8.1",
note = "prototypes of `quads` and `quads_matching` have changed"
)]
pub type DQuadSource<'a, D> = Box<dyn Iterator<Item = DResult<D, <D as Dataset>::Quad<'a>>> + 'a>;
pub type DTerm<'a, D> = <<D as Dataset>::Quad<'a> as Quad>::Term;
#[deprecated(
since = "0.8.1",
note = "prototypes of term-yielding methods have changed"
)]
pub type DTermSource<'a, D> = Box<dyn Iterator<Item = DResult<D, DTerm<'a, D>>> + 'a>;
pub trait Dataset {
type Quad<'x>: Quad
where
Self: 'x;
type Error: Error + Send + Sync + 'static;
fn quads(&self) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_;
fn quads_matching<'s, S, P, O, G>(
&'s self,
sm: S,
pm: P,
om: O,
gm: G,
) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_
where
S: TermMatcher + 's,
P: TermMatcher + 's,
O: TermMatcher + 's,
G: GraphNameMatcher + 's,
{
self.quads().filter_ok(move |q| {
q.matched_by(
sm.matcher_ref(),
pm.matcher_ref(),
om.matcher_ref(),
gm.matcher_ref(),
)
})
}
fn contains<TS, TP, TO, TG>(&self, s: TS, p: TP, o: TO, g: GraphName<TG>) -> DResult<Self, bool>
where
TS: Term,
TP: Term,
TO: Term,
TG: Term,
{
self.quads_matching([s], [p], [o], [g])
.next()
.transpose()
.map(|o| o.is_some())
}
fn subjects(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
self.quads().map_ok(Quad::to_s)
}
fn predicates(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
self.quads().map_ok(Quad::to_p)
}
fn objects(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
self.quads().map_ok(Quad::to_o)
}
fn graph_names(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
self.quads().filter_map_ok(Quad::to_g)
}
fn iris(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
self.quads()
.flat_map_ok(iter_spog)
.flat_map_ok(Term::to_atoms)
.filter_ok(Term::is_iri)
}
fn blank_nodes(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
self.quads()
.flat_map_ok(iter_spog)
.flat_map_ok(Term::to_atoms)
.filter_ok(Term::is_blank_node)
}
fn literals(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
self.quads()
.flat_map_ok(iter_spog)
.flat_map_ok(Term::to_atoms)
.filter_ok(Term::is_literal)
}
fn quoted_triples<'s>(&'s self) -> Box<dyn Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_>
where
DTerm<'s, Self>: Clone,
{
Box::new(
self.quads()
.flat_map_ok(iter_spog)
.flat_map_ok(Term::to_constituents)
.filter_ok(Term::is_triple),
)
}
fn variables(&self) -> impl Iterator<Item = DResult<Self, DTerm<'_, Self>>> + '_ {
self.quads()
.flat_map_ok(iter_spog)
.flat_map_ok(Term::to_atoms)
.filter_ok(Term::is_variable)
}
fn graph<T>(&self, graph_name: GraphName<T>) -> DatasetGraph<&Self, T>
where
T: for<'x> Term<BorrowTerm<'x> = DTerm<'x, Self>> + 'static,
{
DatasetGraph::new(self, graph_name)
}
fn graph_mut<T>(&mut self, graph_name: GraphName<T>) -> DatasetGraph<&mut Self, T>
where
T: for<'x> Term<BorrowTerm<'x> = DTerm<'x, Self>> + 'static,
{
DatasetGraph::new(self, graph_name)
}
fn partial_union_graph<M>(&self, selector: M) -> PartialUnionGraph<&Self, M>
where
M: GraphNameMatcher + Copy,
{
PartialUnionGraph::new(self, selector)
}
fn union_graph(&self) -> UnionGraph<&Self> {
UnionGraph::new(self)
}
fn into_union_graph(self) -> UnionGraph<Self>
where
Self: Sized,
{
UnionGraph::new(self)
}
}
pub trait CollectibleDataset: Dataset + Sized {
fn from_quad_source<TS: QuadSource>(quads: TS) -> StreamResult<Self, TS::Error, Self::Error>;
}
pub type MdResult<D, T> = std::result::Result<T, <D as MutableDataset>::MutationError>;
pub trait MutableDataset: Dataset {
type MutationError: Error + Send + Sync + 'static;
fn insert<TS, TP, TO, TG>(
&mut self,
s: TS,
p: TP,
o: TO,
g: GraphName<TG>,
) -> MdResult<Self, bool>
where
TS: Term,
TP: Term,
TO: Term,
TG: Term;
fn insert_quad<T>(&mut self, quad: T) -> MdResult<Self, bool>
where
T: Quad,
{
let ([s, p, o], g) = quad.to_spog();
self.insert(s, p, o, g)
}
fn remove<TS, TP, TO, TG>(
&mut self,
s: TS,
p: TP,
o: TO,
g: GraphName<TG>,
) -> MdResult<Self, bool>
where
TS: Term,
TP: Term,
TO: Term,
TG: Term;
fn remove_quad<T>(&mut self, quad: T) -> MdResult<Self, bool>
where
T: Quad,
{
let ([s, p, o], g) = quad.to_spog();
self.remove(s, p, o, g)
}
#[inline]
fn insert_all<TS: QuadSource>(
&mut self,
src: TS,
) -> StreamResult<usize, TS::Error, <Self as MutableDataset>::MutationError> {
let mut src = src;
let mut c = 0;
src.try_for_each_quad(|q| -> MdResult<Self, ()> {
if self.insert_quad(q.spog())? {
c += 1;
}
Ok(())
})
.and(Ok(c))
}
#[inline]
fn remove_all<TS: QuadSource>(
&mut self,
src: TS,
) -> StreamResult<usize, TS::Error, <Self as MutableDataset>::MutationError> {
let mut src = src;
let mut c = 0;
src.try_for_each_quad(|q| -> MdResult<Self, ()> {
if self.remove_quad(q.spog())? {
c += 1;
}
Ok(())
})
.and(Ok(c))
}
fn remove_matching<S, P, O, G>(
&mut self,
ms: S,
mp: P,
mo: O,
mg: G,
) -> Result<usize, Self::MutationError>
where
S: TermMatcher,
P: TermMatcher,
O: TermMatcher,
G: GraphNameMatcher,
Self::MutationError: From<Self::Error>,
{
let to_remove: Result<Vec<([SimpleTerm; 3], GraphName<SimpleTerm>)>, _> = self
.quads_matching(ms, mp, mo, mg)
.map_ok(|q| {
let (spo, g) = q.spog();
(spo.map(Term::into_term), g.map(Term::into_term))
})
.collect();
self.remove_all(to_remove?.into_iter().into_source())
.map_err(|err| err.unwrap_sink_error())
}
fn retain_matching<S, P, O, G>(
&mut self,
ms: S,
mp: P,
mo: O,
mg: G,
) -> Result<(), Self::MutationError>
where
S: TermMatcher,
P: TermMatcher,
O: TermMatcher,
G: GraphNameMatcher,
Self::MutationError: From<Self::Error>,
{
let to_remove: Result<Vec<([SimpleTerm; 3], GraphName<SimpleTerm>)>, _> = self
.quads()
.filter_ok(|q| {
!q.matched_by(
ms.matcher_ref(),
mp.matcher_ref(),
mo.matcher_ref(),
mg.matcher_ref(),
)
})
.map_ok(|q| {
let (spo, g) = q.spog();
(spo.map(Term::into_term), g.map(Term::into_term))
})
.collect();
self.remove_all(to_remove?.into_iter().into_source())
.map_err(|err| err.unwrap_sink_error())?;
Ok(())
}
}
pub trait SetDataset: Dataset {}
mod check_implementability {
use super::*;
use crate::term::SimpleTerm;
use std::collections::HashMap;
#[derive(Clone, Debug, Eq, PartialEq)]
#[allow(dead_code)] enum MyInternalTerm {
Atom(SimpleTerm<'static>),
QuotedTriple(usize),
}
use MyInternalTerm::*;
#[derive(Clone, Debug)]
struct MyDataset {
terms: Vec<MyInternalTerm>,
triples: Vec<[usize; 3]>,
graphs: HashMap<usize, Vec<usize>>,
}
impl MyDataset {
fn make_term(&self, i: usize) -> SimpleTerm<'_> {
match &self.terms[i] {
Atom(t) => t.as_simple(),
QuotedTriple(j) => {
SimpleTerm::Triple(Box::new(self.triples[*j].map(|k| self.make_term(k))))
}
}
}
}
impl Dataset for MyDataset {
type Quad<'x> = [SimpleTerm<'x>; 4] where Self: 'x;
type Error = std::convert::Infallible;
fn quads(&self) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_ {
self.graphs.iter().flat_map(move |(gi, tis)| {
let g = self.make_term(*gi);
tis.iter().copied().map(move |ti| {
let [s, p, o] = self.triples[ti].map(|j| self.make_term(j));
Ok([s, p, o, g.clone()])
})
})
}
}
}
#[cfg(test)]
mod check_implementability_lazy_term {
use super::*;
use crate::term::{SimpleTerm, TermKind};
use std::collections::HashMap;
#[derive(Clone, Debug, Eq, PartialEq)]
#[allow(dead_code)] enum MyInternalTerm {
Atom(SimpleTerm<'static>),
QuotedTriple(usize),
}
use MyInternalTerm::*;
#[derive(Clone, Debug)]
struct MyDataset {
terms: Vec<MyInternalTerm>,
triples: Vec<[usize; 3]>,
graphs: HashMap<usize, Vec<usize>>,
}
#[derive(Clone, Copy, Debug)]
struct MyTerm<'a> {
dataset: &'a MyDataset,
index: usize,
}
impl<'a> Term for MyTerm<'a> {
type BorrowTerm<'x> = MyTerm<'x> where Self: 'x;
fn kind(&self) -> crate::term::TermKind {
if let Atom(t) = &self.dataset.terms[self.index] {
t.kind()
} else {
TermKind::Triple
}
}
fn iri(&self) -> Option<crate::term::IriRef<mownstr::MownStr>> {
if let Atom(t) = &self.dataset.terms[self.index] {
t.iri()
} else {
None
}
}
fn bnode_id(&self) -> Option<crate::term::BnodeId<mownstr::MownStr>> {
if let Atom(t) = &self.dataset.terms[self.index] {
t.bnode_id()
} else {
None
}
}
fn lexical_form(&self) -> Option<mownstr::MownStr> {
if let Atom(t) = &self.dataset.terms[self.index] {
t.lexical_form()
} else {
None
}
}
fn datatype(&self) -> Option<crate::term::IriRef<mownstr::MownStr>> {
if let Atom(t) = &self.dataset.terms[self.index] {
t.datatype()
} else {
None
}
}
fn language_tag(&self) -> Option<crate::term::LanguageTag<mownstr::MownStr>> {
if let Atom(t) = &self.dataset.terms[self.index] {
t.language_tag()
} else {
None
}
}
fn variable(&self) -> Option<crate::term::VarName<mownstr::MownStr>> {
if let Atom(t) = &self.dataset.terms[self.index] {
t.variable()
} else {
None
}
}
fn triple(&self) -> Option<[Self::BorrowTerm<'_>; 3]> {
self.to_triple()
}
fn to_triple(self) -> Option<[Self; 3]> {
if let QuotedTriple(i) = &self.dataset.terms[self.index] {
Some(self.dataset.triples[*i].map(|t| MyTerm {
dataset: self.dataset,
index: t,
}))
} else {
None
}
}
fn borrow_term(&self) -> Self::BorrowTerm<'_> {
*self
}
}
impl Dataset for MyDataset {
type Quad<'x> = [MyTerm<'x>; 4] where Self: 'x;
type Error = std::convert::Infallible;
fn quads(&self) -> impl Iterator<Item = DResult<Self, Self::Quad<'_>>> + '_ {
self.graphs.iter().flat_map(move |(gi, tis)| {
let g = MyTerm {
dataset: self,
index: *gi,
};
tis.iter().copied().map(move |ti| {
let [s, p, o] = self.triples[ti].map(|j| MyTerm {
dataset: self,
index: j,
});
Ok([s, p, o, g])
})
})
}
}
}