@ -1,9 +1,9 @@
//! Implementation of [SPARQL Query Results XML Format](http://www.w3.org/TR/rdf-sparql-XMLres/)
//! Implementation of [SPARQL Query Results XML Format](http://www.w3.org/TR/rdf-sparql-XMLres/)
use crate ::error ::{ invalid_data_error , invalid_input_error } ;
use crate ::model ::* ;
use crate ::model ::* ;
use crate ::sparql ::error ::EvaluationError ;
use crate ::sparql ::model ::* ;
use crate ::sparql ::model ::* ;
use crate ::Error ;
use crate ::Result ;
use quick_xml ::events ::BytesDecl ;
use quick_xml ::events ::BytesDecl ;
use quick_xml ::events ::BytesEnd ;
use quick_xml ::events ::BytesEnd ;
use quick_xml ::events ::BytesStart ;
use quick_xml ::events ::BytesStart ;
@ -17,10 +17,22 @@ use std::io::Write;
use std ::iter ::empty ;
use std ::iter ::empty ;
use std ::rc ::Rc ;
use std ::rc ::Rc ;
pub fn write_xml_results ( results : QueryResult , sink : impl Write ) -> Result < ( ) > {
pub fn write_xml_results ( results : QueryResult , sink : impl Write ) -> Result < ( ) , EvaluationError > {
let mut writer = Writer ::new ( sink ) ;
match results {
match results {
QueryResult ::Boolean ( value ) = > {
QueryResult ::Boolean ( value ) = > {
write_boolean ( value , sink ) . map_err ( map_xml_error ) ? ;
Ok ( ( ) )
}
QueryResult ::Solutions ( solutions ) = > write_solutions ( solutions , sink ) ,
QueryResult ::Graph ( _ ) = > Err ( invalid_input_error (
"Graphs could not be formatted to SPARQL query results XML format" ,
)
. into ( ) ) ,
}
}
fn write_boolean ( value : bool , sink : impl Write ) -> Result < ( ) , quick_xml ::Error > {
let mut writer = Writer ::new ( sink ) ;
writer . write_event ( Event ::Decl ( BytesDecl ::new ( b" 1.0 " , None , None ) ) ) ? ;
writer . write_event ( Event ::Decl ( BytesDecl ::new ( b" 1.0 " , None , None ) ) ) ? ;
let mut sparql_open = BytesStart ::borrowed_name ( b" sparql " ) ;
let mut sparql_open = BytesStart ::borrowed_name ( b" sparql " ) ;
sparql_open . push_attribute ( ( "xmlns" , "http://www.w3.org/2005/sparql-results#" ) ) ;
sparql_open . push_attribute ( ( "xmlns" , "http://www.w3.org/2005/sparql-results#" ) ) ;
@ -35,75 +47,108 @@ pub fn write_xml_results(results: QueryResult, sink: impl Write) -> Result<()> {
} ) ) ) ? ;
} ) ) ) ? ;
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" boolean " ) ) ) ? ;
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" boolean " ) ) ) ? ;
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" sparql " ) ) ) ? ;
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" sparql " ) ) ) ? ;
}
Ok ( ( ) )
QueryResult ::Solutions ( solutions ) = > {
}
writer . write_event ( Event ::Decl ( BytesDecl ::new ( b" 1.0 " , None , None ) ) ) ? ;
fn write_solutions (
solutions : QuerySolutionsIterator ,
sink : impl Write ,
) -> Result < ( ) , EvaluationError > {
let mut writer = Writer ::new ( sink ) ;
writer
. write_event ( Event ::Decl ( BytesDecl ::new ( b" 1.0 " , None , None ) ) )
. map_err ( map_xml_error ) ? ;
let mut sparql_open = BytesStart ::borrowed_name ( b" sparql " ) ;
let mut sparql_open = BytesStart ::borrowed_name ( b" sparql " ) ;
sparql_open . push_attribute ( ( "xmlns" , "http://www.w3.org/2005/sparql-results#" ) ) ;
sparql_open . push_attribute ( ( "xmlns" , "http://www.w3.org/2005/sparql-results#" ) ) ;
writer . write_event ( Event ::Start ( sparql_open ) ) ? ;
writer
writer . write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" head " ) ) ) ? ;
. write_event ( Event ::Start ( sparql_open ) )
. map_err ( map_xml_error ) ? ;
writer
. write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" head " ) ) )
. map_err ( map_xml_error ) ? ;
for variable in solutions . variables ( ) {
for variable in solutions . variables ( ) {
let mut variable_tag = BytesStart ::borrowed_name ( b" variable " ) ;
let mut variable_tag = BytesStart ::borrowed_name ( b" variable " ) ;
variable_tag . push_attribute ( ( "name" , variable . as_str ( ) ) ) ;
variable_tag . push_attribute ( ( "name" , variable . as_str ( ) ) ) ;
writer . write_event ( Event ::Empty ( variable_tag ) ) ? ;
writer
. write_event ( Event ::Empty ( variable_tag ) )
. map_err ( map_xml_error ) ? ;
}
}
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" head " ) ) ) ? ;
writer
writer . write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" results " ) ) ) ? ;
. write_event ( Event ::End ( BytesEnd ::borrowed ( b" head " ) ) )
. map_err ( map_xml_error ) ? ;
writer
. write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" results " ) ) )
. map_err ( map_xml_error ) ? ;
for solution in solutions {
for solution in solutions {
let solution = solution ? ;
let solution = solution ? ;
writer . write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" result " ) ) ) ? ;
writer
. write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" result " ) ) )
. map_err ( map_xml_error ) ? ;
for ( variable , value ) in solution . iter ( ) {
for ( variable , value ) in solution . iter ( ) {
let mut binding_tag = BytesStart ::borrowed_name ( b" binding " ) ;
let mut binding_tag = BytesStart ::borrowed_name ( b" binding " ) ;
binding_tag . push_attribute ( ( "name" , variable . as_str ( ) ) ) ;
binding_tag . push_attribute ( ( "name" , variable . as_str ( ) ) ) ;
writer . write_event ( Event ::Start ( binding_tag ) ) ? ;
writer
. write_event ( Event ::Start ( binding_tag ) )
. map_err ( map_xml_error ) ? ;
match value {
match value {
Term ::NamedNode ( uri ) = > {
Term ::NamedNode ( uri ) = > {
writer . write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" uri " ) ) ) ? ;
writer
writer . write_event ( Event ::Text ( BytesText ::from_plain_str (
. write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" uri " ) ) )
uri . as_str ( ) ,
. map_err ( map_xml_error ) ? ;
) ) ) ? ;
writer
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" uri " ) ) ) ? ;
. write_event ( Event ::Text ( BytesText ::from_plain_str ( uri . as_str ( ) ) ) )
. map_err ( map_xml_error ) ? ;
writer
. write_event ( Event ::End ( BytesEnd ::borrowed ( b" uri " ) ) )
. map_err ( map_xml_error ) ? ;
}
}
Term ::BlankNode ( bnode ) = > {
Term ::BlankNode ( bnode ) = > {
writer
writer
. write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" bnode " ) ) ) ? ;
. write_event ( Event ::Start ( BytesStart ::borrowed_name ( b" bnode " ) ) )
writer . write_event ( Event ::Text ( BytesText ::from_plain_str (
. map_err ( map_xml_error ) ? ;
bnode . as_str ( ) ,
writer
) ) ) ? ;
. write_event ( Event ::Text ( BytesText ::from_plain_str ( bnode . as_str ( ) ) ) )
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" bnode " ) ) ) ? ;
. map_err ( map_xml_error ) ? ;
writer
. write_event ( Event ::End ( BytesEnd ::borrowed ( b" bnode " ) ) )
. map_err ( map_xml_error ) ? ;
}
}
Term ::Literal ( literal ) = > {
Term ::Literal ( literal ) = > {
let mut literal_tag = BytesStart ::borrowed_name ( b" literal " ) ;
let mut literal_tag = BytesStart ::borrowed_name ( b" literal " ) ;
if let Some ( language ) = literal . language ( ) {
if let Some ( language ) = literal . language ( ) {
literal_tag . push_attribute ( ( "xml:lang" , language ) ) ;
literal_tag . push_attribute ( ( "xml:lang" , language ) ) ;
} else if ! literal . is_plain ( ) {
} else if ! literal . is_plain ( ) {
literal_tag
literal_tag . push_attribute ( ( "datatype" , literal . datatype ( ) . as_str ( ) ) ) ;
. push_attribute ( ( "datatype" , literal . datatype ( ) . as_str ( ) ) ) ;
}
}
writer . write_event ( Event ::Start ( literal_tag ) ) ? ;
writer
writer . write_event ( Event ::Text ( BytesText ::from_plain_str (
. write_event ( Event ::Start ( literal_tag ) )
literal . value ( ) ,
. map_err ( map_xml_error ) ? ;
) ) ) ? ;
writer
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" literal " ) ) ) ? ;
. write_event ( Event ::Text ( BytesText ::from_plain_str ( literal . value ( ) ) ) )
}
. map_err ( map_xml_error ) ? ;
}
writer
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" binding " ) ) ) ? ;
. write_event ( Event ::End ( BytesEnd ::borrowed ( b" literal " ) ) )
}
. map_err ( map_xml_error ) ? ;
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" result " ) ) ) ? ;
}
}
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" results " ) ) ) ? ;
writer . write_event ( Event ::End ( BytesEnd ::borrowed ( b" sparql " ) ) ) ? ;
}
}
QueryResult ::Graph ( _ ) = > {
writer
return Err ( Error ::msg (
. write_event ( Event ::End ( BytesEnd ::borrowed ( b" binding " ) ) )
"Graphs could not be formatted to SPARQL query results XML format" ,
. map_err ( map_xml_error ) ? ;
) ) ;
}
}
writer
. write_event ( Event ::End ( BytesEnd ::borrowed ( b" result " ) ) )
. map_err ( map_xml_error ) ? ;
}
}
writer
. write_event ( Event ::End ( BytesEnd ::borrowed ( b" results " ) ) )
. map_err ( map_xml_error ) ? ;
writer
. write_event ( Event ::End ( BytesEnd ::borrowed ( b" sparql " ) ) )
. map_err ( map_xml_error ) ? ;
Ok ( ( ) )
Ok ( ( ) )
}
}
pub fn read_xml_results ( source : impl BufRead + ' static ) -> Result < QueryResult > {
pub fn read_xml_results ( source : impl BufRead + ' static ) -> Result < QueryResult , EvaluationError > {
enum State {
enum State {
Start ,
Start ,
Sparql ,
Sparql ,
@ -123,13 +168,16 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result<QueryResult> {
//Read header
//Read header
loop {
loop {
let event = {
let event = {
let ( ns , event ) = reader . read_namespaced_event ( & mut buffer , & mut namespace_buffer ) ? ;
let ( ns , event ) = reader
. read_namespaced_event ( & mut buffer , & mut namespace_buffer )
. map_err ( map_xml_error ) ? ;
if let Some ( ns ) = ns {
if let Some ( ns ) = ns {
if ns ! = b" http://www.w3.org/2005/sparql-results# " . as_ref ( ) {
if ns ! = b" http://www.w3.org/2005/sparql-results# " . as_ref ( ) {
return Err ( Error ::msg ( format! (
return Err ( invalid_data_error ( format! (
"Unexpected namespace found in RDF/XML query result: {}" ,
"Unexpected namespace found in RDF/XML query result: {}" ,
reader . decode ( ns ) ?
reader . decode ( ns ) . map_err ( map_xml_error ) ?
) ) ) ;
) )
. into ( ) ) ;
}
}
}
}
event
event
@ -140,14 +188,14 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result<QueryResult> {
if event . name ( ) = = b" sparql " {
if event . name ( ) = = b" sparql " {
state = State ::Sparql ;
state = State ::Sparql ;
} else {
} else {
return Err ( Error ::msg ( format! ( "Expecting <sparql> tag, found {}" , reader . decode ( event . name ( ) ) ? ) ) ) ;
return Err ( invalid_data_error ( format! ( "Expecting <sparql> tag, found {}" , reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ? ) ) . into ( ) ) ;
}
}
}
}
State ::Sparql = > {
State ::Sparql = > {
if event . name ( ) = = b" head " {
if event . name ( ) = = b" head " {
state = State ::Head ;
state = State ::Head ;
} else {
} else {
return Err ( Error ::msg ( format! ( "Expecting <head> tag, found {}" , reader . decode ( event . name ( ) ) ? ) ) ) ;
return Err ( invalid_data_error ( format! ( "Expecting <head> tag, found {}" , reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ? ) ) . into ( ) ) ;
}
}
}
}
State ::Head = > {
State ::Head = > {
@ -155,12 +203,12 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result<QueryResult> {
let name = event . attributes ( )
let name = event . attributes ( )
. filter_map ( | attr | attr . ok ( ) )
. filter_map ( | attr | attr . ok ( ) )
. find ( | attr | attr . key = = b" name " )
. find ( | attr | attr . key = = b" name " )
. ok_or_else ( | | Error ::msg ( "No name attribute found for the <variable> tag" ) ) ? ;
. ok_or_else ( | | invalid_data_error ( "No name attribute found for the <variable> tag" ) ) ? ;
variables . push ( name . unescape_and_decode_value ( & reader ) ? ) ;
variables . push ( name . unescape_and_decode_value ( & reader ) . map_err ( map_xml_error ) ? ) ;
} else if event . name ( ) = = b" link " {
} else if event . name ( ) = = b" link " {
// no op
// no op
} else {
} else {
return Err ( Error ::msg ( format! ( "Expecting <variable> or <link> tag, found {}" , reader . decode ( event . name ( ) ) ? ) ) ) ;
return Err ( invalid_data_error ( format! ( "Expecting <variable> or <link> tag, found {}" , reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ? ) ) . into ( ) ) ;
}
}
}
}
State ::AfterHead = > {
State ::AfterHead = > {
@ -181,17 +229,17 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result<QueryResult> {
} ) ,
} ) ,
) ) ) ;
) ) ) ;
} else if event . name ( ) ! = b" link " & & event . name ( ) ! = b" results " & & event . name ( ) ! = b" boolean " {
} else if event . name ( ) ! = b" link " & & event . name ( ) ! = b" results " & & event . name ( ) ! = b" boolean " {
return Err ( Error ::msg ( format! ( "Expecting sparql tag, found {}" , reader . decode ( event . name ( ) ) ? ) ) ) ;
return Err ( invalid_data_error ( format! ( "Expecting sparql tag, found {}" , reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ? ) ) . into ( ) ) ;
}
}
}
}
State ::Boolean = > return Err ( Error ::msg ( format! ( "Unexpected tag inside of <boolean> tag: {}" , reader . decode ( event . name ( ) ) ? ) ) )
State ::Boolean = > return Err ( invalid_data_error ( format! ( "Unexpected tag inside of <boolean> tag: {}" , reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ? ) ) . into ( ) )
} ,
} ,
Event ::Empty ( event ) = > match state {
Event ::Empty ( event ) = > match state {
State ::Sparql = > {
State ::Sparql = > {
if event . name ( ) = = b" head " {
if event . name ( ) = = b" head " {
state = State ::AfterHead ;
state = State ::AfterHead ;
} else {
} else {
return Err ( Error ::msg ( format! ( "Expecting <head> tag, found {}" , reader . decode ( event . name ( ) ) ? ) ) ) ;
return Err ( invalid_data_error ( format! ( "Expecting <head> tag, found {}" , reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ? ) ) . into ( ) ) ;
}
}
}
}
State ::Head = > {
State ::Head = > {
@ -199,12 +247,12 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result<QueryResult> {
let name = event . attributes ( )
let name = event . attributes ( )
. filter_map ( | v | v . ok ( ) )
. filter_map ( | v | v . ok ( ) )
. find ( | attr | attr . key = = b" name " )
. find ( | attr | attr . key = = b" name " )
. ok_or_else ( | | Error ::msg ( "No name attribute found for the <variable> tag" ) ) ? ;
. ok_or_else ( | | invalid_data_error ( "No name attribute found for the <variable> tag" ) ) ? ;
variables . push ( name . unescape_and_decode_value ( & reader ) ? ) ;
variables . push ( name . unescape_and_decode_value ( & reader ) . map_err ( map_xml_error ) ? ) ;
} else if event . name ( ) = = b" link " {
} else if event . name ( ) = = b" link " {
// no op
// no op
} else {
} else {
return Err ( Error ::msg ( format! ( "Expecting <variable> or <link> tag, found {}" , reader . decode ( event . name ( ) ) ? ) ) ) ;
return Err ( invalid_data_error ( format! ( "Expecting <variable> or <link> tag, found {}" , reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ? ) ) . into ( ) ) ;
}
}
} ,
} ,
State ::AfterHead = > {
State ::AfterHead = > {
@ -214,13 +262,13 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result<QueryResult> {
Box ::new ( empty ( ) ) ,
Box ::new ( empty ( ) ) ,
) ) )
) ) )
} else {
} else {
return Err ( Error ::msg ( format! ( "Unexpected autoclosing tag <{}>" , reader . decode ( event . name ( ) ) ? ) ) )
return Err ( invalid_data_error ( format! ( "Unexpected autoclosing tag <{}>" , reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ? ) ) . into ( ) )
}
}
}
}
_ = > return Err ( Error ::msg ( format! ( "Unexpected autoclosing tag <{}>" , reader . decode ( event . name ( ) ) ? ) ) )
_ = > return Err ( invalid_data_error ( format! ( "Unexpected autoclosing tag <{}>" , reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ? ) ) . into ( ) )
} ,
} ,
Event ::Text ( event ) = > {
Event ::Text ( event ) = > {
let value = event . unescaped ( ) ? ;
let value = event . unescaped ( ) . map_err ( map_xml_error ) ? ;
return match state {
return match state {
State ::Boolean = > {
State ::Boolean = > {
return if value . as_ref ( ) = = b" true " {
return if value . as_ref ( ) = = b" true " {
@ -228,18 +276,18 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result<QueryResult> {
} else if value . as_ref ( ) = = b" false " {
} else if value . as_ref ( ) = = b" false " {
Ok ( QueryResult ::Boolean ( false ) )
Ok ( QueryResult ::Boolean ( false ) )
} else {
} else {
Err ( Error ::msg ( format! ( "Unexpected boolean value. Found {}" , reader . decode ( & value ) ? ) ) )
Err ( invalid_data_error ( format! ( "Unexpected boolean value. Found {}" , reader . decode ( & value ) . map_err ( map_xml_error ) ? ) ) . into ( ) )
} ;
} ;
}
}
_ = > Err ( Error ::msg ( format! ( "Unexpected textual value found: {}" , reader . decode ( & value ) ? ) ) )
_ = > Err ( invalid_data_error ( format! ( "Unexpected textual value found: {}" , reader . decode ( & value ) . map_err ( map_xml_error ) ? ) ) . into ( ) )
} ;
} ;
} ,
} ,
Event ::End ( _ ) = > if let State ::Head = state {
Event ::End ( _ ) = > if let State ::Head = state {
state = State ::AfterHead ;
state = State ::AfterHead ;
} else {
} else {
return Err ( Error ::msg ( "Unexpected early file end. All results file should have a <head> and a <result> or <boolean> tag" ) ) ;
return Err ( invalid_data_error ( "Unexpected early file end. All results file should have a <head> and a <result> or <boolean> tag" ) . into ( ) ) ;
} ,
} ,
Event ::Eof = > return Err ( Error ::msg ( "Unexpected early file end. All results file should have a <head> and a <result> or <boolean> tag" ) ) ,
Event ::Eof = > return Err ( invalid_data_error ( "Unexpected early file end. All results file should have a <head> and a <result> or <boolean> tag" ) . into ( ) ) ,
_ = > ( ) ,
_ = > ( ) ,
}
}
}
}
@ -253,15 +301,15 @@ struct ResultsIterator<R: BufRead> {
}
}
impl < R : BufRead > Iterator for ResultsIterator < R > {
impl < R : BufRead > Iterator for ResultsIterator < R > {
type Item = Result < Vec < Option < Term > > > ;
type Item = Result < Vec < Option < Term > > , EvaluationError > ;
fn next ( & mut self ) -> Option < Result < Vec < Option < Term > > > > {
fn next ( & mut self ) -> Option < Result < Vec < Option < Term > > , EvaluationError > > {
self . read_next ( ) . transpose ( )
self . read_next ( ) . transpose ( )
}
}
}
}
impl < R : BufRead > ResultsIterator < R > {
impl < R : BufRead > ResultsIterator < R > {
fn read_next ( & mut self ) -> Result < Option < Vec < Option < Term > > > > {
fn read_next ( & mut self ) -> Result < Option < Vec < Option < Term > > > , EvaluationError > {
enum State {
enum State {
Start ,
Start ,
Result ,
Result ,
@ -283,13 +331,15 @@ impl<R: BufRead> ResultsIterator<R> {
loop {
loop {
let ( ns , event ) = self
let ( ns , event ) = self
. reader
. reader
. read_namespaced_event ( & mut self . buffer , & mut self . namespace_buffer ) ? ;
. read_namespaced_event ( & mut self . buffer , & mut self . namespace_buffer )
. map_err ( map_xml_error ) ? ;
if let Some ( ns ) = ns {
if let Some ( ns ) = ns {
if ns ! = b" http://www.w3.org/2005/sparql-results# " . as_ref ( ) {
if ns ! = b" http://www.w3.org/2005/sparql-results# " . as_ref ( ) {
return Err ( Error ::msg ( format! (
return Err ( invalid_data_error ( format! (
"Unexpected namespace found in RDF/XML query result: {}" ,
"Unexpected namespace found in RDF/XML query result: {}" ,
self . reader . decode ( ns ) ?
self . reader . decode ( ns ) . map_err ( map_xml_error ) ?
) ) ) ;
) )
. into ( ) ) ;
}
}
}
}
match event {
match event {
@ -298,10 +348,11 @@ impl<R: BufRead> ResultsIterator<R> {
if event . name ( ) = = b" result " {
if event . name ( ) = = b" result " {
state = State ::Result ;
state = State ::Result ;
} else {
} else {
return Err ( Error ::msg ( format! (
return Err ( invalid_data_error ( format! (
"Expecting <result>, found {}" ,
"Expecting <result>, found {}" ,
self . reader . decode ( event . name ( ) ) ?
self . reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ?
) ) ) ;
) )
. into ( ) ) ;
}
}
}
}
State ::Result = > {
State ::Result = > {
@ -311,26 +362,33 @@ impl<R: BufRead> ResultsIterator<R> {
. filter_map ( | v | v . ok ( ) )
. filter_map ( | v | v . ok ( ) )
. find ( | attr | attr . key = = b" name " )
. find ( | attr | attr . key = = b" name " )
{
{
Some ( attr ) = > current_var = Some ( attr . unescaped_value ( ) ? . to_vec ( ) ) ,
Some ( attr ) = > {
current_var = Some (
attr . unescaped_value ( ) . map_err ( map_xml_error ) ? . to_vec ( ) ,
)
}
None = > {
None = > {
return Err ( Error ::msg (
return Err ( invalid_data_error (
"No name attribute found for the <binding> tag" ,
"No name attribute found for the <binding> tag" ,
) ) ;
)
. into ( ) ) ;
}
}
}
}
state = State ::Binding ;
state = State ::Binding ;
} else {
} else {
return Err ( Error ::msg ( format! (
return Err ( invalid_data_error ( format! (
"Expecting <binding>, found {}" ,
"Expecting <binding>, found {}" ,
self . reader . decode ( event . name ( ) ) ?
self . reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ?
) ) ) ;
) )
. into ( ) ) ;
}
}
}
}
State ::Binding = > {
State ::Binding = > {
if term . is_some ( ) {
if term . is_some ( ) {
return Err ( Error ::msg (
return Err ( invalid_data_error (
"There is already a value for the current binding" ,
"There is already a value for the current binding" ,
) ) ;
)
. into ( ) ) ;
}
}
if event . name ( ) = = b" uri " {
if event . name ( ) = = b" uri " {
state = State ::Uri ;
state = State ::Uri ;
@ -340,37 +398,67 @@ impl<R: BufRead> ResultsIterator<R> {
for attr in event . attributes ( ) {
for attr in event . attributes ( ) {
if let Ok ( attr ) = attr {
if let Ok ( attr ) = attr {
if attr . key = = b" xml:lang " {
if attr . key = = b" xml:lang " {
lang = Some ( attr . unescape_and_decode_value ( & self . reader ) ? ) ;
lang = Some (
attr . unescape_and_decode_value ( & self . reader )
. map_err ( map_xml_error ) ? ,
) ;
} else if attr . key = = b" datatype " {
} else if attr . key = = b" datatype " {
datatype = Some ( NamedNode ::new (
let iri = attr
attr . unescape_and_decode_value ( & self . reader ) ? ,
. unescape_and_decode_value ( & self . reader )
) ? ) ;
. map_err ( map_xml_error ) ? ;
datatype = Some ( NamedNode ::new ( & iri ) . map_err ( | e | {
invalid_data_error ( format! (
"Invalid datatype IRI '{}': {}" ,
iri , e
) )
} ) ? ) ;
}
}
}
}
}
}
state = State ::Literal ;
state = State ::Literal ;
} else {
} else {
return Err ( Error ::msg ( format! (
return Err ( invalid_data_error ( format! (
"Expecting <uri>, <bnode> or <literal> found {}" ,
"Expecting <uri>, <bnode> or <literal> found {}" ,
self . reader . decode ( event . name ( ) ) ?
self . reader . decode ( event . name ( ) ) . map_err ( map_xml_error ) ?
) ) ) ;
) )
. into ( ) ) ;
}
}
}
}
_ = > ( ) ,
_ = > ( ) ,
} ,
} ,
Event ::Text ( event ) = > {
Event ::Text ( event ) = > {
let data = event . unescaped ( ) ? ;
let data = event . unescaped ( ) . map_err ( map_xml_error ) ? ;
match state {
match state {
State ::Uri = > {
State ::Uri = > {
term = Some ( NamedNode ::new ( self . reader . decode ( & data ) ? ) ? . into ( ) )
let iri = self . reader . decode ( & data ) . map_err ( map_xml_error ) ? ;
term = Some (
NamedNode ::new ( iri )
. map_err ( | e | {
invalid_data_error ( format! (
"Invalid IRI value '{}': {}" ,
iri , e
) )
} ) ?
. into ( ) ,
)
}
}
State ::BNode = > {
State ::BNode = > {
term = Some ( BlankNode ::new ( self . reader . decode ( & data ) ? ) ? . into ( ) )
let bnode = self . reader . decode ( & data ) . map_err ( map_xml_error ) ? ;
term = Some (
BlankNode ::new ( bnode )
. map_err ( | e | {
invalid_data_error ( format! (
"Invalid blank node value '{}': {}" ,
bnode , e
) )
} ) ?
. into ( ) ,
)
}
}
State ::Literal = > {
State ::Literal = > {
term = Some (
term = Some (
build_literal (
build_literal (
self . reader . decode ( & data ) ? ,
self . reader . decode ( & data ) . map_err ( map_xml_error ) ? ,
lang . take ( ) ,
lang . take ( ) ,
datatype . take ( ) ,
datatype . take ( ) ,
) ?
) ?
@ -378,10 +466,11 @@ impl<R: BufRead> ResultsIterator<R> {
) ;
) ;
}
}
_ = > {
_ = > {
return Err ( Error ::msg ( format! (
return Err ( invalid_data_error ( format! (
"Unexpected textual value found: {}" ,
"Unexpected textual value found: {}" ,
self . reader . decode ( & data ) ?
self . reader . decode ( & data ) . map_err ( map_xml_error ) ?
) ) ) ;
) )
. into ( ) ) ;
}
}
}
}
}
}
@ -392,7 +481,9 @@ impl<R: BufRead> ResultsIterator<R> {
if let Some ( var ) = & current_var {
if let Some ( var ) = & current_var {
new_bindings [ self . mapping [ var ] ] = term . clone ( )
new_bindings [ self . mapping [ var ] ] = term . clone ( )
} else {
} else {
return Err ( Error ::msg ( "No name found for <binding> tag" ) ) ;
return Err (
invalid_data_error ( "No name found for <binding> tag" ) . into ( )
) ;
}
}
term = None ;
term = None ;
state = State ::Result ;
state = State ::Result ;
@ -418,12 +509,22 @@ fn build_literal(
value : impl Into < String > ,
value : impl Into < String > ,
lang : Option < String > ,
lang : Option < String > ,
datatype : Option < NamedNode > ,
datatype : Option < NamedNode > ,
) -> Result < Literal > {
) -> Result < Literal , EvaluationError > {
match datatype {
match datatype {
Some ( datatype ) = > Ok ( Literal ::new_typed_literal ( value , datatype ) ) ,
Some ( datatype ) = > Ok ( Literal ::new_typed_literal ( value , datatype ) ) ,
None = > match lang {
None = > match lang {
Some ( lang ) = > Ok ( Literal ::new_language_tagged_literal ( value , lang ) ? ) ,
Some ( lang ) = > Literal ::new_language_tagged_literal ( value , & lang ) . map_err ( | e | {
invalid_data_error ( format! ( "Invalid xml:lang value '{}': {}" , lang , e ) ) . into ( )
} ) ,
None = > Ok ( Literal ::new_simple_literal ( value ) ) ,
None = > Ok ( Literal ::new_simple_literal ( value ) ) ,
} ,
} ,
}
}
}
}
fn map_xml_error ( error : quick_xml ::Error ) -> EvaluationError {
match error {
quick_xml ::Error ::Io ( error ) = > error ,
_ = > invalid_data_error ( error ) ,
}
. into ( )
}