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(())
//! ```
#![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;
mod repository;
@ -42,7 +106,7 @@ pub(crate) mod store;
mod syntax;
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::RepositoryConnection;
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.
/// `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 {
id: u128,
str: [u8; 32],
@ -34,7 +34,7 @@ impl BlankNode {
}
/// Returns the underlying ID of this blank node
pub(crate) fn id(&self) -> u128 {
pub(crate) const fn id(&self) -> u128 {
self.id
}
}

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

@ -48,7 +48,7 @@ fn split_hash_buckets<'a>(
new_bnodes_by_hash.insert(hash, bnodes); // Nothing to improve
} else {
for bnode in bnodes {
let mut starts = vec![NamedOrBlankNode::from(bnode.clone())];
let mut starts = vec![NamedOrBlankNode::from(*bnode)];
for _ in 0..distance {
let mut new_starts = Vec::default();
for s in starts {
@ -71,7 +71,7 @@ fn split_hash_buckets<'a>(
hash.hash(&mut hasher); // We start with the previous 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 po in predicate_objects_for_subject(graph, start) {
match &po.object {
@ -86,7 +86,7 @@ fn split_hash_buckets<'a>(
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();
for start in &term_starts {
for sp in subject_predicates_for_object(graph, start) {
@ -123,7 +123,7 @@ fn build_and_check_containment_from_hashes<'a>(
) -> bool {
if let Some((a_node, remaining_a_node)) = current_a_nodes.split_last() {
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);
a_to_b_mapping.insert(a_node, b_node);
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));
for distance in 0..5 {
let max_size = a_bnodes_by_hash
.values()
.map(|l| l.len())
.max()
.unwrap_or(0);
let max_size = a_bnodes_by_hash.values().map(Vec::len).max().unwrap_or(0);
if max_size < 2 {
break; // We only have small buckets
}

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

@ -162,7 +162,7 @@ impl 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
}
@ -172,7 +172,7 @@ impl 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
}
@ -182,7 +182,7 @@ impl 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
}
@ -244,7 +244,7 @@ impl Quad {
}
/// 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
}
@ -254,7 +254,7 @@ impl Quad {
}
/// 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
}
@ -264,7 +264,7 @@ impl Quad {
}
/// 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
}
@ -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)
pub fn graph_name(&self) -> &Option<NamedOrBlankNode> {
pub const fn graph_name(&self) -> &Option<NamedOrBlankNode> {
&self.graph_name
}

@ -26,7 +26,7 @@ impl DateTime {
timezone_offset: Option<TimezoneOffset>,
) -> Result<Self, DateTimeError> {
Ok(Self {
timestamp: Timestamp::new(DateTimeSevenPropertyModel {
timestamp: Timestamp::new(&DateTimeSevenPropertyModel {
year: Some(year),
month: Some(month),
day: Some(day),
@ -49,56 +49,7 @@ impl DateTime {
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)
pub fn year(&self) -> i64 {
self.timestamp.year()
@ -168,7 +119,8 @@ impl DateTime {
})
} else {
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 {
Some(Self {
timestamp: Timestamp::new(date_time_plus_duration(-rhs, self.properties())?)
timestamp: Timestamp::new(&date_time_plus_duration(-rhs, &self.properties())?)
.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.
#[derive(Eq, PartialEq, PartialOrd, Debug, Clone, Copy, Hash)]
pub struct Time {
@ -206,7 +205,7 @@ impl Time {
hour = 0;
}
Ok(Self {
timestamp: Timestamp::new(DateTimeSevenPropertyModel {
timestamp: Timestamp::new(&DateTimeSevenPropertyModel {
year: None,
month: None,
day: None,
@ -223,46 +222,7 @@ impl Time {
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)
pub fn hour(&self) -> u8 {
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.
#[derive(Eq, PartialEq, PartialOrd, Debug, Clone, Copy, Hash)]
pub struct Date {
@ -349,7 +346,7 @@ impl Date {
timezone_offset: Option<TimezoneOffset>,
) -> Result<Self, DateTimeError> {
Ok(Self {
timestamp: Timestamp::new(DateTimeSevenPropertyModel {
timestamp: Timestamp::new(&DateTimeSevenPropertyModel {
year: Some(year),
month: Some(month),
day: Some(day),
@ -366,44 +363,7 @@ impl Date {
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)
pub fn year(&self) -> i64 {
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)]
pub struct TimezoneOffset {
offset: i16, // in minute with respect to UTC
@ -468,6 +463,10 @@ impl TimezoneOffset {
offset: i16::from_le_bytes(bytes),
}
}
pub fn to_le_bytes(self) -> [u8; 2] {
self.offset.to_le_bytes()
}
}
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)
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
struct DateTimeSevenPropertyModel {
@ -564,7 +557,7 @@ impl Hash for Timestamp {
}
impl Timestamp {
fn new(props: DateTimeSevenPropertyModel) -> Result<Self, DateTimeError> {
fn new(props: &DateTimeSevenPropertyModel) -> Result<Self, DateTimeError> {
// Validation
if let (Some(day), Some(month)) = (props.day, props.month) {
// Constraint: Day-of-month Values
@ -585,14 +578,14 @@ impl Timestamp {
fn now() -> Result<Self, DateTimeError> {
Timestamp::new(
date_time_plus_duration(
&date_time_plus_duration(
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)?
.try_into()
.map_err(|_| DateTimeError {
kind: DateTimeErrorKind::Overflow,
})?,
DateTimeSevenPropertyModel {
&DateTimeSevenPropertyModel {
year: Some(1970),
month: 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) {
let mut days = (self.value.as_i128()
+ i128::from(
@ -697,6 +691,7 @@ impl Timestamp {
day
}
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
fn hour(&self) -> u8 {
(((self.value.as_i128()
+ i128::from(
@ -708,6 +703,7 @@ impl Timestamp {
/ 3600) as u8
}
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
fn minute(&self) -> u8 {
(((self.value.as_i128()
+ i128::from(
@ -723,7 +719,7 @@ impl Timestamp {
self.value.checked_rem_euclid(60).unwrap().abs()
}
fn timezone_offset(&self) -> Option<TimezoneOffset> {
const fn timezone_offset(&self) -> Option<TimezoneOffset> {
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
let yr = yr.checked_add(mo.checked_sub(1)?.checked_div(12)?.checked_sub(1)?)?;
let mo = u8::try_from(
12i64
12_i64
.checked_add(mo.checked_sub(1)?.checked_rem(12)?)?
.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
fn date_time_plus_duration(
du: Duration,
dt: DateTimeSevenPropertyModel,
dt: &DateTimeSevenPropertyModel,
) -> Option<DateTimeSevenPropertyModel> {
let yr = dt.year.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
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 mo = props.month.unwrap_or(12);
let da = props

@ -28,13 +28,14 @@ pub struct Decimal {
impl Decimal {
/// Constructs the decimal i / 10^n
#[allow(clippy::cast_possible_truncation)]
pub fn new(i: i128, n: u32) -> Result<Self, DecimalOverflowError> {
if n > DECIMAL_PART_DIGITS as u32 {
//TODO: check if end with zeros?
return Err(DecimalOverflowError);
}
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),
}
}
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 {
@ -146,7 +291,7 @@ impl FromStr for Decimal {
_ => (1, 0),
};
let mut value = 0i128;
let mut value = 0_i128;
let mut with_before_dot = false;
while cursor < input.len() && b'0' <= input[cursor] && input[cursor] <= b'9' {
value = value
@ -246,7 +391,7 @@ impl From<DecimalOverflowError> for ParseDecimalError {
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Copy)]
pub struct DecimalOverflowError;
impl fmt::Display for DecimalOverflowError {
@ -259,6 +404,7 @@ impl Error for DecimalOverflowError {}
impl fmt::Display for Decimal {
/// Formats the decimal following its canonical representation
#[allow(clippy::cast_possible_truncation)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.value == 0 {
return if let Some(width) = f.width() {
@ -289,8 +435,7 @@ impl fmt::Display for Decimal {
.iter()
.cloned()
.enumerate()
.find(|(_, v)| *v != b'0')
.map(|(i, _)| i)
.find_map(|(i, v)| if v == b'0' { None } else { Some(i) })
.unwrap_or(40);
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 {
type Error = DecimalOverflowError;

@ -39,6 +39,72 @@ impl Duration {
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 {
@ -85,10 +151,10 @@ impl fmt::Display for Duration {
let m = ym % 12;
if y != 0 {
if m != 0 {
write!(f, "{}Y{}M", y, m)?;
} else {
if m == 0 {
write!(f, "{}Y", y)?;
} else {
write!(f, "{}Y{}M", y, m)?;
}
} else if m != 0 || ss == 0.into() {
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 {
type Output = Self;

@ -167,32 +167,32 @@ pub fn parse_value<'a, T>(
//TODO: check every computation
// [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)
}
// [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)
}
// [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)
}
// [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)
}
// [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)
}
// [11] duSecondFrag ::= (unsignedNoDecimalPtNumeral | unsignedDecimalPtNumeral) 'S'
fn du_second_frag(input: &str) -> XsdResult<Decimal> {
fn du_second_frag(input: &str) -> XsdResult<'_, Decimal> {
terminated(
map_res(
recognize(tuple((digit0, opt(preceded(char('.'), digit0))))),
@ -203,7 +203,7 @@ fn du_second_frag(input: &str) -> XsdResult<Decimal> {
}
// [12] duYearMonthFrag ::= (duYearFrag duMonthFrag?) | duMonthFrag
fn du_year_month_frag(input: &str) -> XsdResult<i64> {
fn du_year_month_frag(input: &str) -> XsdResult<'_, i64> {
alt((
map(tuple((du_year_frag, opt(du_month_frag))), |(y, m)| {
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)
fn du_time_frag(input: &str) -> XsdResult<Decimal> {
fn du_time_frag(input: &str) -> XsdResult<'_, Decimal> {
preceded(
char('T'),
alt((
@ -236,7 +236,7 @@ fn du_time_frag(input: &str) -> XsdResult<Decimal> {
}
// [14] duDayTimeFrag ::= (duDayFrag duTimeFrag?) | duTimeFrag
fn du_day_time_frag(input: &str) -> XsdResult<Decimal> {
fn du_day_time_frag(input: &str) -> XsdResult<'_, Decimal> {
alt((
map_res(tuple((du_day_frag, opt(du_time_frag))), |(d, t)| {
Decimal::from(d)
@ -250,7 +250,7 @@ fn du_day_time_frag(input: &str) -> XsdResult<Decimal> {
}
// [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(
tuple((
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?
pub fn date_time_lexical_rep(input: &str) -> XsdResult<DateTime> {
pub fn date_time_lexical_rep(input: &str) -> XsdResult<'_, DateTime> {
map_res(
tuple((
year_frag,
@ -301,7 +301,7 @@ pub fn date_time_lexical_rep(input: &str) -> XsdResult<DateTime> {
}
// [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(
tuple((
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
pub fn date_lexical_rep(input: &str) -> XsdResult<Date> {
pub fn date_lexical_rep(input: &str) -> XsdResult<'_, Date> {
map_res(
tuple((
year_frag,
@ -333,12 +333,12 @@ pub fn date_lexical_rep(input: &str) -> XsdResult<Date> {
}
// [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)
}
// [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(
recognize(tuple((
opt(char('-')),
@ -349,35 +349,36 @@ fn year_frag(input: &str) -> XsdResult<i64> {
}
// [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| {
parsed_u8_range(v, 1, 12)
})(input)
}
// [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| {
parsed_u8_range(v, 1, 31)
})(input)
}
// [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| {
parsed_u8_range(v, 0, 23)
})(input)
}
// [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| {
parsed_u8_range(v, 0, 59)
})(input)
}
// [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(
recognize(tuple((
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'+)?
fn end_of_day_frag(input: &str) -> XsdResult<(u8, u8, Decimal)> {
fn end_of_day_frag(input: &str) -> XsdResult<'_, (u8, u8, Decimal)> {
map(
recognize(tuple((
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')
fn timezone_frag(input: &str) -> XsdResult<TimezoneOffset> {
fn timezone_frag(input: &str) -> XsdResult<'_, TimezoneOffset> {
alt((
map(char('Z'), |_| TimezoneOffset::utc()),
map(

@ -84,13 +84,13 @@ pub trait RepositoryConnection: Clone {
/// }
/// # 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.
fn prepare_query_from_pattern(
&self,
graph_pattern: &GraphPattern,
options: QueryOptions,
options: QueryOptions<'_>,
) -> Result<Self::PreparedQuery>;
/// 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 {
match self.0 {
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, "{{")?;
for i in 0..values.len() {
if let Some(ref val) = values[i] {
write!(f, " {} {} ", variables[i], val)?;
write!(f, " {} \u{2192} {} ", variables[i], val)?;
}
}
write!(f, "}}")?;
@ -712,7 +712,7 @@ impl GraphPattern {
}
GraphPattern::Extend(p, v, _) => {
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::Service(_, p, _) => p.add_visible_variables(vars),
@ -818,7 +818,7 @@ impl<'a> fmt::Display for SparqlGraphPattern<'a> {
f,
"{{ SELECT {} WHERE {{ {} }} GROUP BY {} }}",
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()))
.collect::<Vec<String>>()
.join(" "),
@ -963,13 +963,15 @@ impl fmt::Display for Aggregation {
match self {
Aggregation::Count(e, distinct) => {
if *distinct {
e.as_ref()
.map(|ex| write!(f, "COUNT(DISTINCT {})", ex))
.unwrap_or_else(|| write!(f, "COUNT(DISTINCT *)"))
if let Some(ex) = e {
write!(f, "COUNT(DISTINCT {})", ex)
} else {
write!(f, "COUNT(DISTINCT *)")
}
} else if let Some(ex) = e {
write!(f, "COUNT({})", ex)
} else {
e.as_ref()
.map(|ex| write!(f, "COUNT({})", ex))
.unwrap_or_else(|| write!(f, "COUNT(*)"))
write!(f, "COUNT(*)")
}
}
Aggregation::Sum(e, distinct) => {
@ -1009,31 +1011,25 @@ impl fmt::Display for Aggregation {
}
Aggregation::GroupConcat(e, distinct, sep) => {
if *distinct {
sep.as_ref()
.map(|s| {
write!(
f,
"Aggregation(Distinct({}), GroupConcat, {{\"separator\" → {}}})",
e,
fmt_str(s)
)
})
.unwrap_or_else(|| {
write!(f, "Aggregation(Distinct({}), GroupConcat, {{}})", e)
})
if let Some(s) = sep {
write!(
f,
"Aggregation(Distinct({}), GroupConcat, {{\"separator\" \u{2192} {}}})",
e,
fmt_str(s)
)
} 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 {
sep.as_ref()
.map(|s| {
write!(
f,
"Aggregation({}, GroupConcat, {{\"separator\" → {}}})",
e,
fmt_str(s)
)
})
.unwrap_or_else(|| {
write!(f, "Aggregation(Distinct({}), GroupConcat, {{}})", e)
})
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 }
}
@ -1241,14 +1237,7 @@ impl fmt::Display for QueryVariants {
if let Some(base_iri) = base_iri {
writeln!(f, "BASE <{}>", base_iri)?;
}
write!(
f,
"{}",
SparqlGraphRootPattern {
algebra: &algebra,
dataset: &dataset
}
)
write!(f, "{}", SparqlGraphRootPattern { algebra, dataset })
}
QueryVariants::Construct {
construct,
@ -1269,7 +1258,7 @@ impl fmt::Display for QueryVariants {
.join(" . "),
dataset,
SparqlGraphRootPattern {
algebra: &algebra,
algebra,
dataset: &EMPTY_DATASET
}
)
@ -1287,7 +1276,7 @@ impl fmt::Display for QueryVariants {
"DESCRIBE * {} WHERE {{ {} }}",
dataset,
SparqlGraphRootPattern {
algebra: &algebra,
algebra,
dataset: &EMPTY_DATASET
}
)
@ -1305,7 +1294,7 @@ impl fmt::Display for QueryVariants {
"ASK {} WHERE {{ {} }}",
dataset,
SparqlGraphRootPattern {
algebra: &algebra,
algebra,
dataset: &EMPTY_DATASET
}
)

@ -153,10 +153,10 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
graph_name,
} => Box::new(self.eval_plan(&*child, from).flat_map_ok(move |tuple| {
let mut iter = self.dataset.quads_for_pattern(
get_pattern_value(&subject, &tuple),
get_pattern_value(&predicate, &tuple),
get_pattern_value(&object, &tuple),
get_pattern_value(&graph_name, &tuple),
get_pattern_value(subject, &tuple),
get_pattern_value(predicate, &tuple),
get_pattern_value(object, &tuple),
get_pattern_value(graph_name, &tuple),
);
if subject.is_var() && subject == predicate {
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 quad = quad?;
let mut new_tuple = tuple.clone();
put_pattern_value(&subject, quad.subject, &mut new_tuple);
put_pattern_value(&predicate, quad.predicate, &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(subject, quad.subject, &mut new_tuple);
put_pattern_value(predicate, quad.predicate, &mut new_tuple);
put_pattern_value(object, quad.object, &mut new_tuple);
put_pattern_value(graph_name, quad.graph_name, &mut new_tuple);
Ok(new_tuple)
}));
iter
@ -214,15 +214,16 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
object,
graph_name,
} => Box::new(self.eval_plan(&*child, from).flat_map_ok(move |tuple| {
let input_subject = get_pattern_value(&subject, &tuple);
let input_object = get_pattern_value(&object, &tuple);
let input_subject = get_pattern_value(subject, &tuple);
let input_object = get_pattern_value(object, &tuple);
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
} 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"
)))) as EncodedTuplesIterator<'_>;
))));
return result;
};
match (input_subject, input_object) {
(Some(input_subject), Some(input_object)) => Box::new(
@ -237,13 +238,12 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}
Err(error) => Some(Err(error)),
}),
)
as EncodedTuplesIterator<'_>,
),
(Some(input_subject), None) => Box::new(
self.eval_path_from(path, input_subject, input_graph_name)
.map(move |o| {
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)
}),
),
@ -251,7 +251,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
self.eval_path_to(path, input_object, input_graph_name)
.map(move |s| {
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)
}),
),
@ -259,8 +259,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
Box::new(self.eval_open_path(path, input_graph_name).map(move |so| {
let mut new_tuple = tuple.clone();
so.map(move |(s, o)| {
put_pattern_value(&subject, s, &mut new_tuple);
put_pattern_value(&object, o, &mut new_tuple);
put_pattern_value(subject, s, &mut new_tuple);
put_pattern_value(object, o, &mut new_tuple);
new_tuple
})
}))
@ -302,7 +302,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
right,
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();
unbind_variables(&mut filtered_from, &problem_vars);
let iter = LeftJoinIterator {
@ -326,7 +326,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
Box::new(self.eval_plan(&*child, from).filter(move |tuple| {
match tuple {
Ok(tuple) => eval
.eval_expression(&expression, tuple)
.eval_expression(expression, tuple)
.and_then(|term| eval.to_bool(term))
.unwrap_or(false),
Err(_) => true,
@ -335,7 +335,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
}
PlanNode::Union { children } => Box::new(UnionIterator {
eval: self,
plans: &children,
plans: children,
input: from,
current_iterator: Box::new(empty()),
current_plan: 0,
@ -348,7 +348,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
let eval = self;
Box::new(self.eval_plan(&*child, from).map(move |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)
}
Ok(tuple)
@ -370,14 +370,14 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
for comp in by {
match comp {
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::Less => return Ordering::Less,
Ordering::Equal => (),
}
}
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::Less => return Ordering::Greater,
Ordering::Equal => (),
@ -451,7 +451,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
aggregate
.parameter
.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,
) -> Result<EncodedTuplesIterator<'b>> {
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(self.encode_bindings(
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))
.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(
self.eval_path_from(&a, start, graph_name)
.flat_map_ok(move |middle| self.eval_path_from(&b, middle, graph_name)),
self.eval_path_from(a, start, graph_name)
.flat_map_ok(move |middle| self.eval_path_from(b, middle, graph_name)),
),
PlanPropertyPath::AlternativePath(a, b) => Box::new(
self.eval_path_from(&a, start, graph_name)
.chain(self.eval_path_from(&b, start, graph_name)),
self.eval_path_from(a, start, graph_name)
.chain(self.eval_path_from(b, start, graph_name)),
),
PlanPropertyPath::ZeroOrMorePath(p) => {
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),
)),
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(
self.dataset
.quads_for_pattern(Some(start), None, None, Some(graph_name))
.filter(move |t| match t {
Ok(t) => !ps.contains(&t.predicate),
Err(_) => true,
})
.map(|t| Ok(t?.object)),
.filter_map(move |t| match t {
Ok(t) => {
if ps.contains(&t.predicate) {
None
} 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))
.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(
self.eval_path_to(&b, end, graph_name)
.flat_map_ok(move |middle| self.eval_path_to(&a, middle, graph_name)),
self.eval_path_to(b, end, graph_name)
.flat_map_ok(move |middle| self.eval_path_to(a, middle, graph_name)),
),
PlanPropertyPath::AlternativePath(a, b) => Box::new(
self.eval_path_to(&a, end, graph_name)
.chain(self.eval_path_to(&b, end, graph_name)),
self.eval_path_to(a, end, graph_name)
.chain(self.eval_path_to(b, end, graph_name)),
),
PlanPropertyPath::ZeroOrMorePath(p) => {
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),
)),
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(
self.dataset
.quads_for_pattern(None, None, Some(end), Some(graph_name))
.filter(move |t| match t {
Ok(t) => !ps.contains(&t.predicate),
Err(_) => true,
})
.map(|t| Ok(t?.subject)),
.filter_map(move |t| match t {
Ok(t) => {
if ps.contains(&t.predicate) {
None
} 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))),
),
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))),
),
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)| {
self.eval_path_from(&b, middle, graph_name)
self.eval_path_from(b, middle, graph_name)
.map(move |end| Ok((start, end?)))
}),
),
PlanPropertyPath::AlternativePath(a, b) => Box::new(
self.eval_open_path(&a, graph_name)
.chain(self.eval_open_path(&b, graph_name)),
self.eval_open_path(a, graph_name)
.chain(self.eval_open_path(b, graph_name)),
),
PlanPropertyPath::ZeroOrMorePath(p) => Box::new(transitive_closure(
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(
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(
self.dataset
.quads_for_pattern(None, None, None, Some(graph_name))
.filter(move |t| match t {
Ok(t) => !ps.contains(&t.predicate),
Err(_) => true,
})
.map(|t| t.map(|t| (t.subject, t.object))),
.filter_map(move |t| match t {
Ok(t) => {
if ps.contains(&t.predicate) {
None
} 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)))
}
#[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)]
fn eval_expression<'b>(
&'b self,
expression: &PlanExpression,
@ -1056,7 +1072,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
self.to_string_and_language(self.eval_expression(arg, tuple)?)?;
let replacement =
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) => {
let (value, language) =
@ -1073,7 +1089,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
self.eval_expression(arg1, 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) => {
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(arg2, tuple)?,
)?;
Some((&arg1).ends_with(&arg2 as &str).into())
Some((&arg1).ends_with(arg2.as_str()).into())
}
PlanExpression::Contains(arg1, arg2) => {
let (arg1, arg2, _) = self.to_argument_compatible_strings(
self.eval_expression(arg1, tuple)?,
self.eval_expression(arg2, tuple)?,
)?;
Some((&arg1).contains(&arg2 as &str).into())
Some((&arg1).contains(arg2.as_str()).into())
}
PlanExpression::StrBefore(arg1, arg2) => {
let (arg1, arg2, language) = self.to_argument_compatible_strings(
self.eval_expression(arg1, 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)
} else {
Some(ENCODED_EMPTY_STRING_LITERAL)
@ -1132,7 +1148,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
self.eval_expression(arg1, 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)
} else {
Some(ENCODED_EMPTY_STRING_LITERAL)
@ -1294,7 +1310,9 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
EncodedTerm::DoubleLiteral(value) => Some(value.into()),
EncodedTerm::IntegerLiteral(value) => Some((value as 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 } => {
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::IntegerLiteral(value) => Some((value as 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 } => {
parse_float_str(&*self.dataset.get_str(value_id).ok()??)
}
@ -1376,8 +1396,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
match term {
EncodedTerm::BooleanLiteral(value) => Some(value),
EncodedTerm::StringLiteral { .. } => Some(term != ENCODED_EMPTY_STRING_LITERAL),
EncodedTerm::FloatLiteral(value) => Some(value != 0f32),
EncodedTerm::DoubleLiteral(value) => Some(value != 0f64),
EncodedTerm::FloatLiteral(value) => Some(value != 0_f32),
EncodedTerm::DoubleLiteral(value) => Some(value != 0_f64),
EncodedTerm::IntegerLiteral(value) => Some(value != 0),
EncodedTerm::DecimalLiteral(value) => Some(value != Decimal::default()),
_ => None,
@ -1528,8 +1548,8 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
tuple: &EncodedTuple,
) -> Option<NumericBinaryOperands> {
NumericBinaryOperands::new(
self.eval_expression(&e1, tuple)?,
self.eval_expression(&e2, tuple)?,
self.eval_expression(e1, 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> {
match a {
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> {
match a {
EncodedTerm::StringLiteral { value_id: a } => {
@ -1801,7 +1826,7 @@ impl<'a, S: StoreConnection + 'a> SimpleEvaluator<S> {
tuple: &EncodedTuple,
) -> Option<EncodedTerm> {
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)
}
}
@ -1821,6 +1846,7 @@ enum NumericBinaryOperands {
}
impl NumericBinaryOperands {
#[allow(clippy::cast_precision_loss)]
fn new(a: EncodedTerm, b: EncodedTerm) -> Option<Self> {
match (a, b) {
(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/)
pub trait PreparedQuery {
/// Evaluates the query and returns its results
fn exec(&self) -> Result<QueryResult>;
fn exec(&self) -> Result<QueryResult<'_>>;
}
/// An implementation of `PreparedQuery` for internal use
@ -59,7 +59,7 @@ enum SimplePreparedQueryAction<S: StoreConnection> {
}
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);
Ok(Self(match read_sparql_query(query, options.base_iri)? {
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(
connection: S,
pattern: &GraphPattern,
options: QueryOptions,
options: QueryOptions<'_>,
) -> Result<Self> {
let dataset = DatasetView::new(connection, options.default_graph_as_union);
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> {
fn exec(&self) -> Result<QueryResult> {
fn exec(&self) -> Result<QueryResult<'_>> {
match &self.0 {
SimplePreparedQueryAction::Select {
plan,
variables,
evaluator,
} => evaluator.evaluate_select_plan(&plan, &variables),
SimplePreparedQueryAction::Ask { plan, evaluator } => {
evaluator.evaluate_ask_plan(&plan)
}
} => evaluator.evaluate_select_plan(plan, variables),
SimplePreparedQueryAction::Ask { plan, evaluator } => evaluator.evaluate_ask_plan(plan),
SimplePreparedQueryAction::Construct {
plan,
construct,
evaluator,
} => evaluator.evaluate_construct_plan(&plan, &construct),
} => evaluator.evaluate_construct_plan(plan, construct),
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
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
}

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

@ -165,11 +165,11 @@ impl PlanNode {
set.insert(*position);
child.add_maybe_bound_variables(set);
}
PlanNode::Service { child, .. } => child.add_maybe_bound_variables(set),
PlanNode::Sort { child, .. } => child.add_maybe_bound_variables(set),
PlanNode::HashDeduplicate { child } => child.add_maybe_bound_variables(set),
PlanNode::Skip { child, .. } => child.add_maybe_bound_variables(set),
PlanNode::Limit { child, .. } => child.add_maybe_bound_variables(set),
PlanNode::Service { child, .. }
| PlanNode::Sort { child, .. }
| PlanNode::HashDeduplicate { child }
| PlanNode::Skip { child, .. }
| PlanNode::Limit { child, .. } => child.add_maybe_bound_variables(set),
PlanNode::Project { mapping, child } => {
let child_bound = child.maybe_bound_variables();
for (child_i, output_i) in mapping.iter() {
@ -374,7 +374,7 @@ impl EncodedTuple {
}
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> {

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

@ -944,7 +944,7 @@ BlankNode -> BlankNode =
if state.used_bnodes.contains(b) {
Err("Already used blank node id")
} 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() }
@ -961,7 +961,9 @@ PNAME_NS -> &'input str = ns:$(PN_PREFIX?) ':' {
//[141]
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")
} else {
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::Text(BytesText::from_plain_str(
&literal.value(),
literal.value(),
)))?;
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 => {
if event.name() == b"variable" {
let name = event.attributes()
.filter_map(|attr| attr.ok())
.filter_map(|v| v.ok())
.find(|attr| attr.key == b"name")
.ok_or_else(|| format_err!("No name attribute found for the <variable> tag"))?;
variables.push(name.unescape_and_decode_value(&reader)?);
@ -314,7 +314,7 @@ impl<R: BufRead> ResultsIterator<R> {
if event.name() == b"binding" {
match event
.attributes()
.filter_map(|attr| attr.ok())
.filter_map(|v| v.ok())
.find(|attr| attr.key == b"name")
{
Some(attr) => current_var = Some(attr.unescaped_value()?.to_vec()),

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

@ -83,14 +83,18 @@ impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
type Transaction = StoreRepositoryTransaction<S::Transaction>;
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
}
fn prepare_query_from_pattern(
&self,
pattern: &GraphPattern,
options: QueryOptions,
options: QueryOptions<'_>,
) -> Result<Self::PreparedQuery> {
SimplePreparedQuery::new_from_pattern(self.inner.clone(), pattern, options)
//TODO: avoid clone
@ -154,13 +158,13 @@ impl<S: StoreConnection> RepositoryConnection for StoreRepositoryConnection<S> {
fn insert(&mut self, quad: &Quad) -> Result<()> {
let mut transaction = self.auto_transaction();
transaction.insert(&quad)?;
transaction.insert(quad)?;
transaction.inner.commit()
}
fn remove(&mut self, quad: &Quad) -> Result<()> {
let mut transaction = self.auto_transaction();
transaction.remove(&quad)?;
transaction.remove(quad)?;
transaction.inner.commit()
}
}
@ -177,7 +181,7 @@ impl<T: StoreTransaction> RepositoryTransaction for StoreRepositoryTransaction<T
to_graph_name: Option<&NamedOrBlankNode>,
base_iri: Option<&str>,
) -> Result<()> {
let base_iri = base_iri.unwrap_or(&"");
let base_iri = base_iri.unwrap_or("");
match syntax {
GraphSyntax::NTriples => {
self.load_from_triple_parser(NTriplesParser::new(reader)?, to_graph_name)
@ -197,7 +201,7 @@ impl<T: StoreTransaction> RepositoryTransaction for StoreRepositoryTransaction<T
syntax: DatasetSyntax,
base_iri: Option<&str>,
) -> Result<()> {
let base_iri = base_iri.unwrap_or(&"");
let base_iri = base_iri.unwrap_or("");
match syntax {
DatasetSyntax::NQuads => self.load_from_quad_parser(NQuadsParser::new(reader)?),
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;
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());
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 subject: EncodedTerm,
pub predicate: EncodedTerm,
@ -474,7 +474,7 @@ pub struct EncodedQuad {
}
impl EncodedQuad {
pub fn new(
pub const fn new(
subject: EncodedTerm,
predicate: EncodedTerm,
object: EncodedTerm,
@ -872,7 +872,7 @@ pub trait Encoder {
predicate: self.encode_named_node(quad.predicate())?,
object: self.encode_term(quad.object())?,
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,
},
})
@ -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(
&mut self,
blank_node: rio::BlankNode,
blank_node: rio::BlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>,
) -> 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(
&mut self,
term: rio::NamedOrBlankNode,
term: rio::NamedOrBlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm> {
match term {
@ -916,7 +916,7 @@ pub trait Encoder {
fn encode_rio_term(
&mut self,
term: rio::Term,
term: rio::Term<'_>,
bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm> {
match term {
@ -928,7 +928,7 @@ pub trait Encoder {
fn encode_rio_quad(
&mut self,
quad: rio::Quad,
quad: rio::Quad<'_>,
bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedQuad> {
Ok(EncodedQuad {
@ -944,7 +944,7 @@ pub trait Encoder {
fn encode_rio_triple_in_graph(
&mut self,
triple: rio::Triple,
triple: rio::Triple<'_>,
graph_name: EncodedTerm,
bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedQuad> {
@ -958,7 +958,7 @@ pub trait Encoder {
}
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);
self.insert_str(iri_id, named_node.iri)?;
Ok(EncodedTerm::NamedNode { iri_id })
@ -966,7 +966,7 @@ impl<S: StrContainer> Encoder for S {
fn encode_rio_blank_node(
&mut self,
blank_node: rio::BlankNode,
blank_node: rio::BlankNode<'_>,
bnodes_map: &mut HashMap<String, u128>,
) -> Result<EncodedTerm> {
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 {
rio::Literal::Simple { value } => {
let value_id = get_str_id(value);

@ -59,8 +59,6 @@ const GSPO_CF: &str = "gspo";
const GPOS_CF: &str = "gpos";
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)
const COLUMN_FAMILIES: [&str; 7] = [
@ -524,32 +522,32 @@ impl RocksDbStoreInnerTransaction<'_> {
fn insert(&mut self, quad: &EncodedQuad) -> Result<()> {
self.buffer.write_spog_quad(quad)?;
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.write_posg_quad(quad)?;
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.write_ospg_quad(quad)?;
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.write_gspo_quad(quad)?;
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.write_gpos_quad(quad)?;
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.write_gosp_quad(quad)?;
self.batch
.put_cf(self.connection.gosp_cf, &self.buffer, &EMPTY_BUF)?;
.put_cf(self.connection.gosp_cf, &self.buffer, &[])?;
self.buffer.clear();
Ok(())

Loading…
Cancel
Save