Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F25451364
sparql.rs
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
3 KB
Referenced Files
None
Subscribers
None
sparql.rs
View Options
//! # SPARQL client
use
std
::
collections
::
HashMap
;
use
std
::
io
::
BufRead
;
use
oxrdf
::
Term
;
use
reqwest
::
header
::
{
HeaderMap
,
HeaderValue
};
use
reqwest
::
Url
;
use
sparesults
::
*
;
use
crate
::
services
::
http_client
::
Client
as
HttpClient
;
type
SparqlSolution
=
HashMap
<
String
,
Term
>
;
/// SPARQL client
pub
struct
Client
{
pub
endpoint
:
String
,
http_client
:
HttpClient
,
}
/// Represent results for a SPARQL query
/// A query can return a collection of solutions or a boolean.
pub
enum
SparqlResults
{
/// Results for SELECT queries
Solutions
(
Vec
<
SparqlSolution
>
),
/// Results for INSERT DATA, UPDATE DATA, etc. queries
Boolean
(
bool
),
}
impl
Client
{
pub
fn
new
(
endpoint
:
&
str
)
->
Self
{
let
mut
headers
=
HeaderMap
::
new
();
headers
.
insert
(
"Accept"
,
HeaderValue
::
from_static
(
"Accept: application/sparql-results+xml"
));
Self
{
endpoint
:
String
::
from
(
endpoint
),
http_client
:
HttpClient
::
new
(
Some
(
headers
)),
}
}
pub
async
fn
query
(
&
self
,
query
:
&
str
)
->
SparqlResults
{
let
url
=
Url
::
parse_with_params
(
&
self
.
endpoint
,
&
[(
"query"
,
query
)])
.
expect
(
"Can't parse endpoint as absolute URL."
);
let
query_results
=
self
.
http_client
.
get
(
url
).
await
.
expect
(
"Can't query endpoint"
)
.
text
().
await
.
expect
(
"End-point didn't return a reply."
);
parse_sparql_results
(
&
query_results
)
}
}
pub
fn
parse_sparql_results
(
query_results
:
&
str
)
->
SparqlResults
{
let
results_reader
=
get_query_results_xml_reader
(
query_results
.
as_bytes
());
SparqlResults
::
read
(
results_reader
)
}
impl
SparqlResults
{
pub
fn
read
<
T
>
(
reader
:
QueryResultsReader
<
T
>
)
->
Self
where
T
:
BufRead
{
match
reader
{
QueryResultsReader
::
Solutions
(
solutions
)
=>
{
Self
::
Solutions
(
parse_sparql_solutions
(
solutions
))
},
QueryResultsReader
::
Boolean
(
bool
)
=>
Self
::
Boolean
(
bool
),
}
}
pub
fn
into_solutions
(
self
)
->
Option
<
Vec
<
SparqlSolution
>>
{
match
self
{
SparqlResults
::
Solutions
(
solutions
)
=>
Some
(
solutions
),
SparqlResults
::
Boolean
(
_
)
=>
None
,
}
}
}
fn
get_query_results_xml_reader
<
T
>
(
reader
:
T
)
->
QueryResultsReader
<
T
>
where
T
:
BufRead
{
QueryResultsParser
::
from_format
(
QueryResultsFormat
::
Xml
)
.
read_results
(
reader
)
.
expect
(
"Can't read SPARQL results"
)
}
fn
parse_sparql_solutions
<
T
>
(
solutions
:
SolutionsReader
<
T
>
)
->
Vec
<
SparqlSolution
>
where
T
:
BufRead
{
solutions
.
map
(
|
solution
|
{
parse_sparql_result
(
solution
.
expect
(
"Can't read solution"
)
)
})
.
collect
()
}
pub
fn
parse_sparql_result
(
solution
:
QuerySolution
)
->
SparqlSolution
{
solution
.
iter
()
.
map
(
|
(
variable
,
term
)
|
(
variable
.
as_str
().
to_string
(),
term
.
clone
(),
))
.
collect
()
}
pub
fn
parse_term_uri
(
term
:
&
Term
)
->
Option
<
String
>
{
if
let
Term
::
NamedNode
(
node
)
=
term
{
Some
(
node
.
as_str
().
to_string
())
}
else
{
None
}
}
pub
fn
parse_literal
(
term
:
&
Term
)
->
Option
<
String
>
{
if
let
Term
::
Literal
(
literal
)
=
term
{
Some
(
literal
.
value
().
to_string
())
}
else
{
None
}
}
pub
fn
is_term_empty
(
term
:
&
Term
)
->
bool
{
match
term
{
Term
::
NamedNode
(
node
)
=>
{
// Special values IRI are considered as empty values.
node
.
as_str
().
contains
(
"/.well-known/genid/"
)
}
Term
::
BlankNode
(
_
)
=>
true
,
Term
::
Literal
(
_
)
=>
false
,
}
}
File Metadata
Details
Attached
Mime Type
text/x-asm
Expires
Thu, Apr 16, 05:15 (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3622987
Default Alt Text
sparql.rs (3 KB)
Attached To
Mode
rDS Nasqueron Datasources
Attached
Detach File
Event Timeline
Log In to Comment