From 6a21cb0625083a9785958d318d86f48db8cd5457 Mon Sep 17 00:00:00 2001 From: Tpt Date: Sat, 16 Sep 2023 15:15:16 +0200 Subject: [PATCH] Makes sparesults formatter API closer to oxrdfio --- cli/src/main.rs | 19 ++++---- fuzz/src/result_format.rs | 4 +- lib/sparesults/README.md | 8 +-- lib/sparesults/src/lib.rs | 2 +- lib/sparesults/src/serializer.rs | 84 ++++++++++++++++++++------------ lib/src/sparql/model.rs | 9 ++-- lib/src/sparql/results.rs | 8 +-- python/src/sparql.rs | 4 +- 8 files changed, 81 insertions(+), 57 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 5095076d..54f79299 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -555,7 +555,7 @@ pub fn main() -> anyhow::Result<()> { }; if let Some(results_file) = results_file { let mut writer = QueryResultsSerializer::from_format(format) - .solutions_writer( + .serialize_solutions_to_write( BufWriter::new(File::create(results_file)?), solutions.variables().to_vec(), )?; @@ -565,7 +565,7 @@ pub fn main() -> anyhow::Result<()> { close_file_writer(writer.finish()?)?; } else { let mut writer = QueryResultsSerializer::from_format(format) - .solutions_writer( + .serialize_solutions_to_write( stdout().lock(), solutions.variables().to_vec(), )?; @@ -595,14 +595,15 @@ pub fn main() -> anyhow::Result<()> { }; if let Some(results_file) = results_file { close_file_writer( - QueryResultsSerializer::from_format(format).write_boolean_result( - BufWriter::new(File::create(results_file)?), - result, - )?, + QueryResultsSerializer::from_format(format) + .serialize_boolean_to_write( + BufWriter::new(File::create(results_file)?), + result, + )?, )?; } else { QueryResultsSerializer::from_format(format) - .write_boolean_result(stdout().lock(), result)? + .serialize_boolean_to_write(stdout().lock(), result)? .flush()?; } } @@ -1318,7 +1319,7 @@ fn evaluate_sparql_query( move |w| { Ok(( QueryResultsSerializer::from_format(format) - .solutions_writer(w, solutions.variables().to_vec())?, + .serialize_solutions_to_write(w, solutions.variables().to_vec())?, solutions, )) }, @@ -1338,7 +1339,7 @@ fn evaluate_sparql_query( let format = query_results_content_negotiation(request)?; let mut body = Vec::new(); QueryResultsSerializer::from_format(format) - .write_boolean_result(&mut body, result) + .serialize_boolean_to_write(&mut body, result) .map_err(internal_server_error)?; Ok(Response::builder(Status::OK) .with_header(HeaderName::CONTENT_TYPE, format.media_type()) diff --git a/fuzz/src/result_format.rs b/fuzz/src/result_format.rs index cc00f9be..139d3c9a 100644 --- a/fuzz/src/result_format.rs +++ b/fuzz/src/result_format.rs @@ -18,7 +18,7 @@ pub fn fuzz_result_format(format: QueryResultsFormat, data: &[u8]) { // We try to write again let mut writer = serializer - .solutions_writer( + .serialize_solutions_to_write( Vec::new(), solutions .get(0) @@ -49,7 +49,7 @@ pub fn fuzz_result_format(format: QueryResultsFormat, data: &[u8]) { // We try to write again let mut serialized = Vec::new(); serializer - .write_boolean_result(&mut serialized, value) + .serialize_boolean_to_write(&mut serialized, value) .unwrap(); // And to parse again diff --git a/lib/sparesults/README.md b/lib/sparesults/README.md index 7e719065..f733d37b 100644 --- a/lib/sparesults/README.md +++ b/lib/sparesults/README.md @@ -28,15 +28,15 @@ fn convert_json_to_tsv(json_file: &[u8]) -> Result> { match json_parser.read_results(json_file)? { QueryResultsReader::Boolean(value) => { // it's a boolean result, we copy it in TSV to the output buffer - tsv_serializer.write_boolean_result(Vec::new(), value) + tsv_serializer.serialize_boolean_to_write(Vec::new(), value) }, QueryResultsReader::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 solutions_writer = tsv_serializer.solutions_writer(Vec::new(), solutions_reader.variables().to_vec())?; + let mut serialize_solutions_to_write = tsv_serializer.serialize_solutions_to_write(Vec::new(), solutions_reader.variables().to_vec())?; for solution in solutions_reader { - solutions_writer.write(&solution?)?; + serialize_solutions_to_write.write(&solution?)?; } - solutions_writer.finish() + serialize_solutions_to_write.finish() } } } diff --git a/lib/sparesults/src/lib.rs b/lib/sparesults/src/lib.rs index fc2aee67..21cdce12 100644 --- a/lib/sparesults/src/lib.rs +++ b/lib/sparesults/src/lib.rs @@ -16,5 +16,5 @@ mod xml; pub use crate::error::{ParseError, SyntaxError}; pub use crate::format::QueryResultsFormat; pub use crate::parser::{QueryResultsParser, QueryResultsReader, SolutionsReader}; -pub use crate::serializer::{QueryResultsSerializer, SolutionsWriter}; +pub use crate::serializer::{QueryResultsSerializer, ToWriteSolutionsWriter}; pub use crate::solution::QuerySolution; diff --git a/lib/sparesults/src/serializer.rs b/lib/sparesults/src/serializer.rs index f804a295..2ce77f4d 100644 --- a/lib/sparesults/src/serializer.rs +++ b/lib/sparesults/src/serializer.rs @@ -25,12 +25,12 @@ use std::io::{self, Write}; /// /// // boolean /// let mut buffer = Vec::new(); -/// json_serializer.write_boolean_result(&mut buffer, true)?; +/// json_serializer.serialize_boolean_to_write(&mut buffer, true)?; /// assert_eq!(buffer, b"{\"head\":{},\"boolean\":true}"); /// /// // solutions /// let mut buffer = Vec::new(); -/// let mut writer = json_serializer.solutions_writer(&mut buffer, vec![Variable::new_unchecked("foo"), Variable::new_unchecked("bar")])?; +/// let mut writer = json_serializer.serialize_solutions_to_write(&mut buffer, vec![Variable::new_unchecked("foo"), Variable::new_unchecked("bar")])?; /// writer.write(once((VariableRef::new_unchecked("foo"), LiteralRef::from("test"))))?; /// writer.finish()?; /// assert_eq!(buffer, b"{\"head\":{\"vars\":[\"foo\",\"bar\"]},\"results\":{\"bindings\":[{\"foo\":{\"type\":\"literal\",\"value\":\"test\"}}]}}"); @@ -55,21 +55,30 @@ impl QueryResultsSerializer { /// /// let json_serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Xml); /// let mut buffer = Vec::new(); - /// json_serializer.write_boolean_result(&mut buffer, true)?; + /// json_serializer.serialize_boolean_to_write(&mut buffer, true)?; /// assert_eq!(buffer, b"true"); /// # std::io::Result::Ok(()) /// ``` - pub fn write_boolean_result(&self, writer: W, value: bool) -> io::Result { + pub fn serialize_boolean_to_write(&self, write: W, value: bool) -> io::Result { match self.format { - QueryResultsFormat::Xml => write_boolean_xml_result(writer, value), - QueryResultsFormat::Json => write_boolean_json_result(writer, value), - QueryResultsFormat::Csv => write_boolean_csv_result(writer, value), - QueryResultsFormat::Tsv => write_boolean_tsv_result(writer, value), + QueryResultsFormat::Xml => write_boolean_xml_result(write, value), + QueryResultsFormat::Json => write_boolean_json_result(write, value), + QueryResultsFormat::Csv => write_boolean_csv_result(write, value), + QueryResultsFormat::Tsv => write_boolean_tsv_result(write, value), } } + #[deprecated(note = "Use serialize_boolean_to_write")] + pub fn write_boolean_result(&self, writer: W, value: bool) -> io::Result { + self.serialize_boolean_to_write(writer, value) + } + /// Returns a `SolutionsWriter` allowing writing query solutions into the given [`Write`] implementation. /// + ///
Do not forget to run the [`finish`](ToWriteSolutionsWriter::finish()) method to properly write the last bytes of the file.
+ /// + ///
This writer does unbuffered writes. You might want to use [`BufWriter`](io::BufWriter) to avoid that.
+ /// /// Example in XML (the API is the same for JSON and TSV): /// ``` /// use sparesults::{QueryResultsFormat, QueryResultsSerializer}; @@ -78,40 +87,51 @@ impl QueryResultsSerializer { /// /// let json_serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Xml); /// let mut buffer = Vec::new(); - /// let mut writer = json_serializer.solutions_writer(&mut buffer, vec![Variable::new_unchecked("foo"), Variable::new_unchecked("bar")])?; + /// let mut writer = json_serializer.serialize_solutions_to_write(&mut buffer, vec![Variable::new_unchecked("foo"), Variable::new_unchecked("bar")])?; /// writer.write(once((VariableRef::new_unchecked("foo"), LiteralRef::from("test"))))?; /// writer.finish()?; /// assert_eq!(buffer, b"test"); /// # std::io::Result::Ok(()) /// ``` - pub fn solutions_writer( + pub fn serialize_solutions_to_write( &self, - writer: W, + write: W, variables: Vec, - ) -> io::Result> { - Ok(SolutionsWriter { + ) -> io::Result> { + Ok(ToWriteSolutionsWriter { formatter: match self.format { QueryResultsFormat::Xml => { - SolutionsWriterKind::Xml(XmlSolutionsWriter::start(writer, &variables)?) + ToWriteSolutionsWriterKind::Xml(XmlSolutionsWriter::start(write, &variables)?) } QueryResultsFormat::Json => { - SolutionsWriterKind::Json(JsonSolutionsWriter::start(writer, &variables)?) + ToWriteSolutionsWriterKind::Json(JsonSolutionsWriter::start(write, &variables)?) } QueryResultsFormat::Csv => { - SolutionsWriterKind::Csv(CsvSolutionsWriter::start(writer, variables)?) + ToWriteSolutionsWriterKind::Csv(CsvSolutionsWriter::start(write, variables)?) } QueryResultsFormat::Tsv => { - SolutionsWriterKind::Tsv(TsvSolutionsWriter::start(writer, variables)?) + ToWriteSolutionsWriterKind::Tsv(TsvSolutionsWriter::start(write, variables)?) } }, }) } + + #[deprecated(note = "Use serialize_solutions_to_write")] + pub fn solutions_writer( + &self, + writer: W, + variables: Vec, + ) -> io::Result> { + self.serialize_solutions_to_write(writer, variables) + } } /// Allows writing query results. /// Could be built using a [`QueryResultsSerializer`]. /// -///
Do not forget to run the [`finish`](SolutionsWriter::finish()) method to properly write the last bytes of the file.
+///
Do not forget to run the [`finish`](ToWriteSolutionsWriter::finish()) method to properly write the last bytes of the file.
+/// +///
This writer does unbuffered writes. You might want to use [`BufWriter`](io::BufWriter) to avoid that.
/// /// Example in TSV (the API is the same for JSON and XML): /// ``` @@ -121,25 +141,25 @@ impl QueryResultsSerializer { /// /// let json_serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Tsv); /// let mut buffer = Vec::new(); -/// let mut writer = json_serializer.solutions_writer(&mut buffer, vec![Variable::new_unchecked("foo"), Variable::new_unchecked("bar")])?; +/// let mut writer = json_serializer.serialize_solutions_to_write(&mut buffer, vec![Variable::new_unchecked("foo"), Variable::new_unchecked("bar")])?; /// writer.write(once((VariableRef::new_unchecked("foo"), LiteralRef::from("test"))))?; /// writer.finish()?; /// assert_eq!(buffer, b"?foo\t?bar\n\"test\"\t\n"); /// # std::io::Result::Ok(()) /// ``` #[must_use] -pub struct SolutionsWriter { - formatter: SolutionsWriterKind, +pub struct ToWriteSolutionsWriter { + formatter: ToWriteSolutionsWriterKind, } -enum SolutionsWriterKind { +enum ToWriteSolutionsWriterKind { Xml(XmlSolutionsWriter), Json(JsonSolutionsWriter), Csv(CsvSolutionsWriter), Tsv(TsvSolutionsWriter), } -impl SolutionsWriter { +impl ToWriteSolutionsWriter { /// Writes a solution. /// /// Example in JSON (the API is the same for XML and TSV): @@ -150,7 +170,7 @@ impl SolutionsWriter { /// /// let json_serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Json); /// let mut buffer = Vec::new(); - /// let mut writer = json_serializer.solutions_writer(&mut buffer, vec![Variable::new_unchecked("foo"), Variable::new_unchecked("bar")])?; + /// let mut writer = json_serializer.serialize_solutions_to_write(&mut buffer, vec![Variable::new_unchecked("foo"), Variable::new_unchecked("bar")])?; /// writer.write(once((VariableRef::new_unchecked("foo"), LiteralRef::from("test"))))?; /// writer.write(&QuerySolution::from((vec![Variable::new_unchecked("bar")], vec![Some(Literal::from("test").into())])))?; /// writer.finish()?; @@ -163,20 +183,20 @@ impl SolutionsWriter { ) -> io::Result<()> { let solution = solution.into_iter().map(|(v, s)| (v.into(), s.into())); match &mut self.formatter { - SolutionsWriterKind::Xml(writer) => writer.write(solution), - SolutionsWriterKind::Json(writer) => writer.write(solution), - SolutionsWriterKind::Csv(writer) => writer.write(solution), - SolutionsWriterKind::Tsv(writer) => writer.write(solution), + ToWriteSolutionsWriterKind::Xml(writer) => writer.write(solution), + ToWriteSolutionsWriterKind::Json(writer) => writer.write(solution), + ToWriteSolutionsWriterKind::Csv(writer) => writer.write(solution), + ToWriteSolutionsWriterKind::Tsv(writer) => writer.write(solution), } } /// Writes the last bytes of the file. pub fn finish(self) -> io::Result { match self.formatter { - SolutionsWriterKind::Xml(write) => write.finish(), - SolutionsWriterKind::Json(write) => write.finish(), - SolutionsWriterKind::Csv(write) => write.finish(), - SolutionsWriterKind::Tsv(write) => write.finish(), + ToWriteSolutionsWriterKind::Xml(write) => write.finish(), + ToWriteSolutionsWriterKind::Json(write) => write.finish(), + ToWriteSolutionsWriterKind::Csv(write) => write.finish(), + ToWriteSolutionsWriterKind::Tsv(write) => write.finish(), } } } diff --git a/lib/src/sparql/model.rs b/lib/src/sparql/model.rs index 71a25ea9..d02f7ea2 100644 --- a/lib/src/sparql/model.rs +++ b/lib/src/sparql/model.rs @@ -58,12 +58,12 @@ impl QueryResults { match self { Self::Boolean(value) => { serializer - .write_boolean_result(writer, value) + .serialize_boolean_to_write(writer, value) .map_err(EvaluationError::ResultsSerialization)?; } Self::Solutions(solutions) => { let mut writer = serializer - .solutions_writer(writer, solutions.variables().to_vec()) + .serialize_solutions_to_write(writer, solutions.variables().to_vec()) .map_err(EvaluationError::ResultsSerialization)?; for solution in solutions { writer @@ -79,7 +79,10 @@ impl QueryResults { let p = VariableRef::new_unchecked("predicate"); let o = VariableRef::new_unchecked("object"); let mut writer = serializer - .solutions_writer(writer, vec![s.into_owned(), p.into_owned(), o.into_owned()]) + .serialize_solutions_to_write( + writer, + vec![s.into_owned(), p.into_owned(), o.into_owned()], + ) .map_err(EvaluationError::ResultsSerialization)?; for triple in triples { let triple = triple?; diff --git a/lib/src/sparql/results.rs b/lib/src/sparql/results.rs index 26fa287a..511461cc 100644 --- a/lib/src/sparql/results.rs +++ b/lib/src/sparql/results.rs @@ -15,15 +15,15 @@ //! match json_parser.read_results(json_file)? { //! QueryResultsReader::Boolean(value) => { //! // it's a boolean result, we copy it in TSV to the output buffer -//! tsv_serializer.write_boolean_result(Vec::new(), value) +//! tsv_serializer.serialize_boolean_to_write(Vec::new(), value) //! }, //! QueryResultsReader::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 solutions_writer = tsv_serializer.solutions_writer(Vec::new(), solutions_reader.variables().to_vec())?; +//! let mut serialize_solutions_to_write = tsv_serializer.serialize_solutions_to_write(Vec::new(), solutions_reader.variables().to_vec())?; //! for solution in solutions_reader { -//! solutions_writer.write(&solution?)?; +//! serialize_solutions_to_write.write(&solution?)?; //! } -//! solutions_writer.finish() +//! serialize_solutions_to_write.finish() //! } //! } //! } diff --git a/python/src/sparql.rs b/python/src/sparql.rs index ef544e2d..a2964e0f 100644 --- a/python/src/sparql.rs +++ b/python/src/sparql.rs @@ -247,7 +247,7 @@ impl PyQuerySolutions { PyWritable::do_write( |output, format| { let mut writer = QueryResultsSerializer::from_format(format) - .solutions_writer( + .serialize_solutions_to_write( output, match &self.inner { PyQuerySolutionsVariant::Query(inner) => inner.variables().to_vec(), @@ -349,7 +349,7 @@ impl PyQueryBoolean { |output, format| { py.allow_threads(|| { QueryResultsSerializer::from_format(format) - .write_boolean_result(output, self.inner) + .serialize_boolean_to_write(output, self.inner) .map_err(map_io_err) }) },