sparesults/
json.rs

1//! Implementation of [SPARQL Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/)
2
3use 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}