1use crate::error::{QueryResultsParseError, QueryResultsSyntaxError};
4use json_event_parser::{JsonEvent, ReaderJsonParser, SliceJsonParser, WriterJsonSerializer};
5#[cfg(feature = "async-tokio")]
6use json_event_parser::{TokioAsyncReaderJsonParser, TokioAsyncWriterJsonSerializer};
7use oxrdf::vocab::rdf;
8use oxrdf::*;
9use std::collections::HashMap;
10use std::io::{self, Read, Write};
11use std::mem::take;
12#[cfg(feature = "async-tokio")]
13use tokio::io::{AsyncRead, AsyncWrite};
14
15pub fn write_boolean_json_result<W: Write>(writer: W, value: bool) -> io::Result<W> {
16 let mut serializer = WriterJsonSerializer::new(writer);
17 for event in inner_write_boolean_json_result(value) {
18 serializer.serialize_event(event)?;
19 }
20 serializer.finish()
21}
22
23#[cfg(feature = "async-tokio")]
24pub async fn tokio_async_write_boolean_json_result<W: AsyncWrite + Unpin>(
25 writer: W,
26 value: bool,
27) -> io::Result<W> {
28 let mut serializer = TokioAsyncWriterJsonSerializer::new(writer);
29 for event in inner_write_boolean_json_result(value) {
30 serializer.serialize_event(event).await?;
31 }
32 serializer.finish()
33}
34
35fn inner_write_boolean_json_result(value: bool) -> [JsonEvent<'static>; 7] {
36 [
37 JsonEvent::StartObject,
38 JsonEvent::ObjectKey("head".into()),
39 JsonEvent::StartObject,
40 JsonEvent::EndObject,
41 JsonEvent::ObjectKey("boolean".into()),
42 JsonEvent::Boolean(value),
43 JsonEvent::EndObject,
44 ]
45}
46
47pub struct WriterJsonSolutionsSerializer<W: Write> {
48 inner: InnerJsonSolutionsSerializer,
49 serializer: WriterJsonSerializer<W>,
50}
51
52impl<W: Write> WriterJsonSolutionsSerializer<W> {
53 pub fn start(writer: W, variables: &[Variable]) -> io::Result<Self> {
54 let mut serializer = WriterJsonSerializer::new(writer);
55 let mut buffer = Vec::with_capacity(48);
56 let inner = InnerJsonSolutionsSerializer::start(&mut buffer, variables);
57 Self::do_write(&mut serializer, buffer)?;
58 Ok(Self { inner, serializer })
59 }
60
61 pub fn serialize<'a>(
62 &mut self,
63 solution: impl IntoIterator<Item = (VariableRef<'a>, TermRef<'a>)>,
64 ) -> io::Result<()> {
65 let mut buffer = Vec::with_capacity(48);
66 self.inner.write(&mut buffer, solution);
67 Self::do_write(&mut self.serializer, buffer)
68 }
69
70 pub fn finish(mut self) -> io::Result<W> {
71 let mut buffer = Vec::with_capacity(4);
72 self.inner.finish(&mut buffer);
73 Self::do_write(&mut self.serializer, buffer)?;
74 self.serializer.finish()
75 }
76
77 fn do_write(
78 serializer: &mut WriterJsonSerializer<W>,
79 output: Vec<JsonEvent<'_>>,
80 ) -> io::Result<()> {
81 for event in output {
82 serializer.serialize_event(event)?;
83 }
84 Ok(())
85 }
86}
87
88#[cfg(feature = "async-tokio")]
89pub struct TokioAsyncWriterJsonSolutionsSerializer<W: AsyncWrite + Unpin> {
90 inner: InnerJsonSolutionsSerializer,
91 serializer: TokioAsyncWriterJsonSerializer<W>,
92}
93
94#[cfg(feature = "async-tokio")]
95impl<W: AsyncWrite + Unpin> TokioAsyncWriterJsonSolutionsSerializer<W> {
96 pub async fn start(writer: W, variables: &[Variable]) -> io::Result<Self> {
97 let mut serializer = TokioAsyncWriterJsonSerializer::new(writer);
98 let mut buffer = Vec::with_capacity(48);
99 let inner = InnerJsonSolutionsSerializer::start(&mut buffer, variables);
100 Self::do_write(&mut serializer, buffer).await?;
101 Ok(Self { inner, serializer })
102 }
103
104 pub async fn serialize<'a>(
105 &mut self,
106 solution: impl IntoIterator<Item = (VariableRef<'a>, TermRef<'a>)>,
107 ) -> io::Result<()> {
108 let mut buffer = Vec::with_capacity(48);
109 self.inner.write(&mut buffer, solution);
110 Self::do_write(&mut self.serializer, buffer).await
111 }
112
113 pub async fn finish(mut self) -> io::Result<W> {
114 let mut buffer = Vec::with_capacity(4);
115 self.inner.finish(&mut buffer);
116 Self::do_write(&mut self.serializer, buffer).await?;
117 self.serializer.finish()
118 }
119
120 async fn do_write(
121 serializer: &mut TokioAsyncWriterJsonSerializer<W>,
122 output: Vec<JsonEvent<'_>>,
123 ) -> io::Result<()> {
124 for event in output {
125 serializer.serialize_event(event).await?;
126 }
127 Ok(())
128 }
129}
130
131struct InnerJsonSolutionsSerializer;
132
133impl InnerJsonSolutionsSerializer {
134 fn start<'a>(output: &mut Vec<JsonEvent<'a>>, variables: &'a [Variable]) -> Self {
135 output.push(JsonEvent::StartObject);
136 output.push(JsonEvent::ObjectKey("head".into()));
137 output.push(JsonEvent::StartObject);
138 output.push(JsonEvent::ObjectKey("vars".into()));
139 output.push(JsonEvent::StartArray);
140 for variable in variables {
141 output.push(JsonEvent::String(variable.as_str().into()));
142 }
143 output.push(JsonEvent::EndArray);
144 output.push(JsonEvent::EndObject);
145 output.push(JsonEvent::ObjectKey("results".into()));
146 output.push(JsonEvent::StartObject);
147 output.push(JsonEvent::ObjectKey("bindings".into()));
148 output.push(JsonEvent::StartArray);
149 Self {}
150 }
151
152 #[allow(clippy::unused_self)]
153 fn write<'a>(
154 &self,
155 output: &mut Vec<JsonEvent<'a>>,
156 solution: impl IntoIterator<Item = (VariableRef<'a>, TermRef<'a>)>,
157 ) {
158 output.push(JsonEvent::StartObject);
159 for (variable, value) in solution {
160 output.push(JsonEvent::ObjectKey(variable.as_str().into()));
161 write_json_term(output, value);
162 }
163 output.push(JsonEvent::EndObject);
164 }
165
166 #[allow(clippy::unused_self)]
167 fn finish(self, output: &mut Vec<JsonEvent<'_>>) {
168 output.push(JsonEvent::EndArray);
169 output.push(JsonEvent::EndObject);
170 output.push(JsonEvent::EndObject);
171 }
172}
173
174fn write_json_term<'a>(output: &mut Vec<JsonEvent<'a>>, term: TermRef<'a>) {
175 match term {
176 TermRef::NamedNode(uri) => {
177 output.push(JsonEvent::StartObject);
178 output.push(JsonEvent::ObjectKey("type".into()));
179 output.push(JsonEvent::String("uri".into()));
180 output.push(JsonEvent::ObjectKey("value".into()));
181 output.push(JsonEvent::String(uri.as_str().into()));
182 output.push(JsonEvent::EndObject);
183 }
184 TermRef::BlankNode(bnode) => {
185 output.push(JsonEvent::StartObject);
186 output.push(JsonEvent::ObjectKey("type".into()));
187 output.push(JsonEvent::String("bnode".into()));
188 output.push(JsonEvent::ObjectKey("value".into()));
189 output.push(JsonEvent::String(bnode.as_str().into()));
190 output.push(JsonEvent::EndObject);
191 }
192 TermRef::Literal(literal) => {
193 output.push(JsonEvent::StartObject);
194 output.push(JsonEvent::ObjectKey("type".into()));
195 output.push(JsonEvent::String("literal".into()));
196 output.push(JsonEvent::ObjectKey("value".into()));
197 output.push(JsonEvent::String(literal.value().into()));
198 if let Some(language) = literal.language() {
199 output.push(JsonEvent::ObjectKey("xml:lang".into()));
200 output.push(JsonEvent::String(language.into()));
201 } else if !literal.is_plain() {
202 output.push(JsonEvent::ObjectKey("datatype".into()));
203 output.push(JsonEvent::String(literal.datatype().as_str().into()));
204 }
205 output.push(JsonEvent::EndObject);
206 }
207 #[cfg(feature = "rdf-star")]
208 TermRef::Triple(triple) => {
209 output.push(JsonEvent::StartObject);
210 output.push(JsonEvent::ObjectKey("type".into()));
211 output.push(JsonEvent::String("triple".into()));
212 output.push(JsonEvent::ObjectKey("value".into()));
213 output.push(JsonEvent::StartObject);
214 output.push(JsonEvent::ObjectKey("subject".into()));
215 write_json_term(output, triple.subject.as_ref().into());
216 output.push(JsonEvent::ObjectKey("predicate".into()));
217 write_json_term(output, triple.predicate.as_ref().into());
218 output.push(JsonEvent::ObjectKey("object".into()));
219 write_json_term(output, triple.object.as_ref());
220 output.push(JsonEvent::EndObject);
221 output.push(JsonEvent::EndObject);
222 }
223 }
224}
225
226#[allow(clippy::large_enum_variant)]
227pub enum ReaderJsonQueryResultsParserOutput<R: Read> {
228 Solutions {
229 variables: Vec<Variable>,
230 solutions: ReaderJsonSolutionsParser<R>,
231 },
232 Boolean(bool),
233}
234
235impl<R: Read> ReaderJsonQueryResultsParserOutput<R> {
236 pub fn read(reader: R) -> Result<Self, QueryResultsParseError> {
237 let mut json_parser = ReaderJsonParser::new(reader);
238 let mut inner = JsonInnerReader::new();
239 loop {
240 if let Some(result) = inner.read_event(json_parser.parse_next()?)? {
241 return match result {
242 JsonInnerQueryResults::Solutions {
243 variables,
244 solutions,
245 } => Ok(Self::Solutions {
246 variables,
247 solutions: ReaderJsonSolutionsParser {
248 inner: solutions,
249 json_parser,
250 },
251 }),
252 JsonInnerQueryResults::Boolean(value) => Ok(Self::Boolean(value)),
253 };
254 }
255 }
256 }
257}
258
259pub struct ReaderJsonSolutionsParser<R: Read> {
260 inner: JsonInnerSolutions,
261 json_parser: ReaderJsonParser<R>,
262}
263
264impl<R: Read> ReaderJsonSolutionsParser<R> {
265 pub fn parse_next(&mut self) -> Result<Option<Vec<Option<Term>>>, QueryResultsParseError> {
266 match &mut self.inner {
267 JsonInnerSolutions::Reader(reader) => loop {
268 let event = self.json_parser.parse_next()?;
269 if event == JsonEvent::Eof {
270 return Ok(None);
271 }
272 if let Some(result) = reader.parse_event(event)? {
273 return Ok(Some(result));
274 }
275 },
276 JsonInnerSolutions::Iterator(iter) => Ok(iter.next()?),
277 }
278 }
279}
280
281#[cfg(feature = "async-tokio")]
282#[allow(clippy::large_enum_variant)]
283pub enum TokioAsyncReaderJsonQueryResultsParserOutput<R: AsyncRead + Unpin> {
284 Solutions {
285 variables: Vec<Variable>,
286 solutions: TokioAsyncReaderJsonSolutionsParser<R>,
287 },
288 Boolean(bool),
289}
290
291#[cfg(feature = "async-tokio")]
292impl<R: AsyncRead + Unpin> TokioAsyncReaderJsonQueryResultsParserOutput<R> {
293 pub async fn read(reader: R) -> Result<Self, QueryResultsParseError> {
294 let mut json_parser = TokioAsyncReaderJsonParser::new(reader);
295 let mut inner = JsonInnerReader::new();
296 loop {
297 if let Some(result) = inner.read_event(json_parser.parse_next().await?)? {
298 return match result {
299 JsonInnerQueryResults::Solutions {
300 variables,
301 solutions,
302 } => Ok(Self::Solutions {
303 variables,
304 solutions: TokioAsyncReaderJsonSolutionsParser {
305 inner: solutions,
306 json_parser,
307 },
308 }),
309 JsonInnerQueryResults::Boolean(value) => Ok(Self::Boolean(value)),
310 };
311 }
312 }
313 }
314}
315
316#[cfg(feature = "async-tokio")]
317pub struct TokioAsyncReaderJsonSolutionsParser<R: AsyncRead + Unpin> {
318 inner: JsonInnerSolutions,
319 json_parser: TokioAsyncReaderJsonParser<R>,
320}
321
322#[cfg(feature = "async-tokio")]
323impl<R: AsyncRead + Unpin> TokioAsyncReaderJsonSolutionsParser<R> {
324 pub async fn parse_next(
325 &mut self,
326 ) -> Result<Option<Vec<Option<Term>>>, QueryResultsParseError> {
327 match &mut self.inner {
328 JsonInnerSolutions::Reader(reader) => loop {
329 let event = self.json_parser.parse_next().await?;
330 if event == JsonEvent::Eof {
331 return Ok(None);
332 }
333 if let Some(result) = reader.parse_event(event)? {
334 return Ok(Some(result));
335 }
336 },
337 JsonInnerSolutions::Iterator(iter) => Ok(iter.next()?),
338 }
339 }
340}
341
342#[allow(clippy::large_enum_variant)]
343pub enum SliceJsonQueryResultsParserOutput<'a> {
344 Solutions {
345 variables: Vec<Variable>,
346 solutions: SliceJsonSolutionsParser<'a>,
347 },
348 Boolean(bool),
349}
350
351impl<'a> SliceJsonQueryResultsParserOutput<'a> {
352 pub fn read(slice: &'a [u8]) -> Result<Self, QueryResultsSyntaxError> {
353 let mut json_parser = SliceJsonParser::new(slice);
354 let mut inner = JsonInnerReader::new();
355 loop {
356 if let Some(result) = inner.read_event(json_parser.parse_next()?)? {
357 return match result {
358 JsonInnerQueryResults::Solutions {
359 variables,
360 solutions,
361 } => Ok(Self::Solutions {
362 variables,
363 solutions: SliceJsonSolutionsParser {
364 inner: solutions,
365 json_parser,
366 },
367 }),
368 JsonInnerQueryResults::Boolean(value) => Ok(Self::Boolean(value)),
369 };
370 }
371 }
372 }
373}
374
375pub struct SliceJsonSolutionsParser<'a> {
376 inner: JsonInnerSolutions,
377 json_parser: SliceJsonParser<'a>,
378}
379
380impl SliceJsonSolutionsParser<'_> {
381 pub fn parse_next(&mut self) -> Result<Option<Vec<Option<Term>>>, QueryResultsSyntaxError> {
382 match &mut self.inner {
383 JsonInnerSolutions::Reader(reader) => loop {
384 let event = self.json_parser.parse_next()?;
385 if event == JsonEvent::Eof {
386 return Ok(None);
387 }
388 if let Some(result) = reader.parse_event(event)? {
389 return Ok(Some(result));
390 }
391 },
392 JsonInnerSolutions::Iterator(iter) => iter.next(),
393 }
394 }
395}
396
397#[allow(clippy::large_enum_variant)]
398enum JsonInnerQueryResults {
399 Solutions {
400 variables: Vec<Variable>,
401 solutions: JsonInnerSolutions,
402 },
403 Boolean(bool),
404}
405
406#[allow(clippy::large_enum_variant)]
407enum JsonInnerSolutions {
408 Reader(JsonInnerSolutionsParser),
409 Iterator(JsonBufferedSolutionsIterator),
410}
411
412struct JsonInnerReader {
413 state: JsonInnerReaderState,
414 variables: Vec<Variable>,
415 current_solution_variables: Vec<String>,
416 current_solution_values: Vec<Term>,
417 solutions: Vec<(Vec<String>, Vec<Term>)>,
418 vars_read: bool,
419 solutions_read: bool,
420}
421
422#[allow(clippy::large_enum_variant)]
423enum JsonInnerReaderState {
424 Start,
425 InRootObject,
426 BeforeHead,
427 InHead,
428 BeforeVars,
429 InVars,
430 BeforeLinks,
431 InLinks,
432 BeforeResults,
433 InResults,
434 BeforeBindings,
435 BeforeSolution,
436 BetweenSolutionTerms,
437 Term {
438 reader: JsonInnerTermReader,
439 variable: String,
440 },
441 AfterBindings,
442 BeforeBoolean,
443 Ignore {
444 level: usize,
445 after: JsonInnerReaderStateAfterIgnore,
446 },
447}
448
449#[allow(clippy::enum_variant_names)]
450#[derive(Clone, Copy)]
451enum JsonInnerReaderStateAfterIgnore {
452 InRootObject,
453 InHead,
454 InResults,
455 AfterBindings,
456}
457
458impl JsonInnerReader {
459 fn new() -> Self {
460 Self {
461 state: JsonInnerReaderState::Start,
462 variables: Vec::new(),
463 current_solution_variables: Vec::new(),
464 current_solution_values: Vec::new(),
465 solutions: Vec::new(),
466 vars_read: false,
467 solutions_read: false,
468 }
469 }
470
471 fn read_event(
472 &mut self,
473 event: JsonEvent<'_>,
474 ) -> Result<Option<JsonInnerQueryResults>, QueryResultsSyntaxError> {
475 match &mut self.state {
476 JsonInnerReaderState::Start => {
477 if event == JsonEvent::StartObject {
478 self.state = JsonInnerReaderState::InRootObject;
479 Ok(None)
480 } else {
481 Err(QueryResultsSyntaxError::msg(
482 "SPARQL JSON results must be an object",
483 ))
484 }
485 }
486 JsonInnerReaderState::InRootObject => match event {
487 JsonEvent::ObjectKey(key) => match key.as_ref() {
488 "head" => {
489 self.state = JsonInnerReaderState::BeforeHead;
490 Ok(None)
491 }
492 "results" => {
493 self.state = JsonInnerReaderState::BeforeResults;
494 Ok(None)
495 }
496 "boolean" => {
497 self.state = JsonInnerReaderState::BeforeBoolean;
498 Ok(None)
499 }
500 _ => {
501 self.state = JsonInnerReaderState::Ignore {
502 level: 0,
503 after: JsonInnerReaderStateAfterIgnore::InRootObject,
504 };
505 Ok(None)
506 }
507 },
508 JsonEvent::EndObject => Err(QueryResultsSyntaxError::msg(
509 "SPARQL JSON results must contain a 'boolean' or a 'results' key",
510 )),
511 _ => unreachable!(),
512 },
513 JsonInnerReaderState::BeforeHead => {
514 if event == JsonEvent::StartObject {
515 self.state = JsonInnerReaderState::InHead;
516 Ok(None)
517 } else {
518 Err(QueryResultsSyntaxError::msg(
519 "SPARQL JSON results head must be an object",
520 ))
521 }
522 }
523 JsonInnerReaderState::InHead => match event {
524 JsonEvent::ObjectKey(key) => match key.as_ref() {
525 "vars" => {
526 self.state = JsonInnerReaderState::BeforeVars;
527 self.vars_read = true;
528 Ok(None)
529 }
530 "links" => {
531 self.state = JsonInnerReaderState::BeforeLinks;
532 Ok(None)
533 }
534 _ => {
535 self.state = JsonInnerReaderState::Ignore {
536 level: 0,
537 after: JsonInnerReaderStateAfterIgnore::InHead,
538 };
539 Ok(None)
540 }
541 },
542 JsonEvent::EndObject => {
543 self.state = JsonInnerReaderState::InRootObject;
544 Ok(None)
545 }
546 _ => unreachable!(),
547 },
548 JsonInnerReaderState::BeforeVars => {
549 if event == JsonEvent::StartArray {
550 self.state = JsonInnerReaderState::InVars;
551 Ok(None)
552 } else {
553 Err(QueryResultsSyntaxError::msg(
554 "SPARQL JSON results vars must be an array",
555 ))
556 }
557 }
558 JsonInnerReaderState::InVars => match event {
559 JsonEvent::String(variable) => match Variable::new(variable.clone()) {
560 Ok(var) => {
561 if self.variables.contains(&var) {
562 return Err(QueryResultsSyntaxError::msg(format!(
563 "The variable {var} is declared twice"
564 )));
565 }
566 self.variables.push(var);
567 Ok(None)
568 }
569 Err(e) => Err(QueryResultsSyntaxError::msg(format!(
570 "Invalid variable name '{variable}': {e}"
571 ))),
572 },
573 JsonEvent::EndArray => {
574 if self.solutions_read {
575 let mut mapping = HashMap::new();
576 for (i, var) in self.variables.iter().enumerate() {
577 mapping.insert(var.as_str().to_owned(), i);
578 }
579 Ok(Some(JsonInnerQueryResults::Solutions {
580 variables: take(&mut self.variables),
581 solutions: JsonInnerSolutions::Iterator(
582 JsonBufferedSolutionsIterator {
583 mapping,
584 bindings: take(&mut self.solutions).into_iter(),
585 },
586 ),
587 }))
588 } else {
589 self.state = JsonInnerReaderState::InHead;
590 Ok(None)
591 }
592 }
593 _ => Err(QueryResultsSyntaxError::msg(
594 "Variables name in the vars array must be strings",
595 )),
596 },
597 JsonInnerReaderState::BeforeLinks => {
598 if event == JsonEvent::StartArray {
599 self.state = JsonInnerReaderState::InLinks;
600 Ok(None)
601 } else {
602 Err(QueryResultsSyntaxError::msg(
603 "SPARQL JSON results links must be an array",
604 ))
605 }
606 }
607 JsonInnerReaderState::InLinks => match event {
608 JsonEvent::String(_) => Ok(None),
609 JsonEvent::EndArray => {
610 self.state = JsonInnerReaderState::InHead;
611 Ok(None)
612 }
613 _ => Err(QueryResultsSyntaxError::msg(
614 "Links in the links array must be strings",
615 )),
616 },
617 JsonInnerReaderState::BeforeResults => {
618 if event == JsonEvent::StartObject {
619 self.state = JsonInnerReaderState::InResults;
620 Ok(None)
621 } else {
622 Err(QueryResultsSyntaxError::msg(
623 "SPARQL JSON results result must be an object",
624 ))
625 }
626 }
627 JsonInnerReaderState::InResults => match event {
628 JsonEvent::ObjectKey(key) => {
629 if key == "bindings" {
630 self.state = JsonInnerReaderState::BeforeBindings;
631 Ok(None)
632 } else {
633 self.state = JsonInnerReaderState::Ignore {
634 level: 0,
635 after: JsonInnerReaderStateAfterIgnore::InResults,
636 };
637 Ok(None)
638 }
639 }
640 JsonEvent::EndObject => Err(QueryResultsSyntaxError::msg(
641 "The results object must contains a 'bindings' key",
642 )),
643 _ => unreachable!(),
644 },
645 JsonInnerReaderState::BeforeBindings => {
646 if event == JsonEvent::StartArray {
647 self.solutions_read = true;
648 if self.vars_read {
649 let mut mapping = HashMap::new();
650 for (i, var) in self.variables.iter().enumerate() {
651 mapping.insert(var.as_str().to_owned(), i);
652 }
653 Ok(Some(JsonInnerQueryResults::Solutions {
654 variables: take(&mut self.variables),
655 solutions: JsonInnerSolutions::Reader(JsonInnerSolutionsParser {
656 state: JsonInnerSolutionsParserState::BeforeSolution,
657 mapping,
658 new_bindings: Vec::new(),
659 }),
660 }))
661 } else {
662 self.state = JsonInnerReaderState::BeforeSolution;
663 Ok(None)
664 }
665 } else {
666 Err(QueryResultsSyntaxError::msg(
667 "SPARQL JSON results bindings must be an array",
668 ))
669 }
670 }
671 JsonInnerReaderState::BeforeSolution => match event {
672 JsonEvent::StartObject => {
673 self.state = JsonInnerReaderState::BetweenSolutionTerms;
674 Ok(None)
675 }
676 JsonEvent::EndArray => {
677 self.state = JsonInnerReaderState::AfterBindings;
678 Ok(None)
679 }
680 _ => Err(QueryResultsSyntaxError::msg(
681 "Expecting a new solution object",
682 )),
683 },
684 JsonInnerReaderState::BetweenSolutionTerms => match event {
685 JsonEvent::ObjectKey(key) => {
686 self.state = JsonInnerReaderState::Term {
687 reader: JsonInnerTermReader::default(),
688 variable: key.into(),
689 };
690 Ok(None)
691 }
692 JsonEvent::EndObject => {
693 self.state = JsonInnerReaderState::BeforeSolution;
694 self.solutions.push((
695 take(&mut self.current_solution_variables),
696 take(&mut self.current_solution_values),
697 ));
698 Ok(None)
699 }
700 _ => unreachable!(),
701 },
702 JsonInnerReaderState::Term {
703 ref mut reader,
704 variable,
705 } => {
706 let result = reader.read_event(event);
707 if let Some(term) = result? {
708 self.current_solution_variables.push(take(variable));
709 self.current_solution_values.push(term);
710 self.state = JsonInnerReaderState::BetweenSolutionTerms;
711 }
712 Ok(None)
713 }
714 JsonInnerReaderState::AfterBindings => {
715 if event == JsonEvent::EndObject {
716 self.state = JsonInnerReaderState::InRootObject;
717 } else {
718 self.state = JsonInnerReaderState::Ignore {
719 level: 0,
720 after: JsonInnerReaderStateAfterIgnore::AfterBindings,
721 }
722 }
723 Ok(None)
724 }
725 JsonInnerReaderState::BeforeBoolean => {
726 if let JsonEvent::Boolean(v) = event {
727 Ok(Some(JsonInnerQueryResults::Boolean(v)))
728 } else {
729 Err(QueryResultsSyntaxError::msg("Unexpected boolean value"))
730 }
731 }
732 #[allow(clippy::ref_patterns)]
733 JsonInnerReaderState::Ignore { level, ref after } => {
734 let level = match event {
735 JsonEvent::StartArray | JsonEvent::StartObject => *level + 1,
736 JsonEvent::EndArray | JsonEvent::EndObject => *level - 1,
737 JsonEvent::String(_)
738 | JsonEvent::Number(_)
739 | JsonEvent::Boolean(_)
740 | JsonEvent::Null
741 | JsonEvent::ObjectKey(_)
742 | JsonEvent::Eof => *level,
743 };
744 self.state = if level == 0 {
745 match after {
746 JsonInnerReaderStateAfterIgnore::InRootObject => {
747 JsonInnerReaderState::InRootObject
748 }
749 JsonInnerReaderStateAfterIgnore::InHead => JsonInnerReaderState::InHead,
750 JsonInnerReaderStateAfterIgnore::InResults => {
751 JsonInnerReaderState::InResults
752 }
753 JsonInnerReaderStateAfterIgnore::AfterBindings => {
754 JsonInnerReaderState::AfterBindings
755 }
756 }
757 } else {
758 JsonInnerReaderState::Ignore {
759 level,
760 after: *after,
761 }
762 };
763 Ok(None)
764 }
765 }
766 }
767}
768
769struct JsonInnerSolutionsParser {
770 state: JsonInnerSolutionsParserState,
771 mapping: HashMap<String, usize>,
772 new_bindings: Vec<Option<Term>>,
773}
774
775#[allow(clippy::large_enum_variant)]
776enum JsonInnerSolutionsParserState {
777 BeforeSolution,
778 BetweenSolutionTerms,
779 Term {
780 reader: JsonInnerTermReader,
781 key: usize,
782 },
783 AfterEnd,
784}
785
786impl JsonInnerSolutionsParser {
787 fn parse_event(
788 &mut self,
789 event: JsonEvent<'_>,
790 ) -> Result<Option<Vec<Option<Term>>>, QueryResultsSyntaxError> {
791 match &mut self.state {
792 JsonInnerSolutionsParserState::BeforeSolution => match event {
793 JsonEvent::StartObject => {
794 self.state = JsonInnerSolutionsParserState::BetweenSolutionTerms;
795 self.new_bindings = vec![None; self.mapping.len()];
796 Ok(None)
797 }
798 JsonEvent::EndArray => {
799 self.state = JsonInnerSolutionsParserState::AfterEnd;
800 Ok(None)
801 }
802 _ => Err(QueryResultsSyntaxError::msg(
803 "Expecting a new solution object",
804 )),
805 },
806 JsonInnerSolutionsParserState::BetweenSolutionTerms => match event {
807 JsonEvent::ObjectKey(key) => {
808 let key = *self.mapping.get(key.as_ref()).ok_or_else(|| {
809 QueryResultsSyntaxError::msg(format!(
810 "The variable {key} has not been defined in the header"
811 ))
812 })?;
813 self.state = JsonInnerSolutionsParserState::Term {
814 reader: JsonInnerTermReader::default(),
815 key,
816 };
817 Ok(None)
818 }
819 JsonEvent::EndObject => {
820 self.state = JsonInnerSolutionsParserState::BeforeSolution;
821 Ok(Some(take(&mut self.new_bindings)))
822 }
823 _ => unreachable!(),
824 },
825 JsonInnerSolutionsParserState::Term {
826 ref mut reader,
827 key,
828 } => {
829 let result = reader.read_event(event);
830 if let Some(term) = result? {
831 self.new_bindings[*key] = Some(term);
832 self.state = JsonInnerSolutionsParserState::BetweenSolutionTerms;
833 }
834 Ok(None)
835 }
836 JsonInnerSolutionsParserState::AfterEnd => {
837 if event == JsonEvent::EndObject {
838 Ok(None)
839 } else {
840 Err(QueryResultsSyntaxError::msg(
841 "Unexpected JSON after the end of the bindings array",
842 ))
843 }
844 }
845 }
846 }
847}
848
849#[derive(Default)]
850struct JsonInnerTermReader {
851 state: JsonInnerTermReaderState,
852 term_type: Option<TermType>,
853 value: Option<String>,
854 lang: Option<String>,
855 datatype: Option<NamedNode>,
856 #[cfg(feature = "rdf-star")]
857 subject: Option<Term>,
858 #[cfg(feature = "rdf-star")]
859 predicate: Option<Term>,
860 #[cfg(feature = "rdf-star")]
861 object: Option<Term>,
862}
863
864#[derive(Default)]
865enum JsonInnerTermReaderState {
866 #[default]
867 Start,
868 Middle,
869 TermType,
870 Value,
871 Lang,
872 Datatype,
873 #[cfg(feature = "rdf-star")]
874 InValue,
875 #[cfg(feature = "rdf-star")]
876 Subject(Box<JsonInnerTermReader>),
877 #[cfg(feature = "rdf-star")]
878 Predicate(Box<JsonInnerTermReader>),
879 #[cfg(feature = "rdf-star")]
880 Object(Box<JsonInnerTermReader>),
881}
882
883enum TermType {
884 Uri,
885 BNode,
886 Literal,
887 #[cfg(feature = "rdf-star")]
888 Triple,
889}
890
891impl JsonInnerTermReader {
892 fn read_event(
893 &mut self,
894 event: JsonEvent<'_>,
895 ) -> Result<Option<Term>, QueryResultsSyntaxError> {
896 match &mut self.state {
897 JsonInnerTermReaderState::Start => {
898 if event == JsonEvent::StartObject {
899 self.state = JsonInnerTermReaderState::Middle;
900 Ok(None)
901 } else {
902 Err(QueryResultsSyntaxError::msg(
903 "RDF terms must be encoded using objects",
904 ))
905 }
906 }
907 JsonInnerTermReaderState::Middle => match event {
908 JsonEvent::ObjectKey(object_key) => {
909 self.state = match object_key.as_ref() {
910 "type" => JsonInnerTermReaderState::TermType,
911 "value" => JsonInnerTermReaderState::Value,
912 "datatype" => JsonInnerTermReaderState::Datatype,
913 "xml:lang" => JsonInnerTermReaderState::Lang,
914 _ => {
915 return Err(QueryResultsSyntaxError::msg(format!(
916 "Unsupported term key: {object_key}"
917 )));
918 }
919 };
920 Ok(None)
921 }
922 JsonEvent::EndObject => {
923 self.state = JsonInnerTermReaderState::Start;
924 match self.term_type.take() {
925 None => Err(QueryResultsSyntaxError::msg(
926 "Term serialization should have a 'type' key",
927 )),
928 Some(TermType::Uri) => Ok(Some(
929 NamedNode::new(self.value.take().ok_or_else(|| {
930 QueryResultsSyntaxError::msg(
931 "uri serialization should have a 'value' key",
932 )
933 })?)
934 .map_err(|e| {
935 QueryResultsSyntaxError::msg(format!("Invalid uri value: {e}"))
936 })?
937 .into(),
938 )),
939 Some(TermType::BNode) => Ok(Some(
940 BlankNode::new(self.value.take().ok_or_else(|| {
941 QueryResultsSyntaxError::msg(
942 "bnode serialization should have a 'value' key",
943 )
944 })?)
945 .map_err(|e| {
946 QueryResultsSyntaxError::msg(format!("Invalid bnode value: {e}"))
947 })?
948 .into(),
949 )),
950 Some(TermType::Literal) => {
951 let value = self.value.take().ok_or_else(|| {
952 QueryResultsSyntaxError::msg(
953 "literal serialization should have a 'value' key",
954 )
955 })?;
956 Ok(Some(match self.lang.take() {
957 Some(lang) => {
958 if let Some(datatype) = &self.datatype {
959 if datatype.as_ref() != rdf::LANG_STRING {
960 return Err(QueryResultsSyntaxError::msg(format!(
961 "xml:lang value '{lang}' provided with the datatype {datatype}"
962 )));
963 }
964 }
965 Literal::new_language_tagged_literal(value, &*lang)
966 .map_err(|e| {
967 QueryResultsSyntaxError::msg(format!(
968 "Invalid xml:lang value '{lang}': {e}"
969 ))
970 })?
971 }
972 None => {
973 if let Some(datatype) = self.datatype.take() {
974 Literal::new_typed_literal(value, datatype)
975 } else {
976 Literal::new_simple_literal(value)
977 }
978 }
979 }.into()))
980 }
981 #[cfg(feature = "rdf-star")]
982 Some(TermType::Triple) => Ok(Some(
983 Triple::new(
984 match self.subject.take().ok_or_else(|| {
985 QueryResultsSyntaxError::msg(
986 "triple serialization should have a 'subject' key",
987 )
988 })? {
989 Term::NamedNode(subject) => subject.into(),
990 Term::BlankNode(subject) => subject.into(),
991 Term::Triple(subject) => Subject::Triple(subject),
992 Term::Literal(_) => {
993 return Err(QueryResultsSyntaxError::msg(
994 "The 'subject' value should not be a literal",
995 ));
996 }
997 },
998 match self.predicate.take().ok_or_else(|| {
999 QueryResultsSyntaxError::msg(
1000 "triple serialization should have a 'predicate' key",
1001 )
1002 })? {
1003 Term::NamedNode(predicate) => predicate,
1004 _ => {
1005 return Err(QueryResultsSyntaxError::msg(
1006 "The 'predicate' value should be a uri",
1007 ));
1008 }
1009 },
1010 self.object.take().ok_or_else(|| {
1011 QueryResultsSyntaxError::msg(
1012 "triple serialization should have a 'object' key",
1013 )
1014 })?,
1015 )
1016 .into(),
1017 )),
1018 }
1019 }
1020 _ => unreachable!(),
1021 },
1022 JsonInnerTermReaderState::TermType => {
1023 self.state = JsonInnerTermReaderState::Middle;
1024 if let JsonEvent::String(value) = event {
1025 match value.as_ref() {
1026 "uri" => {
1027 self.term_type = Some(TermType::Uri);
1028 Ok(None)
1029 }
1030 "bnode" => {
1031 self.term_type = Some(TermType::BNode);
1032 Ok(None)
1033 }
1034 "literal" | "typed-literal" => {
1035 self.term_type = Some(TermType::Literal);
1036 Ok(None)
1037 }
1038 #[cfg(feature = "rdf-star")]
1039 "triple" => {
1040 self.term_type = Some(TermType::Triple);
1041 Ok(None)
1042 }
1043 _ => Err(QueryResultsSyntaxError::msg(format!(
1044 "Unexpected term type: '{value}'"
1045 ))),
1046 }
1047 } else {
1048 Err(QueryResultsSyntaxError::msg("Term type must be a string"))
1049 }
1050 }
1051 JsonInnerTermReaderState::Value => match event {
1052 JsonEvent::String(value) => {
1053 self.value = Some(value.into_owned());
1054 self.state = JsonInnerTermReaderState::Middle;
1055 Ok(None)
1056 }
1057 #[cfg(feature = "rdf-star")]
1058 JsonEvent::StartObject => {
1059 self.state = JsonInnerTermReaderState::InValue;
1060 Ok(None)
1061 }
1062 _ => {
1063 self.state = JsonInnerTermReaderState::Middle;
1064
1065 Err(QueryResultsSyntaxError::msg("Term value must be a string"))
1066 }
1067 },
1068 JsonInnerTermReaderState::Lang => {
1069 let result = if let JsonEvent::String(value) = event {
1070 self.lang = Some(value.into_owned());
1071 Ok(None)
1072 } else {
1073 Err(QueryResultsSyntaxError::msg("Term lang must be strings"))
1074 };
1075 self.state = JsonInnerTermReaderState::Middle;
1076
1077 result
1078 }
1079 JsonInnerTermReaderState::Datatype => {
1080 let result = if let JsonEvent::String(value) = event {
1081 match NamedNode::new(value) {
1082 Ok(datatype) => {
1083 self.datatype = Some(datatype);
1084 Ok(None)
1085 }
1086 Err(e) => Err(QueryResultsSyntaxError::msg(format!(
1087 "Invalid datatype: {e}"
1088 ))),
1089 }
1090 } else {
1091 Err(QueryResultsSyntaxError::msg("Term lang must be strings"))
1092 };
1093 self.state = JsonInnerTermReaderState::Middle;
1094
1095 result
1096 }
1097 #[cfg(feature = "rdf-star")]
1098 JsonInnerTermReaderState::InValue => match event {
1099 JsonEvent::ObjectKey(object_key) => {
1100 self.state = match object_key.as_ref() {
1101 "subject" => JsonInnerTermReaderState::Subject(Box::default()),
1102 "predicate" => JsonInnerTermReaderState::Predicate(Box::default()),
1103 "object" => JsonInnerTermReaderState::Object(Box::default()),
1104 _ => {
1105 return Err(QueryResultsSyntaxError::msg(format!(
1106 "Unsupported value key: {object_key}"
1107 )));
1108 }
1109 };
1110 Ok(None)
1111 }
1112 JsonEvent::EndObject => {
1113 self.state = JsonInnerTermReaderState::Middle;
1114 Ok(None)
1115 }
1116 _ => unreachable!(),
1117 },
1118 #[cfg(feature = "rdf-star")]
1119 JsonInnerTermReaderState::Subject(ref mut inner_state) => {
1120 if let Some(term) = inner_state.read_event(event)? {
1121 self.state = JsonInnerTermReaderState::InValue;
1122 self.subject = Some(term);
1123 }
1124 Ok(None)
1125 }
1126 #[cfg(feature = "rdf-star")]
1127 JsonInnerTermReaderState::Predicate(ref mut inner_state) => {
1128 if let Some(term) = inner_state.read_event(event)? {
1129 self.state = JsonInnerTermReaderState::InValue;
1130 self.predicate = Some(term);
1131 }
1132 Ok(None)
1133 }
1134 #[cfg(feature = "rdf-star")]
1135 JsonInnerTermReaderState::Object(ref mut inner_state) => {
1136 if let Some(term) = inner_state.read_event(event)? {
1137 self.state = JsonInnerTermReaderState::InValue;
1138 self.object = Some(term);
1139 }
1140 Ok(None)
1141 }
1142 }
1143 }
1144}
1145
1146pub struct JsonBufferedSolutionsIterator {
1147 mapping: HashMap<String, usize>,
1148 bindings: std::vec::IntoIter<(Vec<String>, Vec<Term>)>,
1149}
1150
1151impl JsonBufferedSolutionsIterator {
1152 fn next(&mut self) -> Result<Option<Vec<Option<Term>>>, QueryResultsSyntaxError> {
1153 let Some((variables, values)) = self.bindings.next() else {
1154 return Ok(None);
1155 };
1156 let mut new_bindings = vec![None; self.mapping.len()];
1157 for (variable, value) in variables.into_iter().zip(values) {
1158 let k = *self.mapping.get(&variable).ok_or_else(|| {
1159 QueryResultsSyntaxError::msg(format!(
1160 "The variable {variable} has not been defined in the header"
1161 ))
1162 })?;
1163 new_bindings[k] = Some(value);
1164 }
1165 Ok(Some(new_bindings))
1166 }
1167}