@ -1,58 +1,56 @@
//! Implementation of [SPARQL Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/)
//! Implementation of [SPARQL Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/)
use crate ::error ::invalid_input_error ;
use crate ::error ::{ invalid_data_error , invalid_input_error } ;
use crate ::model ::* ;
use crate ::model ::* ;
use crate ::sparql ::error ::EvaluationError ;
use crate ::sparql ::error ::EvaluationError ;
use crate ::sparql ::model ::* ;
use crate ::sparql ::model ::* ;
use std ::io ::Write ;
use json_event_parser ::{ JsonEvent , JsonReader , JsonWriter } ;
use std ::collections ::BTreeMap ;
use std ::io ;
use std ::io ::{ BufRead , Write } ;
use std ::rc ::Rc ;
pub fn write_json_results (
pub fn write_json_results ( results : QueryResults , sink : impl Write ) -> Result < ( ) , EvaluationError > {
results : QueryResults ,
let mut writer = JsonWriter ::from_writer ( sink ) ;
mut sink : impl Write ,
) -> Result < ( ) , EvaluationError > {
match results {
match results {
QueryResults ::Boolean ( value ) = > {
QueryResults ::Boolean ( value ) = > {
sink . write_all ( b" { \" head \" :{}, \" boolean \" : " ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
sink . write_all ( if value { b" true " } else { b" false " } ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "head" ) ) ? ;
sink . write_all ( b" } " ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "boolean" ) ) ? ;
writer . write_event ( JsonEvent ::Boolean ( value ) ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
Ok ( ( ) )
Ok ( ( ) )
}
}
QueryResults ::Solutions ( solutions ) = > {
QueryResults ::Solutions ( solutions ) = > {
sink . write_all ( b" { \" head \" :{ \" vars \" :[ " ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
let mut start_vars = true ;
writer . write_event ( JsonEvent ::ObjectKey ( "head" ) ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "vars" ) ) ? ;
writer . write_event ( JsonEvent ::StartArray ) ? ;
for variable in solutions . variables ( ) {
for variable in solutions . variables ( ) {
if start_vars {
writer . write_event ( JsonEvent ::String ( variable . as_str ( ) ) ) ? ;
start_vars = false ;
} else {
sink . write_all ( b" , " ) ? ;
}
write_escaped_json_string ( variable . as_str ( ) , & mut sink ) ? ;
}
}
sink . write_all ( b" ]}, \" results \" :{ \" bindings \" :[ " ) ? ;
writer . write_event ( JsonEvent ::EndArray ) ? ;
let mut start_bindings = true ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "results" ) ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "bindings" ) ) ? ;
writer . write_event ( JsonEvent ::StartArray ) ? ;
for solution in solutions {
for solution in solutions {
if start_bindings {
writer . write_event ( JsonEvent ::StartObject ) ? ;
start_bindings = false ;
} else {
sink . write_all ( b" , " ) ? ;
}
sink . write_all ( b" { " ) ? ;
let solution = solution ? ;
let solution = solution ? ;
let mut start_binding = true ;
for ( variable , value ) in solution . iter ( ) {
for ( variable , value ) in solution . iter ( ) {
if start_binding {
writer . write_event ( JsonEvent ::ObjectKey ( variable . as_str ( ) ) ) ? ;
start_binding = false ;
write_json_term ( value . as_ref ( ) , & mut writer ) ? ;
} else {
sink . write_all ( b" , " ) ? ;
}
write_escaped_json_string ( variable . as_str ( ) , & mut sink ) ? ;
sink . write_all ( b" : " ) ? ;
write_json_term ( value . as_ref ( ) , & mut sink ) ? ;
}
}
sink . write_all ( b" } " ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
}
}
sink . write_all ( b" ]}} " ) ? ;
writer . write_event ( JsonEvent ::EndArray ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
Ok ( ( ) )
Ok ( ( ) )
}
}
QueryResults ::Graph ( _ ) = > Err ( invalid_input_error (
QueryResults ::Graph ( _ ) = > Err ( invalid_input_error (
@ -62,74 +60,398 @@ pub fn write_json_results(
}
}
}
}
fn write_json_term ( term : TermRef < ' _ > , sink : & mut impl Write ) -> Result < ( ) , EvaluationError > {
fn write_json_term (
term : TermRef < ' _ > ,
writer : & mut JsonWriter < impl Write > ,
) -> Result < ( ) , EvaluationError > {
match term {
match term {
TermRef ::NamedNode ( uri ) = > {
TermRef ::NamedNode ( uri ) = > {
sink . write_all ( b" { \" type \" : \" uri \" , \" value \" : " ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
write_escaped_json_string ( uri . as_str ( ) , sink ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "type" ) ) ? ;
sink . write_all ( b" } " ) ? ;
writer . write_event ( JsonEvent ::String ( "uri" ) ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "value" ) ) ? ;
writer . write_event ( JsonEvent ::String ( uri . as_str ( ) ) ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
}
}
TermRef ::BlankNode ( bnode ) = > {
TermRef ::BlankNode ( bnode ) = > {
sink . write_all ( b" { \" type \" : \" bnode \" , \" value \" : " ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
write_escaped_json_string ( bnode . as_str ( ) , sink ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "type" ) ) ? ;
sink . write_all ( b" } " ) ? ;
writer . write_event ( JsonEvent ::String ( "bnode" ) ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "value" ) ) ? ;
writer . write_event ( JsonEvent ::String ( bnode . as_str ( ) ) ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
}
}
TermRef ::Literal ( literal ) = > {
TermRef ::Literal ( literal ) = > {
sink . write_all ( b" { \" type \" : \" literal \" , \" value \" : " ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
write_escaped_json_string ( literal . value ( ) , sink ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "type" ) ) ? ;
writer . write_event ( JsonEvent ::String ( "literal" ) ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "value" ) ) ? ;
writer . write_event ( JsonEvent ::String ( literal . value ( ) ) ) ? ;
if let Some ( language ) = literal . language ( ) {
if let Some ( language ) = literal . language ( ) {
sink . write_all ( b" , \" xml:lang \" : " ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "xml:lang" ) ) ? ;
write_escaped_json_string ( language , sink ) ? ;
writer . write_event ( JsonEvent ::String ( language ) ) ? ;
} else if ! literal . is_plain ( ) {
} else if ! literal . is_plain ( ) {
sink . write_all ( b" , \" datatype \" : " ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "datatype" ) ) ? ;
write_escaped_json_s tring ( literal . datatype ( ) . as_str ( ) , sink ) ? ;
writer . write_event ( JsonEvent ::S tring ( literal . datatype ( ) . as_str ( ) ) ) ? ;
}
}
sink . write_all ( b" } " ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
}
}
TermRef ::Triple ( triple ) = > {
TermRef ::Triple ( triple ) = > {
sink . write_all ( b" :{ \" type \" : \" triple \" , \" value \" :{ \" subject \" : " ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
write_json_term ( triple . subject . as_ref ( ) . into ( ) , sink ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "type" ) ) ? ;
sink . write_all ( b" :, \" predicate \" : " ) ? ;
writer . write_event ( JsonEvent ::String ( "triple" ) ) ? ;
write_json_term ( triple . predicate . as_ref ( ) . into ( ) , sink ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "value" ) ) ? ;
sink . write_all ( b" :, \" object \" : " ) ? ;
writer . write_event ( JsonEvent ::StartObject ) ? ;
write_json_term ( triple . object . as_ref ( ) , sink ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "subject" ) ) ? ;
sink . write_all ( b" }} " ) ? ;
write_json_term ( triple . subject . as_ref ( ) . into ( ) , writer ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "predicate" ) ) ? ;
write_json_term ( triple . predicate . as_ref ( ) . into ( ) , writer ) ? ;
writer . write_event ( JsonEvent ::ObjectKey ( "object" ) ) ? ;
write_json_term ( triple . object . as_ref ( ) , writer ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
writer . write_event ( JsonEvent ::EndObject ) ? ;
}
}
}
}
Ok ( ( ) )
Ok ( ( ) )
}
}
fn write_escaped_json_string ( s : & str , sink : & mut impl Write ) -> Result < ( ) , EvaluationError > {
pub fn read_json_results ( source : impl BufRead + ' static ) -> Result < QueryResults , io ::Error > {
sink . write_all ( b" \" " ) ? ;
let mut reader = JsonReader ::from_reader ( source ) ;
for c in s . chars ( ) {
let mut buffer = Vec ::default ( ) ;
match c {
let mut variables = None ;
'\\' = > sink . write_all ( b" \\ \\ " ) ,
'"' = > sink . write_all ( b" \\ \" " ) ,
if reader . read_event ( & mut buffer ) ? ! = JsonEvent ::StartObject {
c = > {
return Err ( invalid_data_error (
if c < char ::from ( 32 ) {
"SPARQL JSON results should be an object" ,
match c {
) ) ;
'\u{08}' = > sink . write_all ( b" \\ b " ) ,
}
'\u{0C}' = > sink . write_all ( b" \\ f " ) ,
'\n' = > sink . write_all ( b" \\ n " ) ,
loop {
'\r' = > sink . write_all ( b" \\ r " ) ,
let event = reader . read_event ( & mut buffer ) ? ;
'\t' = > sink . write_all ( b" \\ t " ) ,
match event {
c = > {
JsonEvent ::ObjectKey ( key ) = > match key {
let mut c = c as u8 ;
"head" = > variables = Some ( read_head ( & mut reader , & mut buffer ) ? ) ,
let mut result = [ b'\\' , b'u' , 0 , 0 , 0 , 0 ] ;
"results" = > {
for i in ( 2 .. 6 ) . rev ( ) {
if reader . read_event ( & mut buffer ) ? ! = JsonEvent ::StartObject {
let ch = c % 16 ;
return Err ( invalid_data_error ( "'results' should be an object" ) ) ;
result [ i ] = ch + if ch < 10 { b'0' } else { b'A' } ;
}
c / = 16 ;
if reader . read_event ( & mut buffer ) ? ! = JsonEvent ::ObjectKey ( "bindings" ) {
return Err ( invalid_data_error (
"'results' should contain a 'bindings' key" ,
) ) ;
}
if reader . read_event ( & mut buffer ) ? ! = JsonEvent ::StartArray {
return Err ( invalid_data_error ( "'bindings' should be an object" ) ) ;
}
return if let Some ( variables ) = variables {
let mut mapping = BTreeMap ::default ( ) ;
for ( i , var ) in variables . iter ( ) . enumerate ( ) {
mapping . insert ( var . clone ( ) , i ) ;
}
Ok ( QueryResults ::Solutions ( QuerySolutionIter ::new (
Rc ::new (
variables
. into_iter ( )
. map ( Variable ::new )
. collect ::< Result < Vec < _ > , _ > > ( )
. map_err ( invalid_data_error ) ? ,
) ,
Box ::new ( ResultsIterator {
reader ,
buffer ,
mapping ,
} ) ,
) ) )
} else {
Err ( invalid_data_error (
"SPARQL tuple query results should contain a head key" ,
) )
} ;
}
"boolean" = > {
return if let JsonEvent ::Boolean ( v ) = reader . read_event ( & mut buffer ) ? {
Ok ( QueryResults ::Boolean ( v ) )
} else {
Err ( invalid_data_error ( "Unexpected boolean value" ) )
}
}
_ = > {
return Err ( invalid_data_error ( format! (
"Expecting head or result key, found {}" ,
key
) ) ) ;
}
} ,
JsonEvent ::EndObject = > {
return Err ( invalid_data_error (
"SPARQL results should contain a bindings key or a boolean key" ,
) )
}
JsonEvent ::Eof = > return Err ( io ::Error ::from ( io ::ErrorKind ::UnexpectedEof ) ) ,
_ = > return Err ( invalid_data_error ( "Invalid SPARQL results serialization" ) ) ,
}
}
}
fn read_head < R : BufRead > (
reader : & mut JsonReader < R > ,
buffer : & mut Vec < u8 > ,
) -> io ::Result < Vec < String > > {
if reader . read_event ( buffer ) ? ! = JsonEvent ::StartObject {
return Err ( invalid_data_error ( "head should be an object" ) ) ;
}
let mut variables = None ;
loop {
match reader . read_event ( buffer ) ? {
JsonEvent ::ObjectKey ( key ) = > match key {
"vars" = > variables = Some ( read_string_array ( reader , buffer ) ? ) ,
"link" = > {
read_string_array ( reader , buffer ) ? ;
}
_ = > {
return Err ( invalid_data_error ( format! (
"Unexpected key in head: '{}'" ,
key
) ) )
}
} ,
JsonEvent ::EndObject = > return Ok ( variables . unwrap_or_else ( Vec ::new ) ) ,
_ = > return Err ( invalid_data_error ( "Invalid head serialization" ) ) ,
}
}
}
fn read_string_array < R : BufRead > (
reader : & mut JsonReader < R > ,
buffer : & mut Vec < u8 > ,
) -> io ::Result < Vec < String > > {
if reader . read_event ( buffer ) ? ! = JsonEvent ::StartArray {
return Err ( invalid_data_error ( "Variable list should be an array" ) ) ;
}
let mut elements = Vec ::new ( ) ;
loop {
match reader . read_event ( buffer ) ? {
JsonEvent ::String ( s ) = > {
elements . push ( s . into ( ) ) ;
}
JsonEvent ::EndArray = > return Ok ( elements ) ,
_ = > return Err ( invalid_data_error ( "Variable names should be strings" ) ) ,
}
}
}
struct ResultsIterator < R : BufRead > {
reader : JsonReader < R > ,
buffer : Vec < u8 > ,
mapping : BTreeMap < String , usize > ,
}
impl < R : BufRead > Iterator for ResultsIterator < R > {
type Item = Result < Vec < Option < Term > > , EvaluationError > ;
fn next ( & mut self ) -> Option < Result < Vec < Option < Term > > , EvaluationError > > {
self . read_next ( ) . map_err ( EvaluationError ::from ) . transpose ( )
}
}
impl < R : BufRead > ResultsIterator < R > {
fn read_next ( & mut self ) -> io ::Result < Option < Vec < Option < Term > > > > {
let mut new_bindings = vec! [ None ; self . mapping . len ( ) ] ;
loop {
match self . reader . read_event ( & mut self . buffer ) ? {
JsonEvent ::StartObject = > ( ) ,
JsonEvent ::EndObject = > return Ok ( Some ( new_bindings ) ) ,
JsonEvent ::EndArray | JsonEvent ::Eof = > return Ok ( None ) ,
JsonEvent ::ObjectKey ( key ) = > {
let k = * self . mapping . get ( key ) . ok_or_else ( | | {
invalid_data_error ( format! (
"The variable {} has not been defined in the header" ,
key
) )
} ) ? ;
new_bindings [ k ] = Some ( self . read_value ( ) ? )
}
_ = > return Err ( invalid_data_error ( "Invalid result serialization" ) ) ,
}
}
}
fn read_value ( & mut self ) -> io ::Result < Term > {
enum Type {
Uri ,
BNode ,
Literal ,
Triple ,
}
#[ derive(Eq, PartialEq) ]
enum State {
Type ,
Value ,
Lang ,
Datatype ,
}
let mut state = None ;
let mut t = None ;
let mut value = None ;
let mut lang = None ;
let mut datatype = None ;
let mut subject = None ;
let mut predicate = None ;
let mut object = None ;
if self . reader . read_event ( & mut self . buffer ) ? ! = JsonEvent ::StartObject {
return Err ( invalid_data_error (
"Term serializations should be an object" ,
) ) ;
}
loop {
match self . reader . read_event ( & mut self . buffer ) ? {
JsonEvent ::ObjectKey ( key ) = > match key {
"type" = > state = Some ( State ::Type ) ,
"value" = > state = Some ( State ::Value ) ,
"xml:lang" = > state = Some ( State ::Lang ) ,
"datatype" = > state = Some ( State ::Datatype ) ,
"subject" = > subject = Some ( self . read_value ( ) ? ) ,
"predicate" = > predicate = Some ( self . read_value ( ) ? ) ,
"object" = > object = Some ( self . read_value ( ) ? ) ,
_ = > {
return Err ( invalid_data_error ( format! (
"Unexpected key in term serialization: '{}'" ,
key
) ) )
}
} ,
JsonEvent ::StartObject = > {
if state ! = Some ( State ::Value ) {
return Err ( invalid_data_error (
"Unexpected nested object in term serialization" ,
) ) ;
}
}
JsonEvent ::String ( s ) = > match state {
Some ( State ::Type ) = > {
match s {
"uri" = > t = Some ( Type ::Uri ) ,
"bnode" = > t = Some ( Type ::BNode ) ,
"literal" = > t = Some ( Type ::Literal ) ,
"triple" = > t = Some ( Type ::Triple ) ,
_ = > {
return Err ( invalid_data_error ( format! (
"Unexpected term type: '{}'" ,
s
) ) )
}
}
sink . write_all ( & result )
} ;
state = None ;
}
Some ( State ::Value ) = > {
value = Some ( s . to_owned ( ) ) ;
state = None ;
}
Some ( State ::Lang ) = > {
lang = Some ( s . to_owned ( ) ) ;
state = None ;
}
Some ( State ::Datatype ) = > {
datatype = Some ( s . to_owned ( ) ) ;
state = None ;
}
_ = > ( ) , // impossible
} ,
JsonEvent ::EndObject = > {
if let Some ( s ) = state {
if s = = State ::Value {
state = None ; //End of triple
} else {
return Err ( invalid_data_error (
"Term description values should be string" ,
) ) ;
}
}
} else {
return match t {
None = > Err ( invalid_data_error (
"Term serialization should have a 'type' key" ,
) ) ,
Some ( Type ::Uri ) = > Ok ( NamedNode ::new ( value . ok_or_else ( | | {
invalid_data_error ( "uri serialization should have a 'value' key" )
} ) ? )
. map_err ( | e | invalid_data_error ( format! ( "Invalid uri value: {}" , e ) ) ) ?
. into ( ) ) ,
Some ( Type ::BNode ) = > Ok ( BlankNode ::new ( value . ok_or_else ( | | {
invalid_data_error ( "bnode serialization should have a 'value' key" )
} ) ? )
. map_err ( | e | invalid_data_error ( format! ( "Invalid bnode value: {}" , e ) ) ) ?
. into ( ) ) ,
Some ( Type ::Literal ) = > {
let value = value . ok_or_else ( | | {
invalid_data_error (
"uri serialization should have a 'value' key" ,
)
} ) ? ;
Ok ( match datatype {
Some ( datatype ) = > Literal ::new_typed_literal (
value ,
NamedNode ::new ( datatype ) . map_err ( | e | {
invalid_data_error ( format! (
"Invalid datatype value: {}" ,
e
) )
} ) ? ,
) ,
None = > match lang {
Some ( lang ) = > {
Literal ::new_language_tagged_literal ( value , lang )
. map_err ( | e | {
invalid_data_error ( format! (
"Invalid xml:lang value: {}" ,
e
) )
} ) ?
}
None = > Literal ::new_simple_literal ( value ) ,
} ,
}
. into ( ) )
}
Some ( Type ::Triple ) = > Ok ( Triple ::new (
match subject . ok_or_else ( | | {
invalid_data_error (
"triple serialization should have a 'subject' key" ,
)
} ) ? {
Term ::NamedNode ( subject ) = > subject . into ( ) ,
Term ::BlankNode ( subject ) = > subject . into ( ) ,
Term ::Triple ( subject ) = > Subject ::Triple ( subject ) ,
Term ::Literal ( _ ) = > {
return Err ( invalid_data_error (
"The 'subject' value should not be a literal" ,
)
. into ( ) )
}
} ,
match predicate . ok_or_else ( | | {
invalid_data_error (
"triple serialization should have a 'predicate' key" ,
)
} ) ? {
Term ::NamedNode ( predicate ) = > predicate ,
_ = > {
return Err ( invalid_data_error (
"The 'predicate' value should be a uri" ,
)
. into ( ) )
}
} ,
object . ok_or_else ( | | {
invalid_data_error (
"triple serialization should have a 'object' key" ,
)
} ) ? ,
)
. into ( ) ) ,
} ;
}
}
} else {
write! ( sink , "{}" , c )
}
}
_ = > return Err ( invalid_data_error ( "Invalid term serialization" ) ) ,
}
}
} ? ;
}
}
}
sink . write_all ( b" \" " ) ? ;
Ok ( ( ) )
}
}