From 412ca37b3c67d9b68c4a05c5c7a4214829f82861 Mon Sep 17 00:00:00 2001 From: Tpt Date: Sat, 16 Sep 2023 16:07:45 +0200 Subject: [PATCH] Makes sparesults parser API closer to oxrdfio --- fuzz/src/result_format.rs | 16 ++++----- lib/sparesults/README.md | 8 ++--- lib/sparesults/src/lib.rs | 2 +- lib/sparesults/src/parser.rs | 63 +++++++++++++++++++++--------------- lib/src/sparql/model.rs | 18 +++++------ lib/src/sparql/results.rs | 14 ++++---- python/src/sparql.rs | 11 ++++--- 7 files changed, 72 insertions(+), 60 deletions(-) diff --git a/fuzz/src/result_format.rs b/fuzz/src/result_format.rs index 139d3c9a..5c6b59ae 100644 --- a/fuzz/src/result_format.rs +++ b/fuzz/src/result_format.rs @@ -1,17 +1,17 @@ use anyhow::Context; use sparesults::{ - QueryResultsFormat, QueryResultsParser, QueryResultsReader, QueryResultsSerializer, + FromReadQueryResultsReader, QueryResultsFormat, QueryResultsParser, QueryResultsSerializer, }; pub fn fuzz_result_format(format: QueryResultsFormat, data: &[u8]) { let parser = QueryResultsParser::from_format(format); let serializer = QueryResultsSerializer::from_format(format); - let Ok(reader) = parser.read_results(data) else { + let Ok(reader) = parser.parse_read(data) else { return; }; match reader { - QueryResultsReader::Solutions(solutions) => { + FromReadQueryResultsReader::Solutions(solutions) => { let Ok(solutions) = solutions.collect::, _>>() else { return; }; @@ -31,8 +31,8 @@ pub fn fuzz_result_format(format: QueryResultsFormat, data: &[u8]) { let serialized = String::from_utf8(writer.finish().unwrap()).unwrap(); // And to parse again - if let QueryResultsReader::Solutions(roundtrip_solutions) = parser - .read_results(serialized.as_bytes()) + if let FromReadQueryResultsReader::Solutions(roundtrip_solutions) = parser + .parse_read(serialized.as_bytes()) .with_context(|| format!("Parsing {:?}", &serialized)) .unwrap() { @@ -45,7 +45,7 @@ pub fn fuzz_result_format(format: QueryResultsFormat, data: &[u8]) { ) } } - QueryResultsReader::Boolean(value) => { + FromReadQueryResultsReader::Boolean(value) => { // We try to write again let mut serialized = Vec::new(); serializer @@ -53,8 +53,8 @@ pub fn fuzz_result_format(format: QueryResultsFormat, data: &[u8]) { .unwrap(); // And to parse again - if let QueryResultsReader::Boolean(roundtrip_value) = - parser.read_results(serialized.as_slice()).unwrap() + if let FromReadQueryResultsReader::Boolean(roundtrip_value) = + parser.parse_read(serialized.as_slice()).unwrap() { assert_eq!(roundtrip_value, value) } diff --git a/lib/sparesults/README.md b/lib/sparesults/README.md index f733d37b..0c61ded1 100644 --- a/lib/sparesults/README.md +++ b/lib/sparesults/README.md @@ -18,19 +18,19 @@ This crate is intended to be a building piece for SPARQL client and server imple Usage example converting a JSON result file into a TSV result file: ```rust -use sparesults::{QueryResultsFormat, QueryResultsParser, QueryResultsReader, QueryResultsSerializer}; +use sparesults::{QueryResultsFormat, QueryResultsParser, FromReadQueryResultsReader, QueryResultsSerializer}; use std::io::Result; fn convert_json_to_tsv(json_file: &[u8]) -> Result> { let json_parser = QueryResultsParser::from_format(QueryResultsFormat::Json); let tsv_serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Tsv); // We start to read the JSON file and see which kind of results it is - match json_parser.read_results(json_file)? { - QueryResultsReader::Boolean(value) => { + match json_parser.parse_read(json_file)? { + FromReadQueryResultsReader::Boolean(value) => { // it's a boolean result, we copy it in TSV to the output buffer tsv_serializer.serialize_boolean_to_write(Vec::new(), value) }, - QueryResultsReader::Solutions(solutions_reader) => { + FromReadQueryResultsReader::Solutions(solutions_reader) => { // it's a set of solutions, we create a writer and we write to it while reading in streaming from the JSON file let mut serialize_solutions_to_write = tsv_serializer.serialize_solutions_to_write(Vec::new(), solutions_reader.variables().to_vec())?; for solution in solutions_reader { diff --git a/lib/sparesults/src/lib.rs b/lib/sparesults/src/lib.rs index 21cdce12..95bcef93 100644 --- a/lib/sparesults/src/lib.rs +++ b/lib/sparesults/src/lib.rs @@ -15,6 +15,6 @@ mod xml; pub use crate::error::{ParseError, SyntaxError}; pub use crate::format::QueryResultsFormat; -pub use crate::parser::{QueryResultsParser, QueryResultsReader, SolutionsReader}; +pub use crate::parser::{FromReadQueryResultsReader, FromReadSolutionsReader, QueryResultsParser}; pub use crate::serializer::{QueryResultsSerializer, ToWriteSolutionsWriter}; pub use crate::solution::QuerySolution; diff --git a/lib/sparesults/src/parser.rs b/lib/sparesults/src/parser.rs index 32ffd62e..fd7a403d 100644 --- a/lib/sparesults/src/parser.rs +++ b/lib/sparesults/src/parser.rs @@ -17,16 +17,16 @@ use std::rc::Rc; /// /// Example in JSON (the API is the same for XML and TSV): /// ``` -/// use sparesults::{QueryResultsFormat, QueryResultsParser, QueryResultsReader}; +/// use sparesults::{QueryResultsFormat, QueryResultsParser, FromReadQueryResultsReader}; /// use oxrdf::{Literal, Variable}; /// /// let json_parser = QueryResultsParser::from_format(QueryResultsFormat::Json); /// // boolean -/// if let QueryResultsReader::Boolean(v) = json_parser.read_results(b"{\"boolean\":true}".as_slice())? { +/// if let FromReadQueryResultsReader::Boolean(v) = json_parser.parse_read(b"{\"boolean\":true}".as_slice())? { /// assert_eq!(v, true); /// } /// // solutions -/// if let QueryResultsReader::Solutions(solutions) = json_parser.read_results(b"{\"head\":{\"vars\":[\"foo\",\"bar\"]},\"results\":{\"bindings\":[{\"foo\":{\"type\":\"literal\",\"value\":\"test\"}}]}}".as_slice())? { +/// if let FromReadQueryResultsReader::Solutions(solutions) = json_parser.parse_read(b"{\"head\":{\"vars\":[\"foo\",\"bar\"]},\"results\":{\"bindings\":[{\"foo\":{\"type\":\"literal\",\"value\":\"test\"}}]}}".as_slice())? { /// assert_eq!(solutions.variables(), &[Variable::new_unchecked("foo"), Variable::new_unchecked("bar")]); /// for solution in solutions { /// assert_eq!(solution?.iter().collect::>(), vec![(&Variable::new_unchecked("foo"), &Literal::from("test").into())]); @@ -49,18 +49,18 @@ impl QueryResultsParser { /// /// Example in XML (the API is the same for JSON and TSV): /// ``` - /// use sparesults::{QueryResultsFormat, QueryResultsParser, QueryResultsReader}; + /// use sparesults::{QueryResultsFormat, QueryResultsParser, FromReadQueryResultsReader}; /// use oxrdf::{Literal, Variable}; /// /// let json_parser = QueryResultsParser::from_format(QueryResultsFormat::Xml); /// /// // boolean - /// if let QueryResultsReader::Boolean(v) = json_parser.read_results(b"true".as_slice())? { + /// if let FromReadQueryResultsReader::Boolean(v) = json_parser.parse_read(b"true".as_slice())? { /// assert_eq!(v, true); /// } /// /// // solutions - /// if let QueryResultsReader::Solutions(solutions) = json_parser.read_results(b"test".as_slice())? { + /// if let FromReadQueryResultsReader::Solutions(solutions) = json_parser.parse_read(b"test".as_slice())? { /// assert_eq!(solutions.variables(), &[Variable::new_unchecked("foo"), Variable::new_unchecked("bar")]); /// for solution in solutions { /// assert_eq!(solution?.iter().collect::>(), vec![(&Variable::new_unchecked("foo"), &Literal::from("test").into())]); @@ -68,61 +68,72 @@ impl QueryResultsParser { /// } /// # Result::<(),sparesults::ParseError>::Ok(()) /// ``` - pub fn read_results(&self, reader: R) -> Result, ParseError> { + pub fn parse_read( + &self, + reader: R, + ) -> Result, ParseError> { Ok(match self.format { QueryResultsFormat::Xml => match XmlQueryResultsReader::read(reader)? { - XmlQueryResultsReader::Boolean(r) => QueryResultsReader::Boolean(r), + XmlQueryResultsReader::Boolean(r) => FromReadQueryResultsReader::Boolean(r), XmlQueryResultsReader::Solutions { solutions, variables, - } => QueryResultsReader::Solutions(SolutionsReader { + } => FromReadQueryResultsReader::Solutions(FromReadSolutionsReader { variables: Rc::new(variables), solutions: SolutionsReaderKind::Xml(solutions), }), }, QueryResultsFormat::Json => match JsonQueryResultsReader::read(reader)? { - JsonQueryResultsReader::Boolean(r) => QueryResultsReader::Boolean(r), + JsonQueryResultsReader::Boolean(r) => FromReadQueryResultsReader::Boolean(r), JsonQueryResultsReader::Solutions { solutions, variables, - } => QueryResultsReader::Solutions(SolutionsReader { + } => FromReadQueryResultsReader::Solutions(FromReadSolutionsReader { variables: Rc::new(variables), solutions: SolutionsReaderKind::Json(solutions), }), }, QueryResultsFormat::Csv => return Err(SyntaxError::msg("CSV SPARQL results syntax is lossy and can't be parsed to a proper RDF representation").into()), QueryResultsFormat::Tsv => match TsvQueryResultsReader::read(reader)? { - TsvQueryResultsReader::Boolean(r) => QueryResultsReader::Boolean(r), + TsvQueryResultsReader::Boolean(r) => FromReadQueryResultsReader::Boolean(r), TsvQueryResultsReader::Solutions { solutions, variables, - } => QueryResultsReader::Solutions(SolutionsReader { + } => FromReadQueryResultsReader::Solutions(FromReadSolutionsReader { variables: Rc::new(variables), solutions: SolutionsReaderKind::Tsv(solutions), }), }, }) } + + #[deprecated(note = "Use parse_read")] + pub fn read_results( + &self, + reader: R, + ) -> Result, ParseError> { + self.parse_read(reader) + } } /// The reader for a given read of a results file. /// -/// It is either a read boolean ([`bool`]) or a streaming reader of a set of solutions ([`SolutionsReader`]). +/// It is either a read boolean ([`bool`]) or a streaming reader of a set of solutions ([`FromReadSolutionsReader`]). /// /// Example in TSV (the API is the same for JSON and XML): /// ``` -/// use sparesults::{QueryResultsFormat, QueryResultsParser, QueryResultsReader}; +/// use sparesults::{QueryResultsFormat, QueryResultsParser, FromReadQueryResultsReader}; /// use oxrdf::{Literal, Variable}; /// /// let json_parser = QueryResultsParser::from_format(QueryResultsFormat::Tsv); /// /// // boolean -/// if let QueryResultsReader::Boolean(v) = json_parser.read_results(b"true".as_slice())? { +/// if let FromReadQueryResultsReader::Boolean(v) = json_parser.parse_read(b"true".as_slice())? { /// assert_eq!(v, true); /// } /// /// // solutions -/// if let QueryResultsReader::Solutions(solutions) = json_parser.read_results(b"?foo\t?bar\n\"test\"\t".as_slice())? { +/// if let FromReadQueryResultsReader::Solutions(solutions) = json_parser.parse_read(b"?foo\t?bar\n\"test\"\t".as_slice())? { /// assert_eq!(solutions.variables(), &[Variable::new_unchecked("foo"), Variable::new_unchecked("bar")]); /// for solution in solutions { /// assert_eq!(solution?.iter().collect::>(), vec![(&Variable::new_unchecked("foo"), &Literal::from("test").into())]); @@ -130,8 +141,8 @@ impl QueryResultsParser { /// } /// # Result::<(),sparesults::ParseError>::Ok(()) /// ``` -pub enum QueryResultsReader { - Solutions(SolutionsReader), +pub enum FromReadQueryResultsReader { + Solutions(FromReadSolutionsReader), Boolean(bool), } @@ -141,11 +152,11 @@ pub enum QueryResultsReader { /// /// Example in JSON (the API is the same for XML and TSV): /// ``` -/// use sparesults::{QueryResultsFormat, QueryResultsParser, QueryResultsReader}; +/// use sparesults::{QueryResultsFormat, QueryResultsParser, FromReadQueryResultsReader}; /// use oxrdf::{Literal, Variable}; /// /// let json_parser = QueryResultsParser::from_format(QueryResultsFormat::Json); -/// if let QueryResultsReader::Solutions(solutions) = json_parser.read_results(b"{\"head\":{\"vars\":[\"foo\",\"bar\"]},\"results\":{\"bindings\":[{\"foo\":{\"type\":\"literal\",\"value\":\"test\"}}]}}".as_slice())? { +/// if let FromReadQueryResultsReader::Solutions(solutions) = json_parser.parse_read(b"{\"head\":{\"vars\":[\"foo\",\"bar\"]},\"results\":{\"bindings\":[{\"foo\":{\"type\":\"literal\",\"value\":\"test\"}}]}}".as_slice())? { /// assert_eq!(solutions.variables(), &[Variable::new_unchecked("foo"), Variable::new_unchecked("bar")]); /// for solution in solutions { /// assert_eq!(solution?.iter().collect::>(), vec![(&Variable::new_unchecked("foo"), &Literal::from("test").into())]); @@ -154,7 +165,7 @@ pub enum QueryResultsReader { /// # Result::<(),sparesults::ParseError>::Ok(()) /// ``` #[allow(clippy::rc_buffer)] -pub struct SolutionsReader { +pub struct FromReadSolutionsReader { variables: Rc>, solutions: SolutionsReaderKind, } @@ -165,16 +176,16 @@ enum SolutionsReaderKind { Tsv(TsvSolutionsReader), } -impl SolutionsReader { +impl FromReadSolutionsReader { /// Ordered list of the declared variables at the beginning of the results. /// /// Example in TSV (the API is the same for JSON and XML): /// ``` - /// use sparesults::{QueryResultsFormat, QueryResultsParser, QueryResultsReader}; + /// use sparesults::{QueryResultsFormat, QueryResultsParser, FromReadQueryResultsReader}; /// use oxrdf::Variable; /// /// let json_parser = QueryResultsParser::from_format(QueryResultsFormat::Tsv); - /// if let QueryResultsReader::Solutions(solutions) = json_parser.read_results(b"?foo\t?bar\n\"ex1\"\t\"ex2\"".as_slice())? { + /// if let FromReadQueryResultsReader::Solutions(solutions) = json_parser.parse_read(b"?foo\t?bar\n\"ex1\"\t\"ex2\"".as_slice())? { /// assert_eq!(solutions.variables(), &[Variable::new_unchecked("foo"), Variable::new_unchecked("bar")]); /// } /// # Result::<(),sparesults::ParseError>::Ok(()) @@ -185,7 +196,7 @@ impl SolutionsReader { } } -impl Iterator for SolutionsReader { +impl Iterator for FromReadSolutionsReader { type Item = Result; fn next(&mut self) -> Option> { diff --git a/lib/src/sparql/model.rs b/lib/src/sparql/model.rs index d02f7ea2..8ef06ecb 100644 --- a/lib/src/sparql/model.rs +++ b/lib/src/sparql/model.rs @@ -2,8 +2,8 @@ use crate::io::{RdfFormat, RdfSerializer}; use crate::model::*; use crate::sparql::error::EvaluationError; use crate::sparql::results::{ - ParseError, QueryResultsFormat, QueryResultsParser, QueryResultsReader, QueryResultsSerializer, - SolutionsReader, + FromReadQueryResultsReader, FromReadSolutionsReader, ParseError, QueryResultsFormat, + QueryResultsParser, QueryResultsSerializer, }; use oxrdf::{Variable, VariableRef}; pub use sparesults::QuerySolution; @@ -27,7 +27,7 @@ impl QueryResults { format: QueryResultsFormat, ) -> Result { Ok(QueryResultsParser::from_format(format) - .read_results(reader)? + .parse_read(reader)? .into()) } @@ -150,11 +150,11 @@ impl From for QueryResults { } } -impl From> for QueryResults { - fn from(reader: QueryResultsReader) -> Self { +impl From> for QueryResults { + fn from(reader: FromReadQueryResultsReader) -> Self { match reader { - QueryResultsReader::Solutions(s) => Self::Solutions(s.into()), - QueryResultsReader::Boolean(v) => Self::Boolean(v), + FromReadQueryResultsReader::Solutions(s) => Self::Solutions(s.into()), + FromReadQueryResultsReader::Boolean(v) => Self::Boolean(v), } } } @@ -211,8 +211,8 @@ impl QuerySolutionIter { } } -impl From> for QuerySolutionIter { - fn from(reader: SolutionsReader) -> Self { +impl From> for QuerySolutionIter { + fn from(reader: FromReadSolutionsReader) -> Self { Self { variables: Rc::new(reader.variables().to_vec()), iter: Box::new(reader.map(|t| t.map_err(EvaluationError::from))), diff --git a/lib/src/sparql/results.rs b/lib/src/sparql/results.rs index 511461cc..0716752b 100644 --- a/lib/src/sparql/results.rs +++ b/lib/src/sparql/results.rs @@ -5,19 +5,19 @@ //! Usage example converting a JSON result file into a TSV result file: //! //! ``` -//! use oxigraph::sparql::results::{QueryResultsFormat, QueryResultsParser, QueryResultsReader, QueryResultsSerializer}; +//! use oxigraph::sparql::results::{QueryResultsFormat, QueryResultsParser, FromReadQueryResultsReader, QueryResultsSerializer}; //! use std::io::Result; //! //! fn convert_json_to_tsv(json_file: &[u8]) -> Result> { //! let json_parser = QueryResultsParser::from_format(QueryResultsFormat::Json); //! let tsv_serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Tsv); //! // We start to read the JSON file and see which kind of results it is -//! match json_parser.read_results(json_file)? { -//! QueryResultsReader::Boolean(value) => { +//! match json_parser.parse_read(json_file)? { +//! FromReadQueryResultsReader::Boolean(value) => { //! // it's a boolean result, we copy it in TSV to the output buffer //! tsv_serializer.serialize_boolean_to_write(Vec::new(), value) -//! }, -//! QueryResultsReader::Solutions(solutions_reader) => { +//! } +//! FromReadQueryResultsReader::Solutions(solutions_reader) => { //! // it's a set of solutions, we create a writer and we write to it while reading in streaming from the JSON file //! let mut serialize_solutions_to_write = tsv_serializer.serialize_solutions_to_write(Vec::new(), solutions_reader.variables().to_vec())?; //! for solution in solutions_reader { @@ -42,6 +42,6 @@ //! ``` pub use sparesults::{ - ParseError, QueryResultsFormat, QueryResultsParser, QueryResultsReader, QueryResultsSerializer, - SolutionsReader, SyntaxError, + FromReadQueryResultsReader, FromReadSolutionsReader, ParseError, QueryResultsFormat, + QueryResultsParser, QueryResultsSerializer, SyntaxError, }; diff --git a/python/src/sparql.rs b/python/src/sparql.rs index a2964e0f..1316eecf 100644 --- a/python/src/sparql.rs +++ b/python/src/sparql.rs @@ -4,7 +4,8 @@ use crate::store::map_storage_error; use oxigraph::io::RdfSerializer; use oxigraph::model::Term; use oxigraph::sparql::results::{ - ParseError, QueryResultsParser, QueryResultsReader, QueryResultsSerializer, SolutionsReader, + FromReadQueryResultsReader, FromReadSolutionsReader, ParseError, QueryResultsParser, + QueryResultsSerializer, }; use oxigraph::sparql::{ EvaluationError, Query, QueryResults, QuerySolution, QuerySolutionIter, QueryTripleIter, @@ -189,7 +190,7 @@ pub struct PyQuerySolutions { } enum PyQuerySolutionsVariant { Query(QuerySolutionIter), - Reader(SolutionsReader>), + Reader(FromReadSolutionsReader>), } #[pymethods] @@ -496,14 +497,14 @@ pub fn parse_query_results( PyReadable::from_data(input) }; let results = QueryResultsParser::from_format(format) - .read_results(BufReader::new(input)) + .parse_read(BufReader::new(input)) .map_err(map_query_results_parse_error)?; Ok(match results { - QueryResultsReader::Solutions(inner) => PyQuerySolutions { + FromReadQueryResultsReader::Solutions(inner) => PyQuerySolutions { inner: PyQuerySolutionsVariant::Reader(inner), } .into_py(py), - QueryResultsReader::Boolean(inner) => PyQueryBoolean { inner }.into_py(py), + FromReadQueryResultsReader::Boolean(inner) => PyQueryBoolean { inner }.into_py(py), }) }