Adds extra compiler and Clippy lints

pull/22/head
Tpt 5 years ago
parent e6124c5fe3
commit 7cd5558d2b
  1. 66
      lib/src/lib.rs
  2. 4
      lib/src/model/blank_node.rs
  3. 32
      lib/src/model/graph.rs
  4. 14
      lib/src/model/isomorphism.rs
  5. 14
      lib/src/model/literal.rs
  6. 14
      lib/src/model/triple.rs
  7. 282
      lib/src/model/xsd/date_time.rs
  8. 298
      lib/src/model/xsd/decimal.rs
  9. 137
      lib/src/model/xsd/duration.rs
  10. 45
      lib/src/model/xsd/parser.rs
  11. 4
      lib/src/repository.rs
  12. 81
      lib/src/sparql/algebra.rs
  13. 176
      lib/src/sparql/eval.rs
  14. 22
      lib/src/sparql/mod.rs
  15. 3
      lib/src/sparql/parser.rs
  16. 12
      lib/src/sparql/plan.rs
  17. 45
      lib/src/sparql/plan_builder.rs
  18. 6
      lib/src/sparql/sparql_grammar.rustpeg
  19. 6
      lib/src/sparql/xml_results.rs
  20. 4
      lib/src/store/memory.rs
  21. 16
      lib/src/store/mod.rs
  22. 28
      lib/src/store/numeric_encoder.rs
  23. 14
      lib/src/store/rocksdb.rs

@ -34,6 +34,70 @@
//! } //! }
//! # Result::Ok(()) //! # Result::Ok(())
//! ``` //! ```
#![deny(
future_incompatible,
nonstandard_style,
//TODO rust_2018_idioms,
missing_copy_implementations,
trivial_casts,
trivial_numeric_casts,
//TODO unsafe_code,
unused_qualifications
)]
#![warn(
clippy::unimplemented,
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_precision_loss,
clippy::cast_sign_loss,
clippy::checked_conversions,
clippy::decimal_literal_representation,
//TODO clippy::doc_markdown,
clippy::empty_enum,
clippy::expl_impl_clone_on_copy,
clippy::explicit_into_iter_loop,
clippy::explicit_iter_loop,
//TODO clippy::fallible_impl_from,
clippy::filter_map,
clippy::filter_map_next,
clippy::find_map,
clippy::get_unwrap,
clippy::if_not_else,
clippy::inline_always,
clippy::invalid_upcast_comparisons,
clippy::items_after_statements,
clippy::map_flatten,
//TODO clippy::match_same_arms,
clippy::maybe_infinite_iter,
clippy::mem_forget,
clippy::multiple_inherent_impl,
clippy::mut_mut,
clippy::needless_borrow,
clippy::needless_continue,
clippy::needless_pass_by_value,
clippy::non_ascii_literal,
clippy::option_map_unwrap_or,
clippy::option_map_unwrap_or_else,
clippy::path_buf_push_overwrite,
clippy::print_stdout,
clippy::pub_enum_variant_names,
//TODO clippy::redundant_closure_for_method_calls,
clippy::replace_consts,
clippy::result_map_unwrap_or_else,
// clippy::shadow_reuse,
// clippy::shadow_same,
// clippy::shadow_unrelated,
// clippy::single_match_else,
clippy::string_add,
clippy::string_add_assign,
clippy::type_repetition_in_bounds,
clippy::unicode_not_nfc,
//TODO clippy::unseparated_literal_suffix,
clippy::used_underscore_binding,
clippy::wildcard_dependencies,
clippy::wrong_pub_self_convention,
)]
pub mod model; pub mod model;
mod repository; mod repository;
@ -42,7 +106,7 @@ pub(crate) mod store;
mod syntax; mod syntax;
pub use failure::Error; pub use failure::Error;
pub type Result<T> = ::std::result::Result<T, failure::Error>; pub type Result<T> = ::std::result::Result<T, Error>;
pub use crate::repository::Repository; pub use crate::repository::Repository;
pub use crate::repository::RepositoryConnection; pub use crate::repository::RepositoryConnection;
pub use crate::repository::RepositoryTransaction; pub use crate::repository::RepositoryTransaction;

@ -14,7 +14,7 @@ use std::str;
/// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation. /// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation.
/// `BlankNode::default().to_string()` should return something like `_:00112233445566778899aabbccddeeff` /// `BlankNode::default().to_string()` should return something like `_:00112233445566778899aabbccddeeff`
/// ///
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
pub struct BlankNode { pub struct BlankNode {
id: u128, id: u128,
str: [u8; 32], str: [u8; 32],
@ -34,7 +34,7 @@ impl BlankNode {
} }
/// Returns the underlying ID of this blank node /// Returns the underlying ID of this blank node
pub(crate) fn id(&self) -> u128 { pub(crate) const fn id(&self) -> u128 {
self.id self.id
} }
} }

@ -43,9 +43,13 @@ impl SimpleGraph {
subject: &'a NamedOrBlankNode, subject: &'a NamedOrBlankNode,
predicate: &'a NamedNode, predicate: &'a NamedNode,
) -> impl Iterator<Item = &Term> + 'a { ) -> impl Iterator<Item = &Term> + 'a {
self.iter() self.iter().filter_map(move |t| {
.filter(move |t| t.subject() == subject && t.predicate() == predicate) if t.subject() == subject && t.predicate() == predicate {
.map(|t| t.object()) Some(t.object())
} else {
None
}
})
} }
pub fn object_for_subject_predicate<'a>( pub fn object_for_subject_predicate<'a>(
@ -62,9 +66,13 @@ impl SimpleGraph {
subject: &'a NamedOrBlankNode, subject: &'a NamedOrBlankNode,
object: &'a Term, object: &'a Term,
) -> impl Iterator<Item = &NamedNode> + 'a { ) -> impl Iterator<Item = &NamedNode> + 'a {
self.iter() self.iter().filter_map(move |t| {
.filter(move |t| t.subject() == subject && t.object() == object) if t.subject() == subject && t.object() == object {
.map(|t| t.predicate()) Some(t.predicate())
} else {
None
}
})
} }
pub fn triples_for_predicate<'a>( pub fn triples_for_predicate<'a>(
@ -79,9 +87,13 @@ impl SimpleGraph {
predicate: &'a NamedNode, predicate: &'a NamedNode,
object: &'a Term, object: &'a Term,
) -> impl Iterator<Item = &NamedOrBlankNode> + 'a { ) -> impl Iterator<Item = &NamedOrBlankNode> + 'a {
self.iter() self.iter().filter_map(move |t| {
.filter(move |t| t.predicate() == predicate && t.object() == object) if t.predicate() == predicate && t.object() == object {
.map(|t| t.subject()) Some(t.subject())
} else {
None
}
})
} }
pub fn triples_for_object<'a>( pub fn triples_for_object<'a>(
@ -157,7 +169,7 @@ impl Extend<Triple> for SimpleGraph {
} }
impl fmt::Display for SimpleGraph { impl fmt::Display for SimpleGraph {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for t in &self.triples { for t in &self.triples {
writeln!(f, "{}", t)?; writeln!(f, "{}", t)?;
} }

@ -48,7 +48,7 @@ fn split_hash_buckets<'a>(
new_bnodes_by_hash.insert(hash, bnodes); // Nothing to improve new_bnodes_by_hash.insert(hash, bnodes); // Nothing to improve
} else { } else {
for bnode in bnodes { for bnode in bnodes {
let mut starts = vec![NamedOrBlankNode::from(bnode.clone())]; let mut starts = vec![NamedOrBlankNode::from(*bnode)];
for _ in 0..distance { for _ in 0..distance {
let mut new_starts = Vec::default(); let mut new_starts = Vec::default();
for s in starts { for s in starts {
@ -71,7 +71,7 @@ fn split_hash_buckets<'a>(
hash.hash(&mut hasher); // We start with the previous hash hash.hash(&mut hasher); // We start with the previous hash
// NB: we need to sort the triples to have the same hash // NB: we need to sort the triples to have the same hash
let mut po_set: BTreeSet<PredicateObject> = BTreeSet::default(); let mut po_set: BTreeSet<PredicateObject<'_>> = BTreeSet::default();
for start in &starts { for start in &starts {
for po in predicate_objects_for_subject(graph, start) { for po in predicate_objects_for_subject(graph, start) {
match &po.object { match &po.object {
@ -86,7 +86,7 @@ fn split_hash_buckets<'a>(
po.hash(&mut hasher); po.hash(&mut hasher);
} }
let mut sp_set: BTreeSet<SubjectPredicate> = BTreeSet::default(); let mut sp_set: BTreeSet<SubjectPredicate<'_>> = BTreeSet::default();
let term_starts: Vec<_> = starts.into_iter().map(|t| t.into()).collect(); let term_starts: Vec<_> = starts.into_iter().map(|t| t.into()).collect();
for start in &term_starts { for start in &term_starts {
for sp in subject_predicates_for_object(graph, start) { for sp in subject_predicates_for_object(graph, start) {
@ -123,7 +123,7 @@ fn build_and_check_containment_from_hashes<'a>(
) -> bool { ) -> bool {
if let Some((a_node, remaining_a_node)) = current_a_nodes.split_last() { if let Some((a_node, remaining_a_node)) = current_a_nodes.split_last() {
let b_nodes = current_b_nodes.iter().cloned().collect::<Vec<_>>(); let b_nodes = current_b_nodes.iter().cloned().collect::<Vec<_>>();
for b_node in b_nodes.into_iter() { for b_node in b_nodes {
current_b_nodes.remove(b_node); current_b_nodes.remove(b_node);
a_to_b_mapping.insert(a_node, b_node); a_to_b_mapping.insert(a_node, b_node);
if check_is_contained_focused(a_to_b_mapping, a_node, a, b) if check_is_contained_focused(a_to_b_mapping, a_node, a, b)
@ -260,11 +260,7 @@ pub fn are_graphs_isomorphic(a: &SimpleGraph, b: &SimpleGraph) -> bool {
b_bnodes_by_hash.insert(0, graph_blank_nodes(&b_bnodes_triples)); b_bnodes_by_hash.insert(0, graph_blank_nodes(&b_bnodes_triples));
for distance in 0..5 { for distance in 0..5 {
let max_size = a_bnodes_by_hash let max_size = a_bnodes_by_hash.values().map(Vec::len).max().unwrap_or(0);
.values()
.map(|l| l.len())
.max()
.unwrap_or(0);
if max_size < 2 { if max_size < 2 {
break; // We only have small buckets break; // We only have small buckets
} }

@ -275,15 +275,15 @@ impl From<Duration> for Literal {
impl<'a> From<&'a Literal> for rio::Literal<'a> { impl<'a> From<&'a Literal> for rio::Literal<'a> {
fn from(literal: &'a Literal) -> Self { fn from(literal: &'a Literal) -> Self {
if literal.is_plain() { if literal.is_plain() {
literal literal.language().map_or_else(
.language() || rio::Literal::Simple {
.map(|lang| rio::Literal::LanguageTaggedString {
value: literal.value(), value: literal.value(),
language: &lang, },
}) |lang| rio::Literal::LanguageTaggedString {
.unwrap_or_else(|| rio::Literal::Simple {
value: literal.value(), value: literal.value(),
}) language: lang,
},
)
} else { } else {
rio::Literal::Typed { rio::Literal::Typed {
value: literal.value(), value: literal.value(),

@ -162,7 +162,7 @@ impl Triple {
} }
/// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple /// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple
pub fn subject(&self) -> &NamedOrBlankNode { pub const fn subject(&self) -> &NamedOrBlankNode {
&self.subject &self.subject
} }
@ -172,7 +172,7 @@ impl Triple {
} }
/// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple /// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple
pub fn predicate(&self) -> &NamedNode { pub const fn predicate(&self) -> &NamedNode {
&self.predicate &self.predicate
} }
@ -182,7 +182,7 @@ impl Triple {
} }
/// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple /// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple
pub fn object(&self) -> &Term { pub const fn object(&self) -> &Term {
&self.object &self.object
} }
@ -244,7 +244,7 @@ impl Quad {
} }
/// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple /// The [subject](https://www.w3.org/TR/rdf11-concepts/#dfn-subject) of this triple
pub fn subject(&self) -> &NamedOrBlankNode { pub const fn subject(&self) -> &NamedOrBlankNode {
&self.subject &self.subject
} }
@ -254,7 +254,7 @@ impl Quad {
} }
/// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple /// The [predicate](https://www.w3.org/TR/rdf11-concepts/#dfn-predicate) of this triple
pub fn predicate(&self) -> &NamedNode { pub const fn predicate(&self) -> &NamedNode {
&self.predicate &self.predicate
} }
@ -264,7 +264,7 @@ impl Quad {
} }
/// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple /// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple
pub fn object(&self) -> &Term { pub const fn object(&self) -> &Term {
&self.object &self.object
} }
@ -274,7 +274,7 @@ impl Quad {
} }
/// The name of the RDF [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) in which the triple is or None if it is in the [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) /// The name of the RDF [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) in which the triple is or None if it is in the [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph)
pub fn graph_name(&self) -> &Option<NamedOrBlankNode> { pub const fn graph_name(&self) -> &Option<NamedOrBlankNode> {
&self.graph_name &self.graph_name
} }

@ -26,7 +26,7 @@ impl DateTime {
timezone_offset: Option<TimezoneOffset>, timezone_offset: Option<TimezoneOffset>,
) -> Result<Self, DateTimeError> { ) -> Result<Self, DateTimeError> {
Ok(Self { Ok(Self {
timestamp: Timestamp::new(DateTimeSevenPropertyModel { timestamp: Timestamp::new(&DateTimeSevenPropertyModel {
year: Some(year), year: Some(year),
month: Some(month), month: Some(month),
day: Some(day), day: Some(day),
@ -49,56 +49,7 @@ impl DateTime {
timestamp: Timestamp::from_le_bytes(bytes), timestamp: Timestamp::from_le_bytes(bytes),
} }
} }
}
/// Conversion according to [XPath cast rules](https://www.w3.org/TR/xpath-functions/#casting-to-datetimes).
impl From<Date> for DateTime {
fn from(date: Date) -> Self {
DateTime::new(
date.year(),
date.month(),
date.day(),
0,
0,
Decimal::default(),
date.timezone_offset(),
)
.unwrap()
}
}
impl FromStr for DateTime {
type Err = XsdParseError;
fn from_str(input: &str) -> Result<Self, XsdParseError> {
parse_value(date_time_lexical_rep, input)
}
}
impl fmt::Display for DateTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let year = self.year();
if year < 0 {
write!(f, "-")?;
}
write!(
f,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}",
year.abs(),
self.month(),
self.day(),
self.hour(),
self.minute(),
self.second()
)?;
if let Some(timezone_offset) = self.timezone_offset() {
write!(f, "{}", timezone_offset)?;
}
Ok(())
}
}
impl DateTime {
/// [fn:year-from-dateTime](https://www.w3.org/TR/xpath-functions/#func-year-from-dateTime) /// [fn:year-from-dateTime](https://www.w3.org/TR/xpath-functions/#func-year-from-dateTime)
pub fn year(&self) -> i64 { pub fn year(&self) -> i64 {
self.timestamp.year() self.timestamp.year()
@ -168,7 +119,8 @@ impl DateTime {
}) })
} else { } else {
Some(Self { Some(Self {
timestamp: Timestamp::new(date_time_plus_duration(rhs, self.properties())?).ok()?, timestamp: Timestamp::new(&date_time_plus_duration(rhs, &self.properties())?)
.ok()?,
}) })
} }
} }
@ -182,13 +134,60 @@ impl DateTime {
}) })
} else { } else {
Some(Self { Some(Self {
timestamp: Timestamp::new(date_time_plus_duration(-rhs, self.properties())?) timestamp: Timestamp::new(&date_time_plus_duration(-rhs, &self.properties())?)
.ok()?, .ok()?,
}) })
} }
} }
} }
/// Conversion according to [XPath cast rules](https://www.w3.org/TR/xpath-functions/#casting-to-datetimes).
impl From<Date> for DateTime {
fn from(date: Date) -> Self {
DateTime::new(
date.year(),
date.month(),
date.day(),
0,
0,
Decimal::default(),
date.timezone_offset(),
)
.unwrap()
}
}
impl FromStr for DateTime {
type Err = XsdParseError;
fn from_str(input: &str) -> Result<Self, XsdParseError> {
parse_value(date_time_lexical_rep, input)
}
}
impl fmt::Display for DateTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let year = self.year();
if year < 0 {
write!(f, "-")?;
}
write!(
f,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}",
year.abs(),
self.month(),
self.day(),
self.hour(),
self.minute(),
self.second()
)?;
if let Some(timezone_offset) = self.timezone_offset() {
write!(f, "{}", timezone_offset)?;
}
Ok(())
}
}
/// [XML Schema `time` datatype](https://www.w3.org/TR/xmlschema11-2/#time) implementation. /// [XML Schema `time` datatype](https://www.w3.org/TR/xmlschema11-2/#time) implementation.
#[derive(Eq, PartialEq, PartialOrd, Debug, Clone, Copy, Hash)] #[derive(Eq, PartialEq, PartialOrd, Debug, Clone, Copy, Hash)]
pub struct Time { pub struct Time {
@ -206,7 +205,7 @@ impl Time {
hour = 0; hour = 0;
} }
Ok(Self { Ok(Self {
timestamp: Timestamp::new(DateTimeSevenPropertyModel { timestamp: Timestamp::new(&DateTimeSevenPropertyModel {
year: None, year: None,
month: None, month: None,
day: None, day: None,
@ -223,46 +222,7 @@ impl Time {
timestamp: Timestamp::from_le_bytes(bytes), timestamp: Timestamp::from_le_bytes(bytes),
} }
} }
}
/// Conversion according to [XPath cast rules](https://www.w3.org/TR/xpath-functions/#casting-to-datetimes).
impl From<DateTime> for Time {
fn from(date_time: DateTime) -> Self {
Time::new(
date_time.hour(),
date_time.minute(),
date_time.second(),
date_time.timezone_offset(),
)
.unwrap()
}
}
impl FromStr for Time {
type Err = XsdParseError;
fn from_str(input: &str) -> Result<Self, XsdParseError> {
parse_value(time_lexical_rep, input)
}
}
impl fmt::Display for Time {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:02}:{:02}:{:02}",
self.hour(),
self.minute(),
self.second()
)?;
if let Some(timezone_offset) = self.timezone_offset() {
write!(f, "{}", timezone_offset)?;
}
Ok(())
}
}
impl Time {
/// [fn:hour-from-time](https://www.w3.org/TR/xpath-functions/#func-hour-from-time) /// [fn:hour-from-time](https://www.w3.org/TR/xpath-functions/#func-hour-from-time)
pub fn hour(&self) -> u8 { pub fn hour(&self) -> u8 {
self.timestamp.hour() self.timestamp.hour()
@ -335,6 +295,43 @@ impl Time {
} }
} }
/// Conversion according to [XPath cast rules](https://www.w3.org/TR/xpath-functions/#casting-to-datetimes).
impl From<DateTime> for Time {
fn from(date_time: DateTime) -> Self {
Time::new(
date_time.hour(),
date_time.minute(),
date_time.second(),
date_time.timezone_offset(),
)
.unwrap()
}
}
impl FromStr for Time {
type Err = XsdParseError;
fn from_str(input: &str) -> Result<Self, XsdParseError> {
parse_value(time_lexical_rep, input)
}
}
impl fmt::Display for Time {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:02}:{:02}:{:02}",
self.hour(),
self.minute(),
self.second()
)?;
if let Some(timezone_offset) = self.timezone_offset() {
write!(f, "{}", timezone_offset)?;
}
Ok(())
}
}
/// [XML Schema `date` datatype](https://www.w3.org/TR/xmlschema11-2/#date) implementation. /// [XML Schema `date` datatype](https://www.w3.org/TR/xmlschema11-2/#date) implementation.
#[derive(Eq, PartialEq, PartialOrd, Debug, Clone, Copy, Hash)] #[derive(Eq, PartialEq, PartialOrd, Debug, Clone, Copy, Hash)]
pub struct Date { pub struct Date {
@ -349,7 +346,7 @@ impl Date {
timezone_offset: Option<TimezoneOffset>, timezone_offset: Option<TimezoneOffset>,
) -> Result<Self, DateTimeError> { ) -> Result<Self, DateTimeError> {
Ok(Self { Ok(Self {
timestamp: Timestamp::new(DateTimeSevenPropertyModel { timestamp: Timestamp::new(&DateTimeSevenPropertyModel {
year: Some(year), year: Some(year),
month: Some(month), month: Some(month),
day: Some(day), day: Some(day),
@ -366,44 +363,7 @@ impl Date {
timestamp: Timestamp::from_le_bytes(bytes), timestamp: Timestamp::from_le_bytes(bytes),
} }
} }
}
/// Conversion according to [XPath cast rules](https://www.w3.org/TR/xpath-functions/#casting-to-datetimes).
impl From<DateTime> for Date {
fn from(date_time: DateTime) -> Self {
Date::new(
date_time.year(),
date_time.month(),
date_time.day(),
date_time.timezone_offset(),
)
.unwrap()
}
}
impl FromStr for Date {
type Err = XsdParseError;
fn from_str(input: &str) -> Result<Self, XsdParseError> {
parse_value(date_lexical_rep, input)
}
}
impl fmt::Display for Date {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let year = self.year();
if year < 0 {
write!(f, "-")?;
}
write!(f, "{:04}-{:02}-{:02}", year.abs(), self.month(), self.day())?;
if let Some(timezone_offset) = self.timezone_offset() {
write!(f, "{}", timezone_offset)?;
}
Ok(())
}
}
impl Date {
/// [fn:year-from-date](https://www.w3.org/TR/xpath-functions/#func-year-from-date) /// [fn:year-from-date](https://www.w3.org/TR/xpath-functions/#func-year-from-date)
pub fn year(&self) -> i64 { pub fn year(&self) -> i64 {
self.timestamp.year() self.timestamp.year()
@ -448,6 +408,41 @@ impl Date {
} }
} }
/// Conversion according to [XPath cast rules](https://www.w3.org/TR/xpath-functions/#casting-to-datetimes).
impl From<DateTime> for Date {
fn from(date_time: DateTime) -> Self {
Date::new(
date_time.year(),
date_time.month(),
date_time.day(),
date_time.timezone_offset(),
)
.unwrap()
}
}
impl FromStr for Date {
type Err = XsdParseError;
fn from_str(input: &str) -> Result<Self, XsdParseError> {
parse_value(date_lexical_rep, input)
}
}
impl fmt::Display for Date {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let year = self.year();
if year < 0 {
write!(f, "-")?;
}
write!(f, "{:04}-{:02}-{:02}", year.abs(), self.month(), self.day())?;
if let Some(timezone_offset) = self.timezone_offset() {
write!(f, "{}", timezone_offset)?;
}
Ok(())
}
}
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub struct TimezoneOffset { pub struct TimezoneOffset {
offset: i16, // in minute with respect to UTC offset: i16, // in minute with respect to UTC
@ -468,6 +463,10 @@ impl TimezoneOffset {
offset: i16::from_le_bytes(bytes), offset: i16::from_le_bytes(bytes),
} }
} }
pub fn to_le_bytes(self) -> [u8; 2] {
self.offset.to_le_bytes()
}
} }
impl From<i16> for TimezoneOffset { impl From<i16> for TimezoneOffset {
@ -492,12 +491,6 @@ impl fmt::Display for TimezoneOffset {
} }
} }
impl TimezoneOffset {
pub fn to_le_bytes(self) -> [u8; 2] {
self.offset.to_le_bytes()
}
}
/// [The Date/time Seven-property model](https://www.w3.org/TR/xmlschema11-2/#dt-dt-7PropMod) /// [The Date/time Seven-property model](https://www.w3.org/TR/xmlschema11-2/#dt-dt-7PropMod)
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
struct DateTimeSevenPropertyModel { struct DateTimeSevenPropertyModel {
@ -564,7 +557,7 @@ impl Hash for Timestamp {
} }
impl Timestamp { impl Timestamp {
fn new(props: DateTimeSevenPropertyModel) -> Result<Self, DateTimeError> { fn new(props: &DateTimeSevenPropertyModel) -> Result<Self, DateTimeError> {
// Validation // Validation
if let (Some(day), Some(month)) = (props.day, props.month) { if let (Some(day), Some(month)) = (props.day, props.month) {
// Constraint: Day-of-month Values // Constraint: Day-of-month Values
@ -585,14 +578,14 @@ impl Timestamp {
fn now() -> Result<Self, DateTimeError> { fn now() -> Result<Self, DateTimeError> {
Timestamp::new( Timestamp::new(
date_time_plus_duration( &date_time_plus_duration(
SystemTime::now() SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)? .duration_since(SystemTime::UNIX_EPOCH)?
.try_into() .try_into()
.map_err(|_| DateTimeError { .map_err(|_| DateTimeError {
kind: DateTimeErrorKind::Overflow, kind: DateTimeErrorKind::Overflow,
})?, })?,
DateTimeSevenPropertyModel { &DateTimeSevenPropertyModel {
year: Some(1970), year: Some(1970),
month: Some(1), month: Some(1),
day: Some(1), day: Some(1),
@ -624,6 +617,7 @@ impl Timestamp {
} }
} }
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
fn year_month_day(&self) -> (i64, u8, u8) { fn year_month_day(&self) -> (i64, u8, u8) {
let mut days = (self.value.as_i128() let mut days = (self.value.as_i128()
+ i128::from( + i128::from(
@ -697,6 +691,7 @@ impl Timestamp {
day day
} }
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
fn hour(&self) -> u8 { fn hour(&self) -> u8 {
(((self.value.as_i128() (((self.value.as_i128()
+ i128::from( + i128::from(
@ -708,6 +703,7 @@ impl Timestamp {
/ 3600) as u8 / 3600) as u8
} }
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
fn minute(&self) -> u8 { fn minute(&self) -> u8 {
(((self.value.as_i128() (((self.value.as_i128()
+ i128::from( + i128::from(
@ -723,7 +719,7 @@ impl Timestamp {
self.value.checked_rem_euclid(60).unwrap().abs() self.value.checked_rem_euclid(60).unwrap().abs()
} }
fn timezone_offset(&self) -> Option<TimezoneOffset> { const fn timezone_offset(&self) -> Option<TimezoneOffset> {
self.timezone_offset self.timezone_offset
} }
@ -771,7 +767,7 @@ fn normalize_month(yr: i64, mo: i64) -> Option<(i64, u8)> {
// Needed to make it work with negative durations // Needed to make it work with negative durations
let yr = yr.checked_add(mo.checked_sub(1)?.checked_div(12)?.checked_sub(1)?)?; let yr = yr.checked_add(mo.checked_sub(1)?.checked_div(12)?.checked_sub(1)?)?;
let mo = u8::try_from( let mo = u8::try_from(
12i64 12_i64
.checked_add(mo.checked_sub(1)?.checked_rem(12)?)? .checked_add(mo.checked_sub(1)?.checked_rem(12)?)?
.checked_add(1)?, .checked_add(1)?,
) )
@ -847,7 +843,7 @@ fn days_in_month(y: Option<i64>, m: u8) -> u8 {
/// The [dateTimePlusDuration](https://www.w3.org/TR/xmlschema11-2/#vp-dt-dateTimePlusDuration) function /// The [dateTimePlusDuration](https://www.w3.org/TR/xmlschema11-2/#vp-dt-dateTimePlusDuration) function
fn date_time_plus_duration( fn date_time_plus_duration(
du: Duration, du: Duration,
dt: DateTimeSevenPropertyModel, dt: &DateTimeSevenPropertyModel,
) -> Option<DateTimeSevenPropertyModel> { ) -> Option<DateTimeSevenPropertyModel> {
let yr = dt.year.unwrap_or(1); let yr = dt.year.unwrap_or(1);
let mo = dt.month.unwrap_or(1); let mo = dt.month.unwrap_or(1);
@ -874,7 +870,7 @@ fn date_time_plus_duration(
} }
/// The [timeOnTimeline](https://www.w3.org/TR/xmlschema11-2/#vp-dt-timeOnTimeline) function /// The [timeOnTimeline](https://www.w3.org/TR/xmlschema11-2/#vp-dt-timeOnTimeline) function
fn time_on_timeline(props: DateTimeSevenPropertyModel) -> Option<Decimal> { fn time_on_timeline(props: &DateTimeSevenPropertyModel) -> Option<Decimal> {
let yr = props.year.map_or(1971, |y| y - 1); let yr = props.year.map_or(1971, |y| y - 1);
let mo = props.month.unwrap_or(12); let mo = props.month.unwrap_or(12);
let da = props let da = props

@ -28,13 +28,14 @@ pub struct Decimal {
impl Decimal { impl Decimal {
/// Constructs the decimal i / 10^n /// Constructs the decimal i / 10^n
#[allow(clippy::cast_possible_truncation)]
pub fn new(i: i128, n: u32) -> Result<Self, DecimalOverflowError> { pub fn new(i: i128, n: u32) -> Result<Self, DecimalOverflowError> {
if n > DECIMAL_PART_DIGITS as u32 { if n > DECIMAL_PART_DIGITS as u32 {
//TODO: check if end with zeros? //TODO: check if end with zeros?
return Err(DecimalOverflowError); return Err(DecimalOverflowError);
} }
Ok(Self { Ok(Self {
value: i.checked_div(10i128.pow(n)).ok_or(DecimalOverflowError)?, value: i.checked_div(10_i128.pow(n)).ok_or(DecimalOverflowError)?,
}) })
} }
@ -44,6 +45,150 @@ impl Decimal {
value: i128::from_le_bytes(bytes), value: i128::from_le_bytes(bytes),
} }
} }
pub fn to_le_bytes(&self) -> [u8; 16] {
self.value.to_le_bytes()
}
/// [op:numeric-add](https://www.w3.org/TR/xpath-functions/#func-numeric-add)
#[inline]
pub fn checked_add(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_add(rhs.into().value)?,
})
}
/// [op:numeric-subtract](https://www.w3.org/TR/xpath-functions/#func-numeric-subtract)
#[inline]
pub fn checked_sub(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_sub(rhs.into().value)?,
})
}
/// [op:numeric-multiply](https://www.w3.org/TR/xpath-functions/#func-numeric-multiply)
#[inline]
pub fn checked_mul(&self, rhs: impl Into<Self>) -> Option<Self> {
//TODO: better algorithm to keep precision
Some(Self {
value: self
.value
.checked_div(DECIMAL_PART_HALF_POW)?
.checked_mul(rhs.into().value.checked_div(DECIMAL_PART_HALF_POW)?)?,
})
}
/// [op:numeric-divide](https://www.w3.org/TR/xpath-functions/#func-numeric-divide)
#[inline]
pub fn checked_div(&self, rhs: impl Into<Self>) -> Option<Self> {
//TODO: better algorithm to keep precision
Some(Self {
value: self
.value
.checked_mul(DECIMAL_PART_HALF_POW)?
.checked_div(rhs.into().value)?
.checked_mul(DECIMAL_PART_HALF_POW)?,
})
}
/// TODO: XSD? is well defined for not integer
pub fn checked_rem(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_rem(rhs.into().value)?,
})
}
pub fn checked_rem_euclid(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_rem_euclid(rhs.into().value)?,
})
}
/// [fn:abs](https://www.w3.org/TR/xpath-functions/#func-abs)
#[inline]
pub const fn abs(&self) -> Decimal {
Self {
value: self.value.abs(),
}
}
/// [fn:round](https://www.w3.org/TR/xpath-functions/#func-round)
#[inline]
pub fn round(&self) -> Decimal {
let value = self.value / DECIMAL_PART_POW_MINUS_ONE;
Self {
value: if value >= 0 {
(value / 10 + if value % 10 >= 5 { 1 } else { 0 }) * DECIMAL_PART_POW
} else {
(value / 10 + if -value % 10 > 5 { -1 } else { 0 }) * DECIMAL_PART_POW
},
}
}
/// [fn:ceiling](https://www.w3.org/TR/xpath-functions/#func-ceiling)
#[inline]
pub fn ceil(&self) -> Decimal {
Self {
value: if self.value >= 0 && self.value % DECIMAL_PART_POW != 0 {
(self.value / DECIMAL_PART_POW + 1) * DECIMAL_PART_POW
} else {
(self.value / DECIMAL_PART_POW) * DECIMAL_PART_POW
},
}
}
/// [fn:floor](https://www.w3.org/TR/xpath-functions/#func-floor)
#[inline]
pub fn floor(&self) -> Decimal {
Self {
value: if self.value >= 0 || self.value % DECIMAL_PART_POW == 0 {
(self.value / DECIMAL_PART_POW) * DECIMAL_PART_POW
} else {
(self.value / DECIMAL_PART_POW - 1) * DECIMAL_PART_POW
},
}
}
pub const fn is_negative(&self) -> bool {
self.value < 0
}
pub const fn is_positive(&self) -> bool {
self.value > 0
}
/// Creates a `Decimal` from a `f32` without taking care of precision
#[inline]
pub(crate) fn from_f32(v: f32) -> Self {
Self::from_f64(v.into())
}
/// Creates a `f32` from a `Decimal` without taking care of precision
#[inline]
#[allow(clippy::cast_possible_truncation)]
pub fn to_f32(&self) -> f32 {
self.to_f64() as f32
}
/// Creates a `Decimal` from a `f64` without taking care of precision
#[inline]
#[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)]
pub(crate) fn from_f64(v: f64) -> Self {
Self {
value: (v * (DECIMAL_PART_POW as f64)) as i128,
}
}
/// Creates a `f64` from a `Decimal` without taking care of precision
#[inline]
#[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)]
pub fn to_f64(&self) -> f64 {
(self.value as f64) / (DECIMAL_PART_POW as f64)
}
pub(super) const fn as_i128(&self) -> i128 {
self.value / DECIMAL_PART_POW
}
} }
impl From<i8> for Decimal { impl From<i8> for Decimal {
@ -146,7 +291,7 @@ impl FromStr for Decimal {
_ => (1, 0), _ => (1, 0),
}; };
let mut value = 0i128; let mut value = 0_i128;
let mut with_before_dot = false; let mut with_before_dot = false;
while cursor < input.len() && b'0' <= input[cursor] && input[cursor] <= b'9' { while cursor < input.len() && b'0' <= input[cursor] && input[cursor] <= b'9' {
value = value value = value
@ -246,7 +391,7 @@ impl From<DecimalOverflowError> for ParseDecimalError {
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy)]
pub struct DecimalOverflowError; pub struct DecimalOverflowError;
impl fmt::Display for DecimalOverflowError { impl fmt::Display for DecimalOverflowError {
@ -259,6 +404,7 @@ impl Error for DecimalOverflowError {}
impl fmt::Display for Decimal { impl fmt::Display for Decimal {
/// Formats the decimal following its canonical representation /// Formats the decimal following its canonical representation
#[allow(clippy::cast_possible_truncation)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.value == 0 { if self.value == 0 {
return if let Some(width) = f.width() { return if let Some(width) = f.width() {
@ -289,8 +435,7 @@ impl fmt::Display for Decimal {
.iter() .iter()
.cloned() .cloned()
.enumerate() .enumerate()
.find(|(_, v)| *v != b'0') .find_map(|(i, v)| if v == b'0' { None } else { Some(i) })
.map(|(i, _)| i)
.unwrap_or(40); .unwrap_or(40);
if last_non_zero >= DECIMAL_PART_DIGITS { if last_non_zero >= DECIMAL_PART_DIGITS {
@ -343,149 +488,6 @@ impl Neg for Decimal {
} }
} }
impl Decimal {
pub fn to_le_bytes(&self) -> [u8; 16] {
self.value.to_le_bytes()
}
/// [op:numeric-add](https://www.w3.org/TR/xpath-functions/#func-numeric-add)
#[inline]
pub fn checked_add(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_add(rhs.into().value)?,
})
}
/// [op:numeric-subtract](https://www.w3.org/TR/xpath-functions/#func-numeric-subtract)
#[inline]
pub fn checked_sub(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_sub(rhs.into().value)?,
})
}
/// [op:numeric-multiply](https://www.w3.org/TR/xpath-functions/#func-numeric-multiply)
#[inline]
pub fn checked_mul(&self, rhs: impl Into<Self>) -> Option<Self> {
//TODO: better algorithm to keep precision
Some(Self {
value: self
.value
.checked_div(DECIMAL_PART_HALF_POW)?
.checked_mul(rhs.into().value.checked_div(DECIMAL_PART_HALF_POW)?)?,
})
}
/// [op:numeric-divide](https://www.w3.org/TR/xpath-functions/#func-numeric-divide)
#[inline]
pub fn checked_div(&self, rhs: impl Into<Self>) -> Option<Self> {
//TODO: better algorithm to keep precision
Some(Self {
value: self
.value
.checked_mul(DECIMAL_PART_HALF_POW)?
.checked_div(rhs.into().value)?
.checked_mul(DECIMAL_PART_HALF_POW)?,
})
}
/// TODO: XSD? is well defined for not integer
pub fn checked_rem(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_rem(rhs.into().value)?,
})
}
pub fn checked_rem_euclid(&self, rhs: impl Into<Self>) -> Option<Self> {
Some(Self {
value: self.value.checked_rem_euclid(rhs.into().value)?,
})
}
/// [fn:abs](https://www.w3.org/TR/xpath-functions/#func-abs)
#[inline]
pub fn abs(&self) -> Decimal {
Self {
value: self.value.abs(),
}
}
/// [fn:round](https://www.w3.org/TR/xpath-functions/#func-round)
#[inline]
pub fn round(&self) -> Decimal {
let value = self.value / DECIMAL_PART_POW_MINUS_ONE;
Self {
value: if value >= 0 {
(value / 10 + if value % 10 >= 5 { 1 } else { 0 }) * DECIMAL_PART_POW
} else {
(value / 10 + if -value % 10 > 5 { -1 } else { 0 }) * DECIMAL_PART_POW
},
}
}
/// [fn:ceiling](https://www.w3.org/TR/xpath-functions/#func-ceiling)
#[inline]
pub fn ceil(&self) -> Decimal {
Self {
value: if self.value >= 0 && self.value % DECIMAL_PART_POW != 0 {
(self.value / DECIMAL_PART_POW + 1) * DECIMAL_PART_POW
} else {
(self.value / DECIMAL_PART_POW) * DECIMAL_PART_POW
},
}
}
/// [fn:floor](https://www.w3.org/TR/xpath-functions/#func-floor)
#[inline]
pub fn floor(&self) -> Decimal {
Self {
value: if self.value >= 0 || self.value % DECIMAL_PART_POW == 0 {
(self.value / DECIMAL_PART_POW) * DECIMAL_PART_POW
} else {
(self.value / DECIMAL_PART_POW - 1) * DECIMAL_PART_POW
},
}
}
pub fn is_negative(&self) -> bool {
self.value < 0
}
pub fn is_positive(&self) -> bool {
self.value > 0
}
/// Creates a `Decimal` from a `f32` without taking care of precision
#[inline]
pub(crate) fn from_f32(v: f32) -> Self {
Self::from_f64(v.into())
}
/// Creates a `f32` from a `Decimal` without taking care of precision
#[inline]
pub fn to_f32(&self) -> f32 {
self.to_f64() as f32
}
/// Creates a `Decimal` from a `f64` without taking care of precision
#[inline]
pub(crate) fn from_f64(v: f64) -> Self {
Self {
value: (v * (DECIMAL_PART_POW as f64)) as i128,
}
}
/// Creates a `f64` from a `Decimal` without taking care of precision
#[inline]
pub fn to_f64(&self) -> f64 {
(self.value as f64) / (DECIMAL_PART_POW as f64)
}
pub(super) fn as_i128(&self) -> i128 {
self.value / DECIMAL_PART_POW
}
}
impl TryFrom<Decimal> for i64 { impl TryFrom<Decimal> for i64 {
type Error = DecimalOverflowError; type Error = DecimalOverflowError;

@ -39,6 +39,72 @@ impl Duration {
seconds: Decimal::from_le_bytes(seconds), seconds: Decimal::from_le_bytes(seconds),
} }
} }
/// [fn:years-from-duration](https://www.w3.org/TR/xpath-functions/#func-years-from-duration)
pub fn years(&self) -> i64 {
self.months / 12
}
/// [fn:months-from-duration](https://www.w3.org/TR/xpath-functions/#func-months-from-duration)
pub fn months(&self) -> i64 {
self.months % 12
}
/// [fn:days-from-duration](https://www.w3.org/TR/xpath-functions/#func-days-from-duration)
#[allow(clippy::cast_possible_truncation)]
pub fn days(&self) -> i64 {
(self.seconds.as_i128() / 86400) as i64
}
/// [fn:hours-from-duration](https://www.w3.org/TR/xpath-functions/#func-hours-from-duration)
#[allow(clippy::cast_possible_truncation)]
pub fn hours(&self) -> i64 {
((self.seconds.as_i128() % 86400) / 3600) as i64
}
/// [fn:minutes-from-duration](https://www.w3.org/TR/xpath-functions/#func-minutes-from-duration)
#[allow(clippy::cast_possible_truncation)]
pub fn minutes(&self) -> i64 {
((self.seconds.as_i128() % 3600) / 60) as i64
}
/// [fn:seconds-from-duration](https://www.w3.org/TR/xpath-functions/#func-seconds-from-duration)
pub fn seconds(&self) -> Decimal {
self.seconds.checked_rem(60).unwrap()
}
pub(super) const fn all_months(&self) -> i64 {
self.months
}
pub(super) const fn all_seconds(&self) -> Decimal {
self.seconds
}
pub fn to_le_bytes(&self) -> [u8; 24] {
let mut bytes = [0; 24];
bytes[0..8].copy_from_slice(&self.months.to_le_bytes());
bytes[8..24].copy_from_slice(&self.seconds.to_le_bytes());
bytes
}
/// [op:add-yearMonthDurations](https://www.w3.org/TR/xpath-functions/#func-add-yearMonthDurations) and [op:add-dayTimeDurations](https://www.w3.org/TR/xpath-functions/#func-add-dayTimeDurations)
pub fn checked_add(&self, rhs: impl Into<Self>) -> Option<Self> {
let rhs = rhs.into();
Some(Self {
months: self.months.checked_add(rhs.months)?,
seconds: self.seconds.checked_add(rhs.seconds)?,
})
}
/// [op:subtract-yearMonthDurations](https://www.w3.org/TR/xpath-functions/#func-subtract-yearMonthDurations) and [op:subtract-dayTimeDurations](https://www.w3.org/TR/xpath-functions/#func-subtract-dayTimeDurations)
pub fn checked_sub(&self, rhs: impl Into<Self>) -> Option<Self> {
let rhs = rhs.into();
Some(Self {
months: self.months.checked_sub(rhs.months)?,
seconds: self.seconds.checked_sub(rhs.seconds)?,
})
}
} }
impl TryFrom<StdDuration> for Duration { impl TryFrom<StdDuration> for Duration {
@ -85,10 +151,10 @@ impl fmt::Display for Duration {
let m = ym % 12; let m = ym % 12;
if y != 0 { if y != 0 {
if m != 0 { if m == 0 {
write!(f, "{}Y{}M", y, m)?;
} else {
write!(f, "{}Y", y)?; write!(f, "{}Y", y)?;
} else {
write!(f, "{}Y{}M", y, m)?;
} }
} else if m != 0 || ss == 0.into() { } else if m != 0 || ss == 0.into() {
write!(f, "{}M", m)?; write!(f, "{}M", m)?;
@ -154,71 +220,6 @@ impl PartialOrd for Duration {
} }
} }
impl Duration {
/// [fn:years-from-duration](https://www.w3.org/TR/xpath-functions/#func-years-from-duration)
pub fn years(&self) -> i64 {
self.months / 12
}
/// [fn:months-from-duration](https://www.w3.org/TR/xpath-functions/#func-months-from-duration)
pub fn months(&self) -> i64 {
self.months % 12
}
/// [fn:days-from-duration](https://www.w3.org/TR/xpath-functions/#func-days-from-duration)
pub fn days(&self) -> i64 {
(self.seconds.as_i128() / 86400) as i64
}
/// [fn:hours-from-duration](https://www.w3.org/TR/xpath-functions/#func-hours-from-duration)
pub fn hours(&self) -> i64 {
((self.seconds.as_i128() % 86400) / 3600) as i64
}
/// [fn:minutes-from-duration](https://www.w3.org/TR/xpath-functions/#func-minutes-from-duration)
pub fn minutes(&self) -> i64 {
((self.seconds.as_i128() % 3600) / 60) as i64
}
/// [fn:seconds-from-duration](https://www.w3.org/TR/xpath-functions/#func-seconds-from-duration)
pub fn seconds(&self) -> Decimal {
self.seconds.checked_rem(60).unwrap()
}
pub(super) fn all_months(&self) -> i64 {
self.months
}
pub(super) fn all_seconds(&self) -> Decimal {
self.seconds
}
pub fn to_le_bytes(&self) -> [u8; 24] {
let mut bytes = [0; 24];
bytes[0..8].copy_from_slice(&self.months.to_le_bytes());
bytes[8..24].copy_from_slice(&self.seconds.to_le_bytes());
bytes
}
/// [op:add-yearMonthDurations](https://www.w3.org/TR/xpath-functions/#func-add-yearMonthDurations) and [op:add-dayTimeDurations](https://www.w3.org/TR/xpath-functions/#func-add-dayTimeDurations)
pub fn checked_add(&self, rhs: impl Into<Self>) -> Option<Self> {
let rhs = rhs.into();
Some(Self {
months: self.months.checked_add(rhs.months)?,
seconds: self.seconds.checked_add(rhs.seconds)?,
})
}
/// [op:subtract-yearMonthDurations](https://www.w3.org/TR/xpath-functions/#func-subtract-yearMonthDurations) and [op:subtract-dayTimeDurations](https://www.w3.org/TR/xpath-functions/#func-subtract-dayTimeDurations)
pub fn checked_sub(&self, rhs: impl Into<Self>) -> Option<Self> {
let rhs = rhs.into();
Some(Self {
months: self.months.checked_sub(rhs.months)?,
seconds: self.seconds.checked_sub(rhs.seconds)?,
})
}
}
impl Neg for Duration { impl Neg for Duration {
type Output = Self; type Output = Self;

@ -167,32 +167,32 @@ pub fn parse_value<'a, T>(
//TODO: check every computation //TODO: check every computation
// [6] duYearFrag ::= unsignedNoDecimalPtNumeral 'Y' // [6] duYearFrag ::= unsignedNoDecimalPtNumeral 'Y'
fn du_year_frag(input: &str) -> XsdResult<i64> { fn du_year_frag(input: &str) -> XsdResult<'_, i64> {
terminated(unsigned_no_decimal_pt_numeral, char('Y'))(input) terminated(unsigned_no_decimal_pt_numeral, char('Y'))(input)
} }
// [7] duMonthFrag ::= unsignedNoDecimalPtNumeral 'M' // [7] duMonthFrag ::= unsignedNoDecimalPtNumeral 'M'
fn du_month_frag(input: &str) -> XsdResult<i64> { fn du_month_frag(input: &str) -> XsdResult<'_, i64> {
terminated(unsigned_no_decimal_pt_numeral, char('M'))(input) terminated(unsigned_no_decimal_pt_numeral, char('M'))(input)
} }
// [8] duDayFrag ::= unsignedNoDecimalPtNumeral 'D' // [8] duDayFrag ::= unsignedNoDecimalPtNumeral 'D'
fn du_day_frag(input: &str) -> XsdResult<i64> { fn du_day_frag(input: &str) -> XsdResult<'_, i64> {
terminated(unsigned_no_decimal_pt_numeral, char('D'))(input) terminated(unsigned_no_decimal_pt_numeral, char('D'))(input)
} }
// [9] duHourFrag ::= unsignedNoDecimalPtNumeral 'H' // [9] duHourFrag ::= unsignedNoDecimalPtNumeral 'H'
fn du_hour_frag(input: &str) -> XsdResult<i64> { fn du_hour_frag(input: &str) -> XsdResult<'_, i64> {
terminated(unsigned_no_decimal_pt_numeral, char('H'))(input) terminated(unsigned_no_decimal_pt_numeral, char('H'))(input)
} }
// [10] duMinuteFrag ::= unsignedNoDecimalPtNumeral 'M' // [10] duMinuteFrag ::= unsignedNoDecimalPtNumeral 'M'
fn du_minute_frag(input: &str) -> XsdResult<i64> { fn du_minute_frag(input: &str) -> XsdResult<'_, i64> {
terminated(unsigned_no_decimal_pt_numeral, char('M'))(input) terminated(unsigned_no_decimal_pt_numeral, char('M'))(input)
} }
// [11] duSecondFrag ::= (unsignedNoDecimalPtNumeral | unsignedDecimalPtNumeral) 'S' // [11] duSecondFrag ::= (unsignedNoDecimalPtNumeral | unsignedDecimalPtNumeral) 'S'
fn du_second_frag(input: &str) -> XsdResult<Decimal> { fn du_second_frag(input: &str) -> XsdResult<'_, Decimal> {
terminated( terminated(
map_res( map_res(
recognize(tuple((digit0, opt(preceded(char('.'), digit0))))), recognize(tuple((digit0, opt(preceded(char('.'), digit0))))),
@ -203,7 +203,7 @@ fn du_second_frag(input: &str) -> XsdResult<Decimal> {
} }
// [12] duYearMonthFrag ::= (duYearFrag duMonthFrag?) | duMonthFrag // [12] duYearMonthFrag ::= (duYearFrag duMonthFrag?) | duMonthFrag
fn du_year_month_frag(input: &str) -> XsdResult<i64> { fn du_year_month_frag(input: &str) -> XsdResult<'_, i64> {
alt(( alt((
map(tuple((du_year_frag, opt(du_month_frag))), |(y, m)| { map(tuple((du_year_frag, opt(du_month_frag))), |(y, m)| {
12 * y + m.unwrap_or(0) 12 * y + m.unwrap_or(0)
@ -213,7 +213,7 @@ fn du_year_month_frag(input: &str) -> XsdResult<i64> {
} }
// [13] duTimeFrag ::= 'T' ((duHourFrag duMinuteFrag? duSecondFrag?) | (duMinuteFrag duSecondFrag?) | duSecondFrag) // [13] duTimeFrag ::= 'T' ((duHourFrag duMinuteFrag? duSecondFrag?) | (duMinuteFrag duSecondFrag?) | duSecondFrag)
fn du_time_frag(input: &str) -> XsdResult<Decimal> { fn du_time_frag(input: &str) -> XsdResult<'_, Decimal> {
preceded( preceded(
char('T'), char('T'),
alt(( alt((
@ -236,7 +236,7 @@ fn du_time_frag(input: &str) -> XsdResult<Decimal> {
} }
// [14] duDayTimeFrag ::= (duDayFrag duTimeFrag?) | duTimeFrag // [14] duDayTimeFrag ::= (duDayFrag duTimeFrag?) | duTimeFrag
fn du_day_time_frag(input: &str) -> XsdResult<Decimal> { fn du_day_time_frag(input: &str) -> XsdResult<'_, Decimal> {
alt(( alt((
map_res(tuple((du_day_frag, opt(du_time_frag))), |(d, t)| { map_res(tuple((du_day_frag, opt(du_time_frag))), |(d, t)| {
Decimal::from(d) Decimal::from(d)
@ -250,7 +250,7 @@ fn du_day_time_frag(input: &str) -> XsdResult<Decimal> {
} }
// [15] durationLexicalRep ::= '-'? 'P' ((duYearMonthFrag duDayTimeFrag?) | duDayTimeFrag) // [15] durationLexicalRep ::= '-'? 'P' ((duYearMonthFrag duDayTimeFrag?) | duDayTimeFrag)
pub fn duration_lexical_rep(input: &str) -> XsdResult<Duration> { pub fn duration_lexical_rep(input: &str) -> XsdResult<'_, Duration> {
map( map(
tuple(( tuple((
opt(char('-')), opt(char('-')),
@ -276,7 +276,7 @@ pub fn duration_lexical_rep(input: &str) -> XsdResult<Duration> {
} }
// [16] dateTimeLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag 'T' ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag? // [16] dateTimeLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag 'T' ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag?
pub fn date_time_lexical_rep(input: &str) -> XsdResult<DateTime> { pub fn date_time_lexical_rep(input: &str) -> XsdResult<'_, DateTime> {
map_res( map_res(
tuple(( tuple((
year_frag, year_frag,
@ -301,7 +301,7 @@ pub fn date_time_lexical_rep(input: &str) -> XsdResult<DateTime> {
} }
// [17] timeLexicalRep ::= ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag? // [17] timeLexicalRep ::= ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag?
pub fn time_lexical_rep(input: &str) -> XsdResult<Time> { pub fn time_lexical_rep(input: &str) -> XsdResult<'_, Time> {
map_res( map_res(
tuple(( tuple((
alt(( alt((
@ -318,7 +318,7 @@ pub fn time_lexical_rep(input: &str) -> XsdResult<Time> {
} }
// [18] dateLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag timezoneFrag? Constraint: Day-of-month Representations // [18] dateLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag timezoneFrag? Constraint: Day-of-month Representations
pub fn date_lexical_rep(input: &str) -> XsdResult<Date> { pub fn date_lexical_rep(input: &str) -> XsdResult<'_, Date> {
map_res( map_res(
tuple(( tuple((
year_frag, year_frag,
@ -333,12 +333,12 @@ pub fn date_lexical_rep(input: &str) -> XsdResult<Date> {
} }
// [46] unsignedNoDecimalPtNumeral ::= digit+ // [46] unsignedNoDecimalPtNumeral ::= digit+
fn unsigned_no_decimal_pt_numeral(input: &str) -> XsdResult<i64> { fn unsigned_no_decimal_pt_numeral(input: &str) -> XsdResult<'_, i64> {
map_res(digit1, |i| i64::from_str(i))(input) map_res(digit1, |i| i64::from_str(i))(input)
} }
// [56] yearFrag ::= '-'? (([1-9] digit digit digit+)) | ('0' digit digit digit)) // [56] yearFrag ::= '-'? (([1-9] digit digit digit+)) | ('0' digit digit digit))
fn year_frag(input: &str) -> XsdResult<i64> { fn year_frag(input: &str) -> XsdResult<'_, i64> {
map_res( map_res(
recognize(tuple(( recognize(tuple((
opt(char('-')), opt(char('-')),
@ -349,35 +349,36 @@ fn year_frag(input: &str) -> XsdResult<i64> {
} }
// [57] monthFrag ::= ('0' [1-9]) | ('1' [0-2]) // [57] monthFrag ::= ('0' [1-9]) | ('1' [0-2])
fn month_frag(input: &str) -> XsdResult<u8> { fn month_frag(input: &str) -> XsdResult<'_, u8> {
map_res(take_while_m_n(2, 2, |c: char| c.is_ascii_digit()), |v| { map_res(take_while_m_n(2, 2, |c: char| c.is_ascii_digit()), |v| {
parsed_u8_range(v, 1, 12) parsed_u8_range(v, 1, 12)
})(input) })(input)
} }
// [58] dayFrag ::= ('0' [1-9]) | ([12] digit) | ('3' [01]) // [58] dayFrag ::= ('0' [1-9]) | ([12] digit) | ('3' [01])
fn day_frag(input: &str) -> XsdResult<u8> { fn day_frag(input: &str) -> XsdResult<'_, u8> {
map_res(take_while_m_n(2, 2, |c: char| c.is_ascii_digit()), |v| { map_res(take_while_m_n(2, 2, |c: char| c.is_ascii_digit()), |v| {
parsed_u8_range(v, 1, 31) parsed_u8_range(v, 1, 31)
})(input) })(input)
} }
// [59] hourFrag ::= ([01] digit) | ('2' [0-3]) // [59] hourFrag ::= ([01] digit) | ('2' [0-3])
fn hour_frag(input: &str) -> XsdResult<u8> { fn hour_frag(input: &str) -> XsdResult<'_, u8> {
map_res(take_while_m_n(2, 2, |c: char| c.is_ascii_digit()), |v| { map_res(take_while_m_n(2, 2, |c: char| c.is_ascii_digit()), |v| {
parsed_u8_range(v, 0, 23) parsed_u8_range(v, 0, 23)
})(input) })(input)
} }
// [60] minuteFrag ::= [0-5] digit // [60] minuteFrag ::= [0-5] digit
fn minute_frag(input: &str) -> XsdResult<u8> { fn minute_frag(input: &str) -> XsdResult<'_, u8> {
map_res(take_while_m_n(2, 2, |c: char| c.is_ascii_digit()), |v| { map_res(take_while_m_n(2, 2, |c: char| c.is_ascii_digit()), |v| {
parsed_u8_range(v, 0, 59) parsed_u8_range(v, 0, 59)
})(input) })(input)
} }
// [61] secondFrag ::= ([0-5] digit) ('.' digit+)? // [61] secondFrag ::= ([0-5] digit) ('.' digit+)?
fn second_frag(input: &str) -> XsdResult<Decimal> { #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
fn second_frag(input: &str) -> XsdResult<'_, Decimal> {
map_res( map_res(
recognize(tuple(( recognize(tuple((
take_while_m_n(2, 2, |c: char| c.is_ascii_digit()), take_while_m_n(2, 2, |c: char| c.is_ascii_digit()),
@ -404,7 +405,7 @@ fn second_frag(input: &str) -> XsdResult<Decimal> {
} }
// [62] endOfDayFrag ::= '24:00:00' ('.' '0'+)? // [62] endOfDayFrag ::= '24:00:00' ('.' '0'+)?
fn end_of_day_frag(input: &str) -> XsdResult<(u8, u8, Decimal)> { fn end_of_day_frag(input: &str) -> XsdResult<'_, (u8, u8, Decimal)> {
map( map(
recognize(tuple(( recognize(tuple((
tag("24:00:00"), tag("24:00:00"),
@ -415,7 +416,7 @@ fn end_of_day_frag(input: &str) -> XsdResult<(u8, u8, Decimal)> {
} }
// [63] timezoneFrag ::= 'Z' | ('+' | '-') (('0' digit | '1' [0-3]) ':' minuteFrag | '14:00') // [63] timezoneFrag ::= 'Z' | ('+' | '-') (('0' digit | '1' [0-3]) ':' minuteFrag | '14:00')
fn timezone_frag(input: &str) -> XsdResult<TimezoneOffset> { fn timezone_frag(input: &str) -> XsdResult<'_, TimezoneOffset> {
alt(( alt((
map(char('Z'), |_| TimezoneOffset::utc()), map(char('Z'), |_| TimezoneOffset::utc()),
map( map(

@ -84,13 +84,13 @@ pub trait RepositoryConnection: Clone {
/// } /// }
/// # Result::Ok(()) /// # Result::Ok(())
/// ``` /// ```
fn prepare_query(&self, query: &str, options: QueryOptions) -> Result<Self::PreparedQuery>; fn prepare_query(&self, query: &str, options: QueryOptions<'_>) -> Result<Self::PreparedQuery>;
/// This is similar to `prepare_query`, but useful if a SPARQL query has already been parsed, which is the case when building `ServiceHandler`s for federated queries with `SERVICE` clauses. For examples, look in the tests. /// This is similar to `prepare_query`, but useful if a SPARQL query has already been parsed, which is the case when building `ServiceHandler`s for federated queries with `SERVICE` clauses. For examples, look in the tests.
fn prepare_query_from_pattern( fn prepare_query_from_pattern(
&self, &self,
graph_pattern: &GraphPattern, graph_pattern: &GraphPattern,
options: QueryOptions, options: QueryOptions<'_>,
) -> Result<Self::PreparedQuery>; ) -> Result<Self::PreparedQuery>;
/// Retrieves quads with a filter on each quad component /// Retrieves quads with a filter on each quad component

@ -237,7 +237,7 @@ impl<'a> fmt::Display for SparqlTripleOrPathPattern<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 { match self.0 {
TripleOrPathPattern::Triple(tp) => write!(f, "{}", tp), TripleOrPathPattern::Triple(tp) => write!(f, "{}", tp),
TripleOrPathPattern::Path(ppp) => write!(f, "{}", SparqlPathPattern(&ppp)), TripleOrPathPattern::Path(ppp) => write!(f, "{}", SparqlPathPattern(ppp)),
} }
} }
} }
@ -605,7 +605,7 @@ impl fmt::Display for GraphPattern {
write!(f, "{{")?; write!(f, "{{")?;
for i in 0..values.len() { for i in 0..values.len() {
if let Some(ref val) = values[i] { if let Some(ref val) = values[i] {
write!(f, " {} {} ", variables[i], val)?; write!(f, " {} \u{2192} {} ", variables[i], val)?;
} }
} }
write!(f, "}}")?; write!(f, "}}")?;
@ -712,7 +712,7 @@ impl GraphPattern {
} }
GraphPattern::Extend(p, v, _) => { GraphPattern::Extend(p, v, _) => {
p.add_visible_variables(vars); p.add_visible_variables(vars);
adds_if_has_name(vars, &v); adds_if_has_name(vars, v);
} }
GraphPattern::Minus(a, _) => a.add_visible_variables(vars), GraphPattern::Minus(a, _) => a.add_visible_variables(vars),
GraphPattern::Service(_, p, _) => p.add_visible_variables(vars), GraphPattern::Service(_, p, _) => p.add_visible_variables(vars),
@ -818,7 +818,7 @@ impl<'a> fmt::Display for SparqlGraphPattern<'a> {
f, f,
"{{ SELECT {} WHERE {{ {} }} GROUP BY {} }}", "{{ SELECT {} WHERE {{ {} }} GROUP BY {} }}",
agg.iter() agg.iter()
.map(|(a, v)| format!("({} AS {})", SparqlAggregation(&a), v)) .map(|(a, v)| format!("({} AS {})", SparqlAggregation(a), v))
.chain(group.iter().map(|e| e.to_string())) .chain(group.iter().map(|e| e.to_string()))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(" "), .join(" "),
@ -963,13 +963,15 @@ impl fmt::Display for Aggregation {
match self { match self {
Aggregation::Count(e, distinct) => { Aggregation::Count(e, distinct) => {
if *distinct { if *distinct {
e.as_ref() if let Some(ex) = e {
.map(|ex| write!(f, "COUNT(DISTINCT {})", ex)) write!(f, "COUNT(DISTINCT {})", ex)
.unwrap_or_else(|| write!(f, "COUNT(DISTINCT *)")) } else {
write!(f, "COUNT(DISTINCT *)")
}
} else if let Some(ex) = e {
write!(f, "COUNT({})", ex)
} else { } else {
e.as_ref() write!(f, "COUNT(*)")
.map(|ex| write!(f, "COUNT({})", ex))
.unwrap_or_else(|| write!(f, "COUNT(*)"))
} }
} }
Aggregation::Sum(e, distinct) => { Aggregation::Sum(e, distinct) => {
@ -1009,31 +1011,25 @@ impl fmt::Display for Aggregation {
} }
Aggregation::GroupConcat(e, distinct, sep) => { Aggregation::GroupConcat(e, distinct, sep) => {
if *distinct { if *distinct {
sep.as_ref() if let Some(s) = sep {
.map(|s| { write!(
write!( f,
f, "Aggregation(Distinct({}), GroupConcat, {{\"separator\" \u{2192} {}}})",
"Aggregation(Distinct({}), GroupConcat, {{\"separator\" → {}}})", e,
e, fmt_str(s)
fmt_str(s) )
) } else {
}) write!(f, "Aggregation(Distinct({}), GroupConcat, {{}})", e)
.unwrap_or_else(|| { }
write!(f, "Aggregation(Distinct({}), GroupConcat, {{}})", e) } else if let Some(s) = sep {
}) write!(
f,
"Aggregation({}, GroupConcat, {{\"separator\" \u{2192} {}}})",
e,
fmt_str(s)
)
} else { } else {
sep.as_ref() write!(f, "Aggregation(Distinct({}), GroupConcat, {{}})", e)
.map(|s| {
write!(
f,
"Aggregation({}, GroupConcat, {{\"separator\" → {}}})",
e,
fmt_str(s)
)
})
.unwrap_or_else(|| {
write!(f, "Aggregation(Distinct({}), GroupConcat, {{}})", e)
})
} }
} }
} }
@ -1120,7 +1116,7 @@ impl<'a> fmt::Display for SparqlAggregation<'a> {
} }
} }
fn fmt_str(value: &str) -> rio::Literal { fn fmt_str(value: &str) -> rio::Literal<'_> {
rio::Literal::Simple { value } rio::Literal::Simple { value }
} }
@ -1241,14 +1237,7 @@ impl fmt::Display for QueryVariants {
if let Some(base_iri) = base_iri { if let Some(base_iri) = base_iri {
writeln!(f, "BASE <{}>", base_iri)?; writeln!(f, "BASE <{}>", base_iri)?;
} }
write!( write!(f, "{}", SparqlGraphRootPattern { algebra, dataset })
f,
"{}",
SparqlGraphRootPattern {
algebra: &algebra,
dataset: &dataset
}
)
} }
QueryVariants::Construct { QueryVariants::Construct {
construct, construct,
@ -1269,7 +1258,7 @@ impl fmt::Display for QueryVariants {
.join(" . "), .join(" . "),
dataset, dataset,
SparqlGraphRootPattern { SparqlGraphRootPattern {
algebra: &algebra, algebra,
dataset: &EMPTY_DATASET dataset: &EMPTY_DATASET
} }
) )
@ -1287,7 +1276,7 @@ impl fmt::Display for QueryVariants {
"DESCRIBE * {} WHERE {{ {} }}", "DESCRIBE * {} WHERE {{ {} }}",
dataset, dataset,
SparqlGraphRootPattern { SparqlGraphRootPattern {
algebra: &algebra, algebra,
dataset: &EMPTY_DATASET dataset: &EMPTY_DATASET
} }
) )
@ -1305,7 +1294,7 @@ impl fmt::Display for QueryVariants {
"ASK {} WHERE {{ {} }}", "ASK {} WHERE {{ {} }}",
dataset, dataset,
SparqlGraphRootPattern { SparqlGraphRootPattern {
algebra: &algebra, algebra,
dataset: &EMPTY_DATASET dataset: &EMPTY_DATASET
} }
) )

@ -153,10 +153,10 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
graph_name, graph_name,
} => Box::new(self.eval_plan(&*child, from).flat_map_ok(move |tuple| { } => Box::new(self.eval_plan(&*child, from).flat_map_ok(move |tuple| {
let mut iter = self.dataset.quads_for_pattern( let mut iter = self.dataset.quads_for_pattern(
get_pattern_value(&subject, &tuple), get_pattern_value(subject, &tuple),
get_pattern_value(&predicate, &tuple), get_pattern_value(predicate, &tuple),
get_pattern_value(&object, &tuple), get_pattern_value(object, &tuple),
get_pattern_value(&graph_name, &tuple), get_pattern_value(graph_name, &tuple),
); );
if subject.is_var() && subject == predicate { if subject.is_var() && subject == predicate {
iter = Box::new(iter.filter(|quad| match quad { iter = Box::new(iter.filter(|quad| match quad {
@ -199,10 +199,10 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
let iter: EncodedTuplesIterator<'_> = Box::new(iter.map(move |quad| { let iter: EncodedTuplesIterator<'_> = Box::new(iter.map(move |quad| {
let quad = quad?; let quad = quad?;
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
put_pattern_value(&subject, quad.subject, &mut new_tuple); put_pattern_value(subject, quad.subject, &mut new_tuple);
put_pattern_value(&predicate, quad.predicate, &mut new_tuple); put_pattern_value(predicate, quad.predicate, &mut new_tuple);
put_pattern_value(&object, quad.object, &mut new_tuple); put_pattern_value(object, quad.object, &mut new_tuple);
put_pattern_value(&graph_name, quad.graph_name, &mut new_tuple); put_pattern_value(graph_name, quad.graph_name, &mut new_tuple);
Ok(new_tuple) Ok(new_tuple)
})); }));
iter iter
@ -214,15 +214,16 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
object, object,
graph_name, graph_name,
} => Box::new(self.eval_plan(&*child, from).flat_map_ok(move |tuple| { } => Box::new(self.eval_plan(&*child, from).flat_map_ok(move |tuple| {
let input_subject = get_pattern_value(&subject, &tuple); let input_subject = get_pattern_value(subject, &tuple);
let input_object = get_pattern_value(&object, &tuple); let input_object = get_pattern_value(object, &tuple);
let input_graph_name = let input_graph_name =
if let Some(graph_name) = get_pattern_value(&graph_name, &tuple) { if let Some(graph_name) = get_pattern_value(graph_name, &tuple) {
graph_name graph_name
} else { } else {
return Box::new(once(Err(format_err!( let result: EncodedTuplesIterator<'_> = Box::new(once(Err(format_err!(
"Unknown graph name is not allowed when evaluating property path" "Unknown graph name is not allowed when evaluating property path"
)))) as EncodedTuplesIterator<'_>; ))));
return result;
}; };
match (input_subject, input_object) { match (input_subject, input_object) {
(Some(input_subject), Some(input_object)) => Box::new( (Some(input_subject), Some(input_object)) => Box::new(
@ -237,13 +238,12 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
} }
Err(error) => Some(Err(error)), Err(error) => Some(Err(error)),
}), }),
) ),
as EncodedTuplesIterator<'_>,
(Some(input_subject), None) => Box::new( (Some(input_subject), None) => Box::new(
self.eval_path_from(path, input_subject, input_graph_name) self.eval_path_from(path, input_subject, input_graph_name)
.map(move |o| { .map(move |o| {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
put_pattern_value(&object, o?, &mut new_tuple); put_pattern_value(object, o?, &mut new_tuple);
Ok(new_tuple) Ok(new_tuple)
}), }),
), ),
@ -251,7 +251,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
self.eval_path_to(path, input_object, input_graph_name) self.eval_path_to(path, input_object, input_graph_name)
.map(move |s| { .map(move |s| {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
put_pattern_value(&subject, s?, &mut new_tuple); put_pattern_value(subject, s?, &mut new_tuple);
Ok(new_tuple) Ok(new_tuple)
}), }),
), ),
@ -259,8 +259,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
Box::new(self.eval_open_path(path, input_graph_name).map(move |so| { Box::new(self.eval_open_path(path, input_graph_name).map(move |so| {
let mut new_tuple = tuple.clone(); let mut new_tuple = tuple.clone();
so.map(move |(s, o)| { so.map(move |(s, o)| {
put_pattern_value(&subject, s, &mut new_tuple); put_pattern_value(subject, s, &mut new_tuple);
put_pattern_value(&object, o, &mut new_tuple); put_pattern_value(object, o, &mut new_tuple);
new_tuple new_tuple
}) })
})) }))
@ -302,7 +302,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
right, right,
possible_problem_vars, possible_problem_vars,
} => { } => {
let problem_vars = bind_variables_in_set(&from, &possible_problem_vars); let problem_vars = bind_variables_in_set(&from, possible_problem_vars);
let mut filtered_from = from.clone(); let mut filtered_from = from.clone();
unbind_variables(&mut filtered_from, &problem_vars); unbind_variables(&mut filtered_from, &problem_vars);
let iter = LeftJoinIterator { let iter = LeftJoinIterator {
@ -326,7 +326,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
Box::new(self.eval_plan(&*child, from).filter(move |tuple| { Box::new(self.eval_plan(&*child, from).filter(move |tuple| {
match tuple { match tuple {
Ok(tuple) => eval Ok(tuple) => eval
.eval_expression(&expression, tuple) .eval_expression(expression, tuple)
.and_then(|term| eval.to_bool(term)) .and_then(|term| eval.to_bool(term))
.unwrap_or(false), .unwrap_or(false),
Err(_) => true, Err(_) => true,
@ -335,7 +335,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
} }
PlanNode::Union { children } => Box::new(UnionIterator { PlanNode::Union { children } => Box::new(UnionIterator {
eval: self, eval: self,
plans: &children, plans: children,
input: from, input: from,
current_iterator: Box::new(empty()), current_iterator: Box::new(empty()),
current_plan: 0, current_plan: 0,
@ -348,7 +348,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
let eval = self; let eval = self;
Box::new(self.eval_plan(&*child, from).map(move |tuple| { Box::new(self.eval_plan(&*child, from).map(move |tuple| {
let mut tuple = tuple?; let mut tuple = tuple?;
if let Some(value) = eval.eval_expression(&expression, &tuple) { if let Some(value) = eval.eval_expression(expression, &tuple) {
tuple.set(*position, value) tuple.set(*position, value)
} }
Ok(tuple) Ok(tuple)
@ -370,14 +370,14 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
for comp in by { for comp in by {
match comp { match comp {
Comparator::Asc(expression) => { Comparator::Asc(expression) => {
match self.cmp_according_to_expression(a, b, &expression) { match self.cmp_according_to_expression(a, b, expression) {
Ordering::Greater => return Ordering::Greater, Ordering::Greater => return Ordering::Greater,
Ordering::Less => return Ordering::Less, Ordering::Less => return Ordering::Less,
Ordering::Equal => (), Ordering::Equal => (),
} }
} }
Comparator::Desc(expression) => { Comparator::Desc(expression) => {
match self.cmp_according_to_expression(a, b, &expression) { match self.cmp_according_to_expression(a, b, expression) {
Ordering::Greater => return Ordering::Less, Ordering::Greater => return Ordering::Less,
Ordering::Less => return Ordering::Greater, Ordering::Less => return Ordering::Greater,
Ordering::Equal => (), Ordering::Equal => (),
@ -451,7 +451,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
aggregate aggregate
.parameter .parameter
.as_ref() .as_ref()
.and_then(|parameter| self.eval_expression(&parameter, &tuple)), .and_then(|parameter| self.eval_expression(parameter, &tuple)),
); );
} }
}); });
@ -492,12 +492,12 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
from: &EncodedTuple, from: &EncodedTuple,
) -> Result<EncodedTuplesIterator<'b>> { ) -> Result<EncodedTuplesIterator<'b>> {
let service_name = self.dataset.decode_named_node( let service_name = self.dataset.decode_named_node(
get_pattern_value(service_name, &from) get_pattern_value(service_name, from)
.ok_or_else(|| format_err!("The SERVICE name is not bound"))?, .ok_or_else(|| format_err!("The SERVICE name is not bound"))?,
)?; )?;
Ok(self.encode_bindings( Ok(self.encode_bindings(
variables, variables,
self.service_handler.handle(&service_name, &graph_pattern)?, self.service_handler.handle(&service_name, graph_pattern)?,
)) ))
} }
@ -558,14 +558,14 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
.quads_for_pattern(Some(start), Some(*p), None, Some(graph_name)) .quads_for_pattern(Some(start), Some(*p), None, Some(graph_name))
.map(|t| Ok(t?.object)), .map(|t| Ok(t?.object)),
), ),
PlanPropertyPath::InversePath(p) => self.eval_path_to(&p, start, graph_name), PlanPropertyPath::InversePath(p) => self.eval_path_to(p, start, graph_name),
PlanPropertyPath::SequencePath(a, b) => Box::new( PlanPropertyPath::SequencePath(a, b) => Box::new(
self.eval_path_from(&a, start, graph_name) self.eval_path_from(a, start, graph_name)
.flat_map_ok(move |middle| self.eval_path_from(&b, middle, graph_name)), .flat_map_ok(move |middle| self.eval_path_from(b, middle, graph_name)),
), ),
PlanPropertyPath::AlternativePath(a, b) => Box::new( PlanPropertyPath::AlternativePath(a, b) => Box::new(
self.eval_path_from(&a, start, graph_name) self.eval_path_from(a, start, graph_name)
.chain(self.eval_path_from(&b, start, graph_name)), .chain(self.eval_path_from(b, start, graph_name)),
), ),
PlanPropertyPath::ZeroOrMorePath(p) => { PlanPropertyPath::ZeroOrMorePath(p) => {
Box::new(transitive_closure(Some(Ok(start)), move |e| { Box::new(transitive_closure(Some(Ok(start)), move |e| {
@ -577,16 +577,21 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
move |e| self.eval_path_from(p, e, graph_name), move |e| self.eval_path_from(p, e, graph_name),
)), )),
PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate( PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate(
once(Ok(start)).chain(self.eval_path_from(&p, start, graph_name)), once(Ok(start)).chain(self.eval_path_from(p, start, graph_name)),
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => Box::new( PlanPropertyPath::NegatedPropertySet(ps) => Box::new(
self.dataset self.dataset
.quads_for_pattern(Some(start), None, None, Some(graph_name)) .quads_for_pattern(Some(start), None, None, Some(graph_name))
.filter(move |t| match t { .filter_map(move |t| match t {
Ok(t) => !ps.contains(&t.predicate), Ok(t) => {
Err(_) => true, if ps.contains(&t.predicate) {
}) None
.map(|t| Ok(t?.object)), } else {
Some(Ok(t.object))
}
}
Err(e) => Some(Err(e)),
}),
), ),
} }
} }
@ -606,14 +611,14 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
.quads_for_pattern(None, Some(*p), Some(end), Some(graph_name)) .quads_for_pattern(None, Some(*p), Some(end), Some(graph_name))
.map(|t| Ok(t?.subject)), .map(|t| Ok(t?.subject)),
), ),
PlanPropertyPath::InversePath(p) => self.eval_path_from(&p, end, graph_name), PlanPropertyPath::InversePath(p) => self.eval_path_from(p, end, graph_name),
PlanPropertyPath::SequencePath(a, b) => Box::new( PlanPropertyPath::SequencePath(a, b) => Box::new(
self.eval_path_to(&b, end, graph_name) self.eval_path_to(b, end, graph_name)
.flat_map_ok(move |middle| self.eval_path_to(&a, middle, graph_name)), .flat_map_ok(move |middle| self.eval_path_to(a, middle, graph_name)),
), ),
PlanPropertyPath::AlternativePath(a, b) => Box::new( PlanPropertyPath::AlternativePath(a, b) => Box::new(
self.eval_path_to(&a, end, graph_name) self.eval_path_to(a, end, graph_name)
.chain(self.eval_path_to(&b, end, graph_name)), .chain(self.eval_path_to(b, end, graph_name)),
), ),
PlanPropertyPath::ZeroOrMorePath(p) => { PlanPropertyPath::ZeroOrMorePath(p) => {
Box::new(transitive_closure(Some(Ok(end)), move |e| { Box::new(transitive_closure(Some(Ok(end)), move |e| {
@ -625,16 +630,21 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
move |e| self.eval_path_to(p, e, graph_name), move |e| self.eval_path_to(p, e, graph_name),
)), )),
PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate( PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate(
once(Ok(end)).chain(self.eval_path_to(&p, end, graph_name)), once(Ok(end)).chain(self.eval_path_to(p, end, graph_name)),
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => Box::new( PlanPropertyPath::NegatedPropertySet(ps) => Box::new(
self.dataset self.dataset
.quads_for_pattern(None, None, Some(end), Some(graph_name)) .quads_for_pattern(None, None, Some(end), Some(graph_name))
.filter(move |t| match t { .filter_map(move |t| match t {
Ok(t) => !ps.contains(&t.predicate), Ok(t) => {
Err(_) => true, if ps.contains(&t.predicate) {
}) None
.map(|t| Ok(t?.subject)), } else {
Some(Ok(t.subject))
}
}
Err(e) => Some(Err(e)),
}),
), ),
} }
} }
@ -654,19 +664,19 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
.map(|t| t.map(|t| (t.subject, t.object))), .map(|t| t.map(|t| (t.subject, t.object))),
), ),
PlanPropertyPath::InversePath(p) => Box::new( PlanPropertyPath::InversePath(p) => Box::new(
self.eval_open_path(&p, graph_name) self.eval_open_path(p, graph_name)
.map(|t| t.map(|(s, o)| (o, s))), .map(|t| t.map(|(s, o)| (o, s))),
), ),
PlanPropertyPath::SequencePath(a, b) => Box::new( PlanPropertyPath::SequencePath(a, b) => Box::new(
self.eval_open_path(&a, graph_name) self.eval_open_path(a, graph_name)
.flat_map_ok(move |(start, middle)| { .flat_map_ok(move |(start, middle)| {
self.eval_path_from(&b, middle, graph_name) self.eval_path_from(b, middle, graph_name)
.map(move |end| Ok((start, end?))) .map(move |end| Ok((start, end?)))
}), }),
), ),
PlanPropertyPath::AlternativePath(a, b) => Box::new( PlanPropertyPath::AlternativePath(a, b) => Box::new(
self.eval_open_path(&a, graph_name) self.eval_open_path(a, graph_name)
.chain(self.eval_open_path(&b, graph_name)), .chain(self.eval_open_path(b, graph_name)),
), ),
PlanPropertyPath::ZeroOrMorePath(p) => Box::new(transitive_closure( PlanPropertyPath::ZeroOrMorePath(p) => Box::new(transitive_closure(
self.get_subject_or_object_identity_pairs(graph_name), //TODO: avoid to inject everything self.get_subject_or_object_identity_pairs(graph_name), //TODO: avoid to inject everything
@ -684,16 +694,21 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
)), )),
PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate( PlanPropertyPath::ZeroOrOnePath(p) => Box::new(hash_deduplicate(
self.get_subject_or_object_identity_pairs(graph_name) self.get_subject_or_object_identity_pairs(graph_name)
.chain(self.eval_open_path(&p, graph_name)), .chain(self.eval_open_path(p, graph_name)),
)), )),
PlanPropertyPath::NegatedPropertySet(ps) => Box::new( PlanPropertyPath::NegatedPropertySet(ps) => Box::new(
self.dataset self.dataset
.quads_for_pattern(None, None, None, Some(graph_name)) .quads_for_pattern(None, None, None, Some(graph_name))
.filter(move |t| match t { .filter_map(move |t| match t {
Ok(t) => !ps.contains(&t.predicate), Ok(t) => {
Err(_) => true, if ps.contains(&t.predicate) {
}) None
.map(|t| t.map(|t| (t.subject, t.object))), } else {
Some(Ok((t.subject, t.object)))
}
}
Err(e) => Some(Err(e)),
}),
), ),
} }
} }
@ -708,6 +723,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
.map(|e| e.map(|e| (e, e))) .map(|e| e.map(|e| (e, e)))
} }
#[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)]
fn eval_expression<'b>( fn eval_expression<'b>(
&'b self, &'b self,
expression: &PlanExpression, expression: &PlanExpression,
@ -1056,7 +1072,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
self.to_string_and_language(self.eval_expression(arg, tuple)?)?; self.to_string_and_language(self.eval_expression(arg, tuple)?)?;
let replacement = let replacement =
self.to_simple_string(self.eval_expression(replacement, tuple)?)?; self.to_simple_string(self.eval_expression(replacement, tuple)?)?;
self.build_plain_literal(&regex.replace_all(&text, &replacement as &str), language) self.build_plain_literal(&regex.replace_all(&text, replacement.as_str()), language)
} }
PlanExpression::UCase(e) => { PlanExpression::UCase(e) => {
let (value, language) = let (value, language) =
@ -1073,7 +1089,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
self.eval_expression(arg1, tuple)?, self.eval_expression(arg1, tuple)?,
self.eval_expression(arg2, tuple)?, self.eval_expression(arg2, tuple)?,
)?; )?;
Some((&arg1).starts_with(&arg2 as &str).into()) Some((&arg1).starts_with(arg2.as_str()).into())
} }
PlanExpression::EncodeForURI(ltrl) => { PlanExpression::EncodeForURI(ltrl) => {
let ltlr = self.to_string(self.eval_expression(ltrl, tuple)?)?; let ltlr = self.to_string(self.eval_expression(ltrl, tuple)?)?;
@ -1107,21 +1123,21 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
self.eval_expression(arg1, tuple)?, self.eval_expression(arg1, tuple)?,
self.eval_expression(arg2, tuple)?, self.eval_expression(arg2, tuple)?,
)?; )?;
Some((&arg1).ends_with(&arg2 as &str).into()) Some((&arg1).ends_with(arg2.as_str()).into())
} }
PlanExpression::Contains(arg1, arg2) => { PlanExpression::Contains(arg1, arg2) => {
let (arg1, arg2, _) = self.to_argument_compatible_strings( let (arg1, arg2, _) = self.to_argument_compatible_strings(
self.eval_expression(arg1, tuple)?, self.eval_expression(arg1, tuple)?,
self.eval_expression(arg2, tuple)?, self.eval_expression(arg2, tuple)?,
)?; )?;
Some((&arg1).contains(&arg2 as &str).into()) Some((&arg1).contains(arg2.as_str()).into())
} }
PlanExpression::StrBefore(arg1, arg2) => { PlanExpression::StrBefore(arg1, arg2) => {
let (arg1, arg2, language) = self.to_argument_compatible_strings( let (arg1, arg2, language) = self.to_argument_compatible_strings(
self.eval_expression(arg1, tuple)?, self.eval_expression(arg1, tuple)?,
self.eval_expression(arg2, tuple)?, self.eval_expression(arg2, tuple)?,
)?; )?;
if let Some(position) = (&arg1).find(&arg2 as &str) { if let Some(position) = (&arg1).find(arg2.as_str()) {
self.build_plain_literal(&arg1[..position], language) self.build_plain_literal(&arg1[..position], language)
} else { } else {
Some(ENCODED_EMPTY_STRING_LITERAL) Some(ENCODED_EMPTY_STRING_LITERAL)
@ -1132,7 +1148,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
self.eval_expression(arg1, tuple)?, self.eval_expression(arg1, tuple)?,
self.eval_expression(arg2, tuple)?, self.eval_expression(arg2, tuple)?,
)?; )?;
if let Some(position) = (&arg1).find(&arg2 as &str) { if let Some(position) = (&arg1).find(arg2.as_str()) {
self.build_plain_literal(&arg1[position + arg2.len()..], language) self.build_plain_literal(&arg1[position + arg2.len()..], language)
} else { } else {
Some(ENCODED_EMPTY_STRING_LITERAL) Some(ENCODED_EMPTY_STRING_LITERAL)
@ -1294,7 +1310,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
EncodedTerm::DoubleLiteral(value) => Some(value.into()), EncodedTerm::DoubleLiteral(value) => Some(value.into()),
EncodedTerm::IntegerLiteral(value) => Some((value as f64).into()), EncodedTerm::IntegerLiteral(value) => Some((value as f64).into()),
EncodedTerm::DecimalLiteral(value) => Some(value.to_f64().into()), EncodedTerm::DecimalLiteral(value) => Some(value.to_f64().into()),
EncodedTerm::BooleanLiteral(value) => Some(if value { 1f64 } else { 0f64 }.into()), EncodedTerm::BooleanLiteral(value) => {
Some(if value { 1_f64 } else { 0_f64 }.into())
}
EncodedTerm::StringLiteral { value_id } => { EncodedTerm::StringLiteral { value_id } => {
parse_double_str(&*self.dataset.get_str(value_id).ok()??) parse_double_str(&*self.dataset.get_str(value_id).ok()??)
} }
@ -1305,7 +1323,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
EncodedTerm::DoubleLiteral(value) => Some((value as f32).into()), EncodedTerm::DoubleLiteral(value) => Some((value as f32).into()),
EncodedTerm::IntegerLiteral(value) => Some((value as f32).into()), EncodedTerm::IntegerLiteral(value) => Some((value as f32).into()),
EncodedTerm::DecimalLiteral(value) => Some(value.to_f32().into()), EncodedTerm::DecimalLiteral(value) => Some(value.to_f32().into()),
EncodedTerm::BooleanLiteral(value) => Some(if value { 1f32 } else { 0f32 }.into()), EncodedTerm::BooleanLiteral(value) => {
Some(if value { 1_f32 } else { 0_f32 }.into())
}
EncodedTerm::StringLiteral { value_id } => { EncodedTerm::StringLiteral { value_id } => {
parse_float_str(&*self.dataset.get_str(value_id).ok()??) parse_float_str(&*self.dataset.get_str(value_id).ok()??)
} }
@ -1376,8 +1396,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
match term { match term {
EncodedTerm::BooleanLiteral(value) => Some(value), EncodedTerm::BooleanLiteral(value) => Some(value),
EncodedTerm::StringLiteral { .. } => Some(term != ENCODED_EMPTY_STRING_LITERAL), EncodedTerm::StringLiteral { .. } => Some(term != ENCODED_EMPTY_STRING_LITERAL),
EncodedTerm::FloatLiteral(value) => Some(value != 0f32), EncodedTerm::FloatLiteral(value) => Some(value != 0_f32),
EncodedTerm::DoubleLiteral(value) => Some(value != 0f64), EncodedTerm::DoubleLiteral(value) => Some(value != 0_f64),
EncodedTerm::IntegerLiteral(value) => Some(value != 0), EncodedTerm::IntegerLiteral(value) => Some(value != 0),
EncodedTerm::DecimalLiteral(value) => Some(value != Decimal::default()), EncodedTerm::DecimalLiteral(value) => Some(value != Decimal::default()),
_ => None, _ => None,
@ -1528,8 +1548,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
tuple: &EncodedTuple, tuple: &EncodedTuple,
) -> Option<NumericBinaryOperands> { ) -> Option<NumericBinaryOperands> {
NumericBinaryOperands::new( NumericBinaryOperands::new(
self.eval_expression(&e1, tuple)?, self.eval_expression(e1, tuple)?,
self.eval_expression(&e2, tuple)?, self.eval_expression(e2, tuple)?,
) )
} }
@ -1596,7 +1616,11 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
})) }))
} }
#[allow(clippy::float_cmp)] #[allow(
clippy::float_cmp,
clippy::cast_possible_truncation,
clippy::cast_precision_loss
)]
fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<bool> { fn equals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<bool> {
match a { match a {
EncodedTerm::DefaultGraph EncodedTerm::DefaultGraph
@ -1717,6 +1741,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
} }
} }
#[allow(clippy::cast_precision_loss)]
fn partial_cmp_literals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<Ordering> { fn partial_cmp_literals(&self, a: EncodedTerm, b: EncodedTerm) -> Option<Ordering> {
match a { match a {
EncodedTerm::StringLiteral { value_id: a } => { EncodedTerm::StringLiteral { value_id: a } => {
@ -1801,7 +1826,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
tuple: &EncodedTuple, tuple: &EncodedTuple,
) -> Option<EncodedTerm> { ) -> Option<EncodedTerm> {
let input = self.to_simple_string(self.eval_expression(arg, tuple)?)?; let input = self.to_simple_string(self.eval_expression(arg, tuple)?)?;
let hash = hex::encode(H::new().chain(&input as &str).result()); let hash = hex::encode(H::new().chain(input.as_str()).result());
self.build_string_literal(&hash) self.build_string_literal(&hash)
} }
} }
@ -1821,6 +1846,7 @@ enum NumericBinaryOperands {
} }
impl NumericBinaryOperands { impl NumericBinaryOperands {
#[allow(clippy::cast_precision_loss)]
fn new(a: EncodedTerm, b: EncodedTerm) -> Option<Self> { fn new(a: EncodedTerm, b: EncodedTerm) -> Option<Self> {
match (a, b) { match (a, b) {
(EncodedTerm::FloatLiteral(v1), EncodedTerm::FloatLiteral(v2)) => { (EncodedTerm::FloatLiteral(v1), EncodedTerm::FloatLiteral(v2)) => {

@ -31,7 +31,7 @@ pub use crate::sparql::model::Variable;
/// A prepared [SPARQL query](https://www.w3.org/TR/sparql11-query/) /// A prepared [SPARQL query](https://www.w3.org/TR/sparql11-query/)
pub trait PreparedQuery { pub trait PreparedQuery {
/// Evaluates the query and returns its results /// Evaluates the query and returns its results
fn exec(&self) -> Result<QueryResult>; fn exec(&self) -> Result<QueryResult<'_>>;
} }
/// An implementation of `PreparedQuery` for internal use /// An implementation of `PreparedQuery` for internal use
@ -59,7 +59,7 @@ enum SimplePreparedQueryAction<S: StoreConnection> {
} }
impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> { impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
pub(crate) fn new(connection: S, query: &str, options: QueryOptions) -> Result<Self> { pub(crate) fn new(connection: S, query: &str, options: QueryOptions<'_>) -> Result<Self> {
let dataset = DatasetView::new(connection, options.default_graph_as_union); let dataset = DatasetView::new(connection, options.default_graph_as_union);
Ok(Self(match read_sparql_query(query, options.base_iri)? { Ok(Self(match read_sparql_query(query, options.base_iri)? {
QueryVariants::Select { QueryVariants::Select {
@ -110,11 +110,11 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
})) }))
} }
/// Builds SimplePreparedQuery from an existing `GraphPattern`. This is used to support federated queries via `SERVICE` clauses /// Builds `SimplePreparedQuery` from an existing `GraphPattern`. This is used to support federated queries via `SERVICE` clauses
pub(crate) fn new_from_pattern( pub(crate) fn new_from_pattern(
connection: S, connection: S,
pattern: &GraphPattern, pattern: &GraphPattern,
options: QueryOptions, options: QueryOptions<'_>,
) -> Result<Self> { ) -> Result<Self> {
let dataset = DatasetView::new(connection, options.default_graph_as_union); let dataset = DatasetView::new(connection, options.default_graph_as_union);
let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?; let (plan, variables) = PlanBuilder::build(dataset.encoder(), pattern)?;
@ -132,23 +132,21 @@ impl<'a, S: StoreConnection + 'a> SimplePreparedQuery<S> {
} }
impl<S: StoreConnection> PreparedQuery for SimplePreparedQuery<S> { impl<S: StoreConnection> PreparedQuery for SimplePreparedQuery<S> {
fn exec(&self) -> Result<QueryResult> { fn exec(&self) -> Result<QueryResult<'_>> {
match &self.0 { match &self.0 {
SimplePreparedQueryAction::Select { SimplePreparedQueryAction::Select {
plan, plan,
variables, variables,
evaluator, evaluator,
} => evaluator.evaluate_select_plan(&plan, &variables), } => evaluator.evaluate_select_plan(plan, variables),
SimplePreparedQueryAction::Ask { plan, evaluator } => { SimplePreparedQueryAction::Ask { plan, evaluator } => evaluator.evaluate_ask_plan(plan),
evaluator.evaluate_ask_plan(&plan)
}
SimplePreparedQueryAction::Construct { SimplePreparedQueryAction::Construct {
plan, plan,
construct, construct,
evaluator, evaluator,
} => evaluator.evaluate_construct_plan(&plan, &construct), } => evaluator.evaluate_construct_plan(plan, construct),
SimplePreparedQueryAction::Describe { plan, evaluator } => { SimplePreparedQueryAction::Describe { plan, evaluator } => {
evaluator.evaluate_describe_plan(&plan) evaluator.evaluate_describe_plan(plan)
} }
} }
} }
@ -211,7 +209,7 @@ impl<'a> QueryOptions<'a> {
} }
/// Consider the union of all graphs in the repository as the default graph /// Consider the union of all graphs in the repository as the default graph
pub fn with_default_graph_as_union(mut self) -> Self { pub const fn with_default_graph_as_union(mut self) -> Self {
self.default_graph_as_union = true; self.default_graph_as_union = true;
self self
} }

@ -8,7 +8,8 @@ mod grammar {
clippy::cognitive_complexity, clippy::cognitive_complexity,
clippy::many_single_char_names, clippy::many_single_char_names,
clippy::type_complexity, clippy::type_complexity,
ellipsis_inclusive_range_patterns ellipsis_inclusive_range_patterns,
elided_lifetimes_in_paths
)] )]
use crate::model::*; use crate::model::*;

@ -165,11 +165,11 @@ impl PlanNode {
set.insert(*position); set.insert(*position);
child.add_maybe_bound_variables(set); child.add_maybe_bound_variables(set);
} }
PlanNode::Service { child, .. } => child.add_maybe_bound_variables(set), PlanNode::Service { child, .. }
PlanNode::Sort { child, .. } => child.add_maybe_bound_variables(set), | PlanNode::Sort { child, .. }
PlanNode::HashDeduplicate { child } => child.add_maybe_bound_variables(set), | PlanNode::HashDeduplicate { child }
PlanNode::Skip { child, .. } => child.add_maybe_bound_variables(set), | PlanNode::Skip { child, .. }
PlanNode::Limit { child, .. } => child.add_maybe_bound_variables(set), | PlanNode::Limit { child, .. } => child.add_maybe_bound_variables(set),
PlanNode::Project { mapping, child } => { PlanNode::Project { mapping, child } => {
let child_bound = child.maybe_bound_variables(); let child_bound = child.maybe_bound_variables();
for (child_i, output_i) in mapping.iter() { for (child_i, output_i) in mapping.iter() {
@ -374,7 +374,7 @@ impl EncodedTuple {
} }
pub fn contains(&self, index: usize) -> bool { pub fn contains(&self, index: usize) -> bool {
self.inner.get(index).map_or(false, |v| v.is_some()) self.inner.get(index).map_or(false, Option::is_some)
} }
pub fn get(&self, index: usize) -> Option<EncodedTerm> { pub fn get(&self, index: usize) -> Option<EncodedTerm> {

@ -96,7 +96,7 @@ impl<E: Encoder> PlanBuilder<E> {
} }
GraphPattern::Extend(p, v, e) => PlanNode::Extend { GraphPattern::Extend(p, v, e) => PlanNode::Extend {
child: Box::new(self.build_for_graph_pattern(p, variables, graph_name)?), child: Box::new(self.build_for_graph_pattern(p, variables, graph_name)?),
position: variable_key(variables, &v), position: variable_key(variables, v),
expression: self.build_for_expression(e, variables, graph_name)?, expression: self.build_for_expression(e, variables, graph_name)?,
}, },
GraphPattern::Minus(a, b) => PlanNode::AntiJoin { GraphPattern::Minus(a, b) => PlanNode::AntiJoin {
@ -398,11 +398,9 @@ impl<E: Encoder> PlanBuilder<E> {
variables, variables,
graph_name, graph_name,
)?)), )?)),
Function::Concat => PlanExpression::Concat(self.expression_list( Function::Concat => {
&parameters, PlanExpression::Concat(self.expression_list(parameters, variables, graph_name)?)
variables, }
graph_name,
)?),
Function::SubStr => PlanExpression::SubStr( Function::SubStr => PlanExpression::SubStr(
Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?), Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?),
Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?), Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?),
@ -528,11 +526,9 @@ impl<E: Encoder> PlanBuilder<E> {
variables, variables,
graph_name, graph_name,
)?)), )?)),
Function::Coalesce => PlanExpression::Coalesce(self.expression_list( Function::Coalesce => PlanExpression::Coalesce(
&parameters, self.expression_list(parameters, variables, graph_name)?,
variables, ),
graph_name,
)?),
Function::If => PlanExpression::If( Function::If => PlanExpression::If(
Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?), Box::new(self.build_for_expression(&parameters[0], variables, graph_name)?),
Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?), Box::new(self.build_for_expression(&parameters[1], variables, graph_name)?),
@ -767,41 +763,41 @@ impl<E: Encoder> PlanBuilder<E> {
Aggregation::Count(e, distinct) => PlanAggregation { Aggregation::Count(e, distinct) => PlanAggregation {
function: PlanAggregationFunction::Count, function: PlanAggregationFunction::Count,
parameter: match e { parameter: match e {
Some(e) => Some(self.build_for_expression(&e, variables, graph_name)?), Some(e) => Some(self.build_for_expression(e, variables, graph_name)?),
None => None, None => None,
}, },
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Sum(e, distinct) => PlanAggregation { Aggregation::Sum(e, distinct) => PlanAggregation {
function: PlanAggregationFunction::Sum, function: PlanAggregationFunction::Sum,
parameter: Some(self.build_for_expression(&e, variables, graph_name)?), parameter: Some(self.build_for_expression(e, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Min(e, distinct) => PlanAggregation { Aggregation::Min(e, distinct) => PlanAggregation {
function: PlanAggregationFunction::Min, function: PlanAggregationFunction::Min,
parameter: Some(self.build_for_expression(&e, variables, graph_name)?), parameter: Some(self.build_for_expression(e, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Max(e, distinct) => PlanAggregation { Aggregation::Max(e, distinct) => PlanAggregation {
function: PlanAggregationFunction::Max, function: PlanAggregationFunction::Max,
parameter: Some(self.build_for_expression(&e, variables, graph_name)?), parameter: Some(self.build_for_expression(e, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Avg(e, distinct) => PlanAggregation { Aggregation::Avg(e, distinct) => PlanAggregation {
function: PlanAggregationFunction::Avg, function: PlanAggregationFunction::Avg,
parameter: Some(self.build_for_expression(&e, variables, graph_name)?), parameter: Some(self.build_for_expression(e, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::Sample(e, distinct) => PlanAggregation { Aggregation::Sample(e, distinct) => PlanAggregation {
function: PlanAggregationFunction::Sample, function: PlanAggregationFunction::Sample,
parameter: Some(self.build_for_expression(&e, variables, graph_name)?), parameter: Some(self.build_for_expression(e, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
Aggregation::GroupConcat(e, distinct, separator) => PlanAggregation { Aggregation::GroupConcat(e, distinct, separator) => PlanAggregation {
function: PlanAggregationFunction::GroupConcat { function: PlanAggregationFunction::GroupConcat {
separator: separator.clone().unwrap_or_else(|| " ".to_string()), separator: separator.clone().unwrap_or_else(|| " ".to_string()),
}, },
parameter: Some(self.build_for_expression(&e, variables, graph_name)?), parameter: Some(self.build_for_expression(e, variables, graph_name)?),
distinct: *distinct, distinct: *distinct,
}, },
}) })
@ -897,12 +893,13 @@ impl<E: Encoder> PlanBuilder<E> {
from: &[Variable], from: &[Variable],
to: &mut Vec<Variable>, to: &mut Vec<Variable>,
) -> usize { ) -> usize {
if let Some(to_id) = to if let Some(to_id) = to.iter().enumerate().find_map(|(to_id, var)| {
.iter() if *var == from[from_id] {
.enumerate() Some(to_id)
.find(|(_, var)| *var == &from[from_id]) } else {
.map(|(to_id, _)| to_id) None
{ }
}) {
to_id to_id
} else { } else {
to.push(Variable::default()); to.push(Variable::default());

@ -944,7 +944,7 @@ BlankNode -> BlankNode =
if state.used_bnodes.contains(b) { if state.used_bnodes.contains(b) {
Err("Already used blank node id") Err("Already used blank node id")
} else { } else {
Ok(state.bnodes_map.entry(b.to_string()).or_insert_with(BlankNode::default).clone()) Ok(*state.bnodes_map.entry(b.to_string()).or_insert_with(BlankNode::default))
} }
} / } /
ANON { BlankNode::default() } ANON { BlankNode::default() }
@ -961,7 +961,9 @@ PNAME_NS -> &'input str = ns:$(PN_PREFIX?) ':' {
//[141] //[141]
PNAME_LN -> Iri<String> = ns:PNAME_NS local:$(PN_LOCAL) {? PNAME_LN -> Iri<String> = ns:PNAME_NS local:$(PN_LOCAL) {?
if let Some(iri) = state.namespaces.get(ns).map(|v| v.clone() + &unescape_pn_local(local)) { if let Some(base) = state.namespaces.get(ns) {
let mut iri = base.clone();
iri.push_str(&unescape_pn_local(local));
Iri::parse(iri).map_err(|_| "IRI parsing failed") Iri::parse(iri).map_err(|_| "IRI parsing failed")
} else { } else {
Err("Prefix not found") Err("Prefix not found")

@ -85,7 +85,7 @@ pub fn write_xml_results<W: Write>(results: QueryResult<'_>, sink: W) -> Result<
} }
writer.write_event(Event::Start(literal_tag))?; writer.write_event(Event::Start(literal_tag))?;
writer.write_event(Event::Text(BytesText::from_plain_str( writer.write_event(Event::Text(BytesText::from_plain_str(
&literal.value(), literal.value(),
)))?; )))?;
writer.write_event(Event::End(BytesEnd::borrowed(b"literal")))?; writer.write_event(Event::End(BytesEnd::borrowed(b"literal")))?;
} }
@ -202,7 +202,7 @@ pub fn read_xml_results<'a>(source: impl BufRead + 'a) -> Result<QueryResult<'a>
State::Head => { State::Head => {
if event.name() == b"variable" { if event.name() == b"variable" {
let name = event.attributes() let name = event.attributes()
.filter_map(|attr| attr.ok()) .filter_map(|v| v.ok())
.find(|attr| attr.key == b"name") .find(|attr| attr.key == b"name")
.ok_or_else(|| format_err!("No name attribute found for the <variable> tag"))?; .ok_or_else(|| format_err!("No name attribute found for the <variable> tag"))?;
variables.push(name.unescape_and_decode_value(&reader)?); variables.push(name.unescape_and_decode_value(&reader)?);
@ -314,7 +314,7 @@ impl<R: BufRead> ResultsIterator<R> {
if event.name() == b"binding" { if event.name() == b"binding" {
match event match event
.attributes() .attributes()
.filter_map(|attr| attr.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()?.to_vec()),

@ -659,12 +659,12 @@ impl StrContainer for MemoryTransaction<'_> {
impl StoreTransaction for MemoryTransaction<'_> { impl StoreTransaction for MemoryTransaction<'_> {
fn insert(&mut self, quad: &EncodedQuad) -> Result<()> { fn insert(&mut self, quad: &EncodedQuad) -> Result<()> {
self.ops.push(TransactionOp::Insert(quad.clone())); self.ops.push(TransactionOp::Insert(*quad));
Ok(()) Ok(())
} }
fn remove(&mut self, quad: &EncodedQuad) -> Result<()> { fn remove(&mut self, quad: &EncodedQuad) -> Result<()> {
self.ops.push(TransactionOp::Delete(quad.clone())); self.ops.push(TransactionOp::Delete(*quad));
Ok(()) Ok(())
} }

@ -83,14 +83,18 @@ impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
type Transaction = StoreRepositoryTransaction<S::Transaction>; type Transaction = StoreRepositoryTransaction<S::Transaction>;
type PreparedQuery = SimplePreparedQuery<S>; type PreparedQuery = SimplePreparedQuery<S>;
fn prepare_query(&self, query: &str, options: QueryOptions) -> Result<SimplePreparedQuery<S>> { fn prepare_query(
&self,
query: &str,
options: QueryOptions<'_>,
) -> Result<SimplePreparedQuery<S>> {
SimplePreparedQuery::new(self.inner.clone(), query, options) //TODO: avoid clone SimplePreparedQuery::new(self.inner.clone(), query, options) //TODO: avoid clone
} }
fn prepare_query_from_pattern( fn prepare_query_from_pattern(
&self, &self,
pattern: &GraphPattern, pattern: &GraphPattern,
options: QueryOptions, options: QueryOptions<'_>,
) -> Result<Self::PreparedQuery> { ) -> Result<Self::PreparedQuery> {
SimplePreparedQuery::new_from_pattern(self.inner.clone(), pattern, options) SimplePreparedQuery::new_from_pattern(self.inner.clone(), pattern, options)
//TODO: avoid clone //TODO: avoid clone
@ -154,13 +158,13 @@ impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
fn insert(&mut self, quad: &Quad) -> Result<()> { fn insert(&mut self, quad: &Quad) -> Result<()> {
let mut transaction = self.auto_transaction(); let mut transaction = self.auto_transaction();
transaction.insert(&quad)?; transaction.insert(quad)?;
transaction.inner.commit() transaction.inner.commit()
} }
fn remove(&mut self, quad: &Quad) -> Result<()> { fn remove(&mut self, quad: &Quad) -> Result<()> {
let mut transaction = self.auto_transaction(); let mut transaction = self.auto_transaction();
transaction.remove(&quad)?; transaction.remove(quad)?;
transaction.inner.commit() transaction.inner.commit()
} }
} }
@ -177,7 +181,7 @@ impl<T: StoreTransaction> RepositoryTransaction for StoreRepositoryTransaction<T
to_graph_name: Option<&NamedOrBlankNode>, to_graph_name: Option<&NamedOrBlankNode>,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let base_iri = base_iri.unwrap_or(&""); let base_iri = base_iri.unwrap_or("");
match syntax { match syntax {
GraphSyntax::NTriples => { GraphSyntax::NTriples => {
self.load_from_triple_parser(NTriplesParser::new(reader)?, to_graph_name) self.load_from_triple_parser(NTriplesParser::new(reader)?, to_graph_name)
@ -197,7 +201,7 @@ impl<T: StoreTransaction> RepositoryTransaction for StoreRepositoryTransaction<T
syntax: DatasetSyntax, syntax: DatasetSyntax,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let base_iri = base_iri.unwrap_or(&""); let base_iri = base_iri.unwrap_or("");
match syntax { match syntax {
DatasetSyntax::NQuads => self.load_from_quad_parser(NQuadsParser::new(reader)?), DatasetSyntax::NQuads => self.load_from_quad_parser(NQuadsParser::new(reader)?),
DatasetSyntax::TriG => self.load_from_quad_parser(TriGParser::new(reader, base_iri)?), DatasetSyntax::TriG => self.load_from_quad_parser(TriGParser::new(reader, base_iri)?),

@ -30,7 +30,7 @@ const XSD_TIME_ID: u128 = 0x7af4_6a16_1b02_35d7_9a79_07ba_3da9_48bb;
const XSD_DURATION_ID: u128 = 0x78ab_8431_984b_6b06_c42d_6271_b82e_487d; const XSD_DURATION_ID: u128 = 0x78ab_8431_984b_6b06_c42d_6271_b82e_487d;
pub fn get_str_id(value: &str) -> u128 { pub fn get_str_id(value: &str) -> u128 {
let mut id = [0 as u8; 16]; let mut id = [0; 16];
id.copy_from_slice(&Md5::new().chain(value).result()); id.copy_from_slice(&Md5::new().chain(value).result());
u128::from_le_bytes(id) u128::from_le_bytes(id)
} }
@ -465,7 +465,7 @@ impl From<&Term> for EncodedTerm {
} }
} }
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub struct EncodedQuad { pub struct EncodedQuad {
pub subject: EncodedTerm, pub subject: EncodedTerm,
pub predicate: EncodedTerm, pub predicate: EncodedTerm,
@ -474,7 +474,7 @@ pub struct EncodedQuad {
} }
impl EncodedQuad { impl EncodedQuad {
pub fn new( pub const fn new(
subject: EncodedTerm, subject: EncodedTerm,
predicate: EncodedTerm, predicate: EncodedTerm,
object: EncodedTerm, object: EncodedTerm,
@ -872,7 +872,7 @@ pub trait Encoder {
predicate: self.encode_named_node(quad.predicate())?, predicate: self.encode_named_node(quad.predicate())?,
object: self.encode_term(quad.object())?, object: self.encode_term(quad.object())?,
graph_name: match quad.graph_name() { graph_name: match quad.graph_name() {
Some(graph_name) => self.encode_named_or_blank_node(&graph_name)?, Some(graph_name) => self.encode_named_or_blank_node(graph_name)?,
None => ENCODED_DEFAULT_GRAPH, None => ENCODED_DEFAULT_GRAPH,
}, },
}) })
@ -891,19 +891,19 @@ pub trait Encoder {
}) })
} }
fn encode_rio_named_node(&mut self, named_node: rio::NamedNode) -> Result<EncodedTerm>; fn encode_rio_named_node(&mut self, named_node: rio::NamedNode<'_>) -> Result<EncodedTerm>;
fn encode_rio_blank_node( fn encode_rio_blank_node(
&mut self, &mut self,
blank_node: rio::BlankNode, blank_node: rio::BlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm>; ) -> Result<EncodedTerm>;
fn encode_rio_literal(&mut self, literal: rio::Literal) -> Result<EncodedTerm>; fn encode_rio_literal(&mut self, literal: rio::Literal<'_>) -> Result<EncodedTerm>;
fn encode_rio_named_or_blank_node( fn encode_rio_named_or_blank_node(
&mut self, &mut self,
term: rio::NamedOrBlankNode, term: rio::NamedOrBlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm> { ) -> Result<EncodedTerm> {
match term { match term {
@ -916,7 +916,7 @@ pub trait Encoder {
fn encode_rio_term( fn encode_rio_term(
&mut self, &mut self,
term: rio::Term, term: rio::Term<'_>,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm> { ) -> Result<EncodedTerm> {
match term { match term {
@ -928,7 +928,7 @@ pub trait Encoder {
fn encode_rio_quad( fn encode_rio_quad(
&mut self, &mut self,
quad: rio::Quad, quad: rio::Quad<'_>,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedQuad> { ) -> Result<EncodedQuad> {
Ok(EncodedQuad { Ok(EncodedQuad {
@ -944,7 +944,7 @@ pub trait Encoder {
fn encode_rio_triple_in_graph( fn encode_rio_triple_in_graph(
&mut self, &mut self,
triple: rio::Triple, triple: rio::Triple<'_>,
graph_name: EncodedTerm, graph_name: EncodedTerm,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedQuad> { ) -> Result<EncodedQuad> {
@ -958,7 +958,7 @@ pub trait Encoder {
} }
impl<S: StrContainer> Encoder for S { impl<S: StrContainer> Encoder for S {
fn encode_rio_named_node(&mut self, named_node: rio::NamedNode) -> Result<EncodedTerm> { fn encode_rio_named_node(&mut self, named_node: rio::NamedNode<'_>) -> Result<EncodedTerm> {
let iri_id = get_str_id(named_node.iri); let iri_id = get_str_id(named_node.iri);
self.insert_str(iri_id, named_node.iri)?; self.insert_str(iri_id, named_node.iri)?;
Ok(EncodedTerm::NamedNode { iri_id }) Ok(EncodedTerm::NamedNode { iri_id })
@ -966,7 +966,7 @@ impl<S: StrContainer> Encoder for S {
fn encode_rio_blank_node( fn encode_rio_blank_node(
&mut self, &mut self,
blank_node: rio::BlankNode, blank_node: rio::BlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>, bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm> { ) -> Result<EncodedTerm> {
Ok(if let Some(id) = bnodes_map.get(blank_node.id) { Ok(if let Some(id) = bnodes_map.get(blank_node.id) {
@ -978,7 +978,7 @@ impl<S: StrContainer> Encoder for S {
}) })
} }
fn encode_rio_literal(&mut self, literal: rio::Literal) -> Result<EncodedTerm> { fn encode_rio_literal(&mut self, literal: rio::Literal<'_>) -> Result<EncodedTerm> {
Ok(match literal { Ok(match literal {
rio::Literal::Simple { value } => { rio::Literal::Simple { value } => {
let value_id = get_str_id(value); let value_id = get_str_id(value);

@ -59,8 +59,6 @@ const GSPO_CF: &str = "gspo";
const GPOS_CF: &str = "gpos"; const GPOS_CF: &str = "gpos";
const GOSP_CF: &str = "gosp"; const GOSP_CF: &str = "gosp";
const EMPTY_BUF: [u8; 0] = [0 as u8; 0];
//TODO: indexes for the default graph and indexes for the named graphs (no more Optional and space saving) //TODO: indexes for the default graph and indexes for the named graphs (no more Optional and space saving)
const COLUMN_FAMILIES: [&str; 7] = [ const COLUMN_FAMILIES: [&str; 7] = [
@ -524,32 +522,32 @@ impl RocksDbStoreInnerTransaction<'_> {
fn insert(&mut self, quad: &EncodedQuad) -> Result<()> { fn insert(&mut self, quad: &EncodedQuad) -> Result<()> {
self.buffer.write_spog_quad(quad)?; self.buffer.write_spog_quad(quad)?;
self.batch self.batch
.put_cf(self.connection.spog_cf, &self.buffer, &EMPTY_BUF)?; .put_cf(self.connection.spog_cf, &self.buffer, &[])?;
self.buffer.clear(); self.buffer.clear();
self.buffer.write_posg_quad(quad)?; self.buffer.write_posg_quad(quad)?;
self.batch self.batch
.put_cf(self.connection.posg_cf, &self.buffer, &EMPTY_BUF)?; .put_cf(self.connection.posg_cf, &self.buffer, &[])?;
self.buffer.clear(); self.buffer.clear();
self.buffer.write_ospg_quad(quad)?; self.buffer.write_ospg_quad(quad)?;
self.batch self.batch
.put_cf(self.connection.ospg_cf, &self.buffer, &EMPTY_BUF)?; .put_cf(self.connection.ospg_cf, &self.buffer, &[])?;
self.buffer.clear(); self.buffer.clear();
self.buffer.write_gspo_quad(quad)?; self.buffer.write_gspo_quad(quad)?;
self.batch self.batch
.put_cf(self.connection.gspo_cf, &self.buffer, &EMPTY_BUF)?; .put_cf(self.connection.gspo_cf, &self.buffer, &[])?;
self.buffer.clear(); self.buffer.clear();
self.buffer.write_gpos_quad(quad)?; self.buffer.write_gpos_quad(quad)?;
self.batch self.batch
.put_cf(self.connection.gpos_cf, &self.buffer, &EMPTY_BUF)?; .put_cf(self.connection.gpos_cf, &self.buffer, &[])?;
self.buffer.clear(); self.buffer.clear();
self.buffer.write_gosp_quad(quad)?; self.buffer.write_gosp_quad(quad)?;
self.batch self.batch
.put_cf(self.connection.gosp_cf, &self.buffer, &EMPTY_BUF)?; .put_cf(self.connection.gosp_cf, &self.buffer, &[])?;
self.buffer.clear(); self.buffer.clear();
Ok(()) Ok(())

Loading…
Cancel
Save