use crate::error::QueryEvaluationError;
use oxrdf::{Term, Triple, Variable};
pub use sparesults::QuerySolution;
use sparesults::{
ReaderQueryResultsParserOutput, ReaderSolutionsParser, SliceQueryResultsParserOutput,
SliceSolutionsParser,
};
use std::io::Read;
use std::sync::Arc;
pub enum QueryResults<'a> {
Solutions(QuerySolutionIter<'a>),
Boolean(bool),
Graph(QueryTripleIter<'a>),
}
impl<'a> From<QuerySolutionIter<'a>> for QueryResults<'a> {
#[inline]
fn from(value: QuerySolutionIter<'a>) -> Self {
Self::Solutions(value)
}
}
impl From<bool> for QueryResults<'_> {
#[inline]
fn from(value: bool) -> Self {
Self::Boolean(value)
}
}
impl<'a> From<QueryTripleIter<'a>> for QueryResults<'a> {
#[inline]
fn from(value: QueryTripleIter<'a>) -> Self {
Self::Graph(value)
}
}
impl<'a, R: Read + 'a> From<ReaderQueryResultsParserOutput<R>> for QueryResults<'a> {
#[inline]
fn from(output: ReaderQueryResultsParserOutput<R>) -> Self {
match output {
ReaderQueryResultsParserOutput::Solutions(output) => Self::Solutions(output.into()),
ReaderQueryResultsParserOutput::Boolean(output) => Self::Boolean(output),
}
}
}
impl<'a> From<SliceQueryResultsParserOutput<'a>> for QueryResults<'a> {
#[inline]
fn from(output: SliceQueryResultsParserOutput<'a>) -> Self {
match output {
SliceQueryResultsParserOutput::Solutions(output) => Self::Solutions(output.into()),
SliceQueryResultsParserOutput::Boolean(output) => Self::Boolean(output),
}
}
}
pub struct QuerySolutionIter<'a> {
variables: Arc<[Variable]>,
iter: Box<dyn Iterator<Item = Result<QuerySolution, QueryEvaluationError>> + 'a>,
}
impl<'a> QuerySolutionIter<'a> {
pub fn new(
variables: Arc<[Variable]>,
iter: impl IntoIterator<Item = Result<QuerySolution, QueryEvaluationError>> + 'a,
) -> Self {
Self {
variables,
iter: Box::new(iter.into_iter()),
}
}
pub fn from_tuples(
variables: Arc<[Variable]>,
iter: impl IntoIterator<Item = Result<Vec<Option<Term>>, QueryEvaluationError>> + 'a,
) -> Self {
Self::new(
Arc::clone(&variables),
iter.into_iter()
.map(move |values| Ok((Arc::clone(&variables), values?).into())),
)
}
#[inline]
pub fn variables(&self) -> &[Variable] {
&self.variables
}
}
impl Iterator for QuerySolutionIter<'_> {
type Item = Result<QuerySolution, QueryEvaluationError>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, R: Read + 'a> From<ReaderSolutionsParser<R>> for QuerySolutionIter<'a> {
#[inline]
fn from(parser: ReaderSolutionsParser<R>) -> Self {
Self {
variables: parser.variables().into(),
iter: Box::new(
parser.map(|r| r.map_err(|e| QueryEvaluationError::Unexpected(e.into()))),
),
}
}
}
impl<'a> From<SliceSolutionsParser<'a>> for QuerySolutionIter<'a> {
#[inline]
fn from(parser: SliceSolutionsParser<'a>) -> Self {
Self {
variables: parser.variables().into(),
iter: Box::new(
parser.map(|r| r.map_err(|e| QueryEvaluationError::Unexpected(e.into()))),
),
}
}
}
pub struct QueryTripleIter<'a> {
iter: Box<dyn Iterator<Item = Result<Triple, QueryEvaluationError>> + 'a>,
}
impl<'a> QueryTripleIter<'a> {
pub fn new(iter: impl Iterator<Item = Result<Triple, QueryEvaluationError>> + 'a) -> Self {
Self {
iter: Box::new(iter),
}
}
}
impl Iterator for QueryTripleIter<'_> {
type Item = Result<Triple, QueryEvaluationError>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}