use crate::oxrdf::Variable;
use crate::sparesults::csv::{FromReadTsvQueryResultsReader, FromReadTsvSolutionsReader};
#[cfg(feature = "async-tokio")]
use crate::sparesults::csv::{
FromTokioAsyncReadTsvQueryResultsReader, FromTokioAsyncReadTsvSolutionsReader,
};
use crate::sparesults::error::{QueryResultsParseError, QueryResultsSyntaxError};
use crate::sparesults::format::QueryResultsFormat;
use crate::sparesults::json::{FromReadJsonQueryResultsReader, FromReadJsonSolutionsReader};
#[cfg(feature = "async-tokio")]
use crate::sparesults::json::{
FromTokioAsyncReadJsonQueryResultsReader, FromTokioAsyncReadJsonSolutionsReader,
};
use crate::sparesults::solution::QuerySolution;
use crate::sparesults::xml::{FromReadXmlQueryResultsReader, FromReadXmlSolutionsReader};
#[cfg(feature = "async-tokio")]
use crate::sparesults::xml::{
FromTokioAsyncReadXmlQueryResultsReader, FromTokioAsyncReadXmlSolutionsReader,
};
use std::io::Read;
use std::sync::Arc;
#[cfg(feature = "async-tokio")]
use tokio::io::AsyncRead;
pub struct QueryResultsParser {
format: QueryResultsFormat,
}
impl QueryResultsParser {
#[inline]
pub fn from_format(format: QueryResultsFormat) -> Self {
Self { format }
}
pub fn parse_read<R: Read>(
&self,
reader: R,
) -> Result<FromReadQueryResultsReader<R>, QueryResultsParseError> {
Ok(match self.format {
QueryResultsFormat::Xml => match FromReadXmlQueryResultsReader::read(reader)? {
FromReadXmlQueryResultsReader::Boolean(r) => FromReadQueryResultsReader::Boolean(r),
FromReadXmlQueryResultsReader::Solutions {
solutions,
variables,
} => FromReadQueryResultsReader::Solutions(FromReadSolutionsReader {
variables: variables.into(),
solutions: FromReadSolutionsReaderKind::Xml(solutions),
}),
},
QueryResultsFormat::Json => match FromReadJsonQueryResultsReader::read(reader)? {
FromReadJsonQueryResultsReader::Boolean(r) => FromReadQueryResultsReader::Boolean(r),
FromReadJsonQueryResultsReader::Solutions {
solutions,
variables,
} => FromReadQueryResultsReader::Solutions(FromReadSolutionsReader {
variables: variables.into(),
solutions: FromReadSolutionsReaderKind::Json(solutions),
}),
},
QueryResultsFormat::Csv => return Err(QueryResultsSyntaxError::msg("CSV SPARQL results syntax is lossy and can't be parsed to a proper RDF representation").into()),
QueryResultsFormat::Tsv => match FromReadTsvQueryResultsReader::read(reader)? {
FromReadTsvQueryResultsReader::Boolean(r) => FromReadQueryResultsReader::Boolean(r),
FromReadTsvQueryResultsReader::Solutions {
solutions,
variables,
} => FromReadQueryResultsReader::Solutions(FromReadSolutionsReader {
variables: variables.into(),
solutions: FromReadSolutionsReaderKind::Tsv(solutions),
}),
},
})
}
#[deprecated(note = "use parse_read", since = "0.4.0")]
pub fn read_results<R: Read>(
&self,
reader: R,
) -> Result<FromReadQueryResultsReader<R>, QueryResultsParseError> {
self.parse_read(reader)
}
#[cfg(feature = "async-tokio")]
pub async fn parse_tokio_async_read<R: AsyncRead + Unpin>(
&self,
reader: R,
) -> Result<FromTokioAsyncReadQueryResultsReader<R>, QueryResultsParseError> {
Ok(match self.format {
QueryResultsFormat::Xml => match FromTokioAsyncReadXmlQueryResultsReader::read(reader).await? {
FromTokioAsyncReadXmlQueryResultsReader::Boolean(r) => FromTokioAsyncReadQueryResultsReader::Boolean(r),
FromTokioAsyncReadXmlQueryResultsReader::Solutions {
solutions,
variables,
} => FromTokioAsyncReadQueryResultsReader::Solutions(FromTokioAsyncReadSolutionsReader {
variables: variables.into(),
solutions: FromTokioAsyncReadSolutionsReaderKind::Xml(solutions),
}),
},
QueryResultsFormat::Json => match FromTokioAsyncReadJsonQueryResultsReader::read(reader).await? {
FromTokioAsyncReadJsonQueryResultsReader::Boolean(r) => FromTokioAsyncReadQueryResultsReader::Boolean(r),
FromTokioAsyncReadJsonQueryResultsReader::Solutions {
solutions,
variables,
} => FromTokioAsyncReadQueryResultsReader::Solutions(FromTokioAsyncReadSolutionsReader {
variables: variables.into(),
solutions: FromTokioAsyncReadSolutionsReaderKind::Json(solutions),
}),
},
QueryResultsFormat::Csv => return Err(QueryResultsSyntaxError::msg("CSV SPARQL results syntax is lossy and can't be parsed to a proper RDF representation").into()),
QueryResultsFormat::Tsv => match FromTokioAsyncReadTsvQueryResultsReader::read(reader).await? {
FromTokioAsyncReadTsvQueryResultsReader::Boolean(r) => FromTokioAsyncReadQueryResultsReader::Boolean(r),
FromTokioAsyncReadTsvQueryResultsReader::Solutions {
solutions,
variables,
} => FromTokioAsyncReadQueryResultsReader::Solutions(FromTokioAsyncReadSolutionsReader {
variables: variables.into(),
solutions: FromTokioAsyncReadSolutionsReaderKind::Tsv(solutions),
}),
},
})
}
}
impl From<QueryResultsFormat> for QueryResultsParser {
fn from(format: QueryResultsFormat) -> Self {
Self::from_format(format)
}
}
pub enum FromReadQueryResultsReader<R: Read> {
Solutions(FromReadSolutionsReader<R>),
Boolean(bool),
}
pub struct FromReadSolutionsReader<R: Read> {
variables: Arc<[Variable]>,
solutions: FromReadSolutionsReaderKind<R>,
}
enum FromReadSolutionsReaderKind<R: Read> {
Xml(FromReadXmlSolutionsReader<R>),
Json(FromReadJsonSolutionsReader<R>),
Tsv(FromReadTsvSolutionsReader<R>),
}
impl<R: Read> FromReadSolutionsReader<R> {
#[inline]
pub fn variables(&self) -> &[Variable] {
&self.variables
}
}
impl<R: Read> Iterator for FromReadSolutionsReader<R> {
type Item = Result<QuerySolution, QueryResultsParseError>;
fn next(&mut self) -> Option<Self::Item> {
Some(
match &mut self.solutions {
FromReadSolutionsReaderKind::Xml(reader) => reader.read_next(),
FromReadSolutionsReaderKind::Json(reader) => reader.read_next(),
FromReadSolutionsReaderKind::Tsv(reader) => reader.read_next(),
}
.transpose()?
.map(|values| (Arc::clone(&self.variables), values).into()),
)
}
}
#[cfg(feature = "async-tokio")]
pub enum FromTokioAsyncReadQueryResultsReader<R: AsyncRead + Unpin> {
Solutions(FromTokioAsyncReadSolutionsReader<R>),
Boolean(bool),
}
#[cfg(feature = "async-tokio")]
pub struct FromTokioAsyncReadSolutionsReader<R: AsyncRead + Unpin> {
variables: Arc<[Variable]>,
solutions: FromTokioAsyncReadSolutionsReaderKind<R>,
}
#[cfg(feature = "async-tokio")]
enum FromTokioAsyncReadSolutionsReaderKind<R: AsyncRead + Unpin> {
Json(FromTokioAsyncReadJsonSolutionsReader<R>),
Xml(FromTokioAsyncReadXmlSolutionsReader<R>),
Tsv(FromTokioAsyncReadTsvSolutionsReader<R>),
}
#[cfg(feature = "async-tokio")]
impl<R: AsyncRead + Unpin> FromTokioAsyncReadSolutionsReader<R> {
#[inline]
pub fn variables(&self) -> &[Variable] {
&self.variables
}
pub async fn next(&mut self) -> Option<Result<QuerySolution, QueryResultsParseError>> {
Some(
match &mut self.solutions {
FromTokioAsyncReadSolutionsReaderKind::Json(reader) => reader.read_next().await,
FromTokioAsyncReadSolutionsReaderKind::Xml(reader) => reader.read_next().await,
FromTokioAsyncReadSolutionsReaderKind::Tsv(reader) => reader.read_next().await,
}
.transpose()?
.map(|values| (Arc::clone(&self.variables), values).into()),
)
}
}