Convert all Error + ErrorKind into one error

pull/745/head
Yuri Astrakhan 11 months ago
parent dae629fd4e
commit a62c5102c4
  1. 3
      Cargo.lock
  2. 47
      lib/oxigraph/src/storage/error.rs
  3. 1
      lib/oxrdf/Cargo.toml
  4. 86
      lib/oxrdf/src/parser.rs
  5. 77
      lib/oxrdfio/src/error.rs
  6. 66
      lib/oxrdfxml/src/error.rs
  7. 26
      lib/oxrdfxml/src/parser.rs
  8. 3
      lib/oxsdatatypes/Cargo.toml
  9. 54
      lib/oxsdatatypes/src/date_time.rs
  10. 66
      lib/oxsdatatypes/src/decimal.rs
  11. 34
      lib/sparesults/src/csv.rs
  12. 97
      lib/sparesults/src/error.rs
  13. 1
      lib/spargebra/Cargo.toml
  14. 53
      lib/spargebra/src/parser.rs

3
Cargo.lock generated

@ -1136,6 +1136,7 @@ dependencies = [
"oxiri",
"oxsdatatypes",
"rand",
"thiserror",
]
[[package]]
@ -1176,6 +1177,7 @@ name = "oxsdatatypes"
version = "0.2.0-alpha.1"
dependencies = [
"js-sys",
"thiserror",
]
[[package]]
@ -1761,6 +1763,7 @@ dependencies = [
"oxrdf",
"peg",
"rand",
"thiserror",
]
[[package]]

@ -1,7 +1,7 @@
use crate::io::{ParseError, RdfFormat};
use oxiri::IriParseError;
use std::error::Error;
use std::{fmt, io};
use std::io;
use thiserror::Error;
/// An error related to storage operations (reads, writes...).
@ -15,8 +15,8 @@ pub enum StorageError {
#[error(transparent)]
Corruption(#[from] CorruptionError),
#[doc(hidden)]
#[error(transparent)]
Other(Box<dyn Error + Send + Sync + 'static>),
#[error("{0}")]
Other(#[source] Box<dyn Error + Send + Sync + 'static>),
}
impl From<StorageError> for io::Error {
@ -31,52 +31,25 @@ impl From<StorageError> for io::Error {
}
/// An error return if some content in the database is corrupted.
#[derive(Debug)]
pub struct CorruptionError {
inner: CorruptionErrorKind,
}
#[derive(Debug)]
enum CorruptionErrorKind {
#[derive(Debug, Error)]
pub enum CorruptionError {
#[error("{0}")]
Msg(String),
Other(Box<dyn Error + Send + Sync + 'static>),
#[error("{0}")]
Other(#[source] Box<dyn Error + Send + Sync + 'static>),
}
impl CorruptionError {
/// Builds an error from a printable error message.
#[inline]
pub(crate) fn new(error: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
Self {
inner: CorruptionErrorKind::Other(error.into()),
}
Self::Other(error.into())
}
/// Builds an error from a printable error message.
#[inline]
pub(crate) fn msg(msg: impl Into<String>) -> Self {
Self {
inner: CorruptionErrorKind::Msg(msg.into()),
}
}
}
impl fmt::Display for CorruptionError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
CorruptionErrorKind::Msg(e) => e.fmt(f),
CorruptionErrorKind::Other(e) => e.fmt(f),
}
}
}
impl Error for CorruptionError {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self.inner {
CorruptionErrorKind::Msg(_) => None,
CorruptionErrorKind::Other(e) => Some(e.as_ref()),
}
Self::Msg(msg.into())
}
}

@ -22,6 +22,7 @@ oxilangtag.workspace = true
oxiri.workspace = true
oxsdatatypes = { workspace = true, optional = true }
rand.workspace = true
thiserror.workspace = true
[lints]
workspace = true

@ -5,9 +5,9 @@ use crate::{
};
#[cfg(feature = "rdf-star")]
use crate::{Subject, Triple};
use std::error::Error;
use std::char;
use std::str::{Chars, FromStr};
use std::{char, fmt};
use thiserror::Error;
/// This limit is set in order to avoid stack overflow error when parsing nested triples due to too many recursive calls.
/// The actual limit value is a wet finger compromise between not failing to parse valid files and avoiding to trigger stack overflow errors.
@ -166,11 +166,9 @@ impl FromStr for Variable {
"Variable serialization should start with ? or $",
));
}
Self::new(&s[1..]).map_err(|error| Self::Err {
kind: TermParseErrorKind::Variable {
value: s.to_owned(),
error,
},
Self::new(&s[1..]).map_err(|error| Self::Err::Variable {
value: s.to_owned(),
error,
})
}
}
@ -183,11 +181,9 @@ fn read_named_node(s: &str) -> Result<(NamedNode, &str), TermParseError> {
.ok_or_else(|| TermParseError::msg("Named node serialization should end with a >"))?;
let (value, remain) = remain.split_at(end);
let remain = &remain[1..];
let term = NamedNode::new(value).map_err(|error| TermParseError {
kind: TermParseErrorKind::Iri {
value: value.to_owned(),
error,
},
let term = NamedNode::new(value).map_err(|error| TermParseError::Iri {
value: value.to_owned(),
error,
})?;
Ok((term, remain))
} else {
@ -207,11 +203,9 @@ fn read_blank_node(s: &str) -> Result<(BlankNode, &str), TermParseError> {
})
.unwrap_or(remain.len());
let (value, remain) = remain.split_at(end);
let term = BlankNode::new(value).map_err(|error| TermParseError {
kind: TermParseErrorKind::BlankNode {
value: value.to_owned(),
error,
},
let term = BlankNode::new(value).map_err(|error| TermParseError::BlankNode {
value: value.to_owned(),
error,
})?;
Ok((term, remain))
} else {
@ -237,11 +231,9 @@ fn read_literal(s: &str) -> Result<(Literal, &str), TermParseError> {
let (language, remain) = remain.split_at(end);
Ok((
Literal::new_language_tagged_literal(value, language).map_err(
|error| TermParseError {
kind: TermParseErrorKind::LanguageTag {
value: language.to_owned(),
error,
},
|error| TermParseError::LanguageTag {
value: language.to_owned(),
error,
},
)?,
remain,
@ -421,61 +413,31 @@ fn read_hexa_char(input: &mut Chars<'_>, len: usize) -> Result<char, TermParseEr
}
/// An error raised during term serialization parsing using the [`FromStr`] trait.
#[derive(Debug)]
pub struct TermParseError {
kind: TermParseErrorKind,
}
#[derive(Debug)]
enum TermParseErrorKind {
Iri {
error: IriParseError,
value: String,
},
#[derive(Debug, Error)]
pub enum TermParseError {
#[error("Error while parsing the named node '{value}': {error}")]
Iri { error: IriParseError, value: String },
#[error("Error while parsing the blank node '{value}': {error}")]
BlankNode {
error: BlankNodeIdParseError,
value: String,
},
#[error("Error while parsing the language tag '{value}': {error}")]
LanguageTag {
error: LanguageTagParseError,
value: String,
},
#[error("Error while parsing the variable '{value}': {error}")]
Variable {
error: VariableNameParseError,
value: String,
},
Msg {
msg: &'static str,
},
#[error("{msg}")]
Msg { msg: &'static str },
}
impl fmt::Display for TermParseError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
TermParseErrorKind::Iri { error, value } => {
write!(f, "Error while parsing the named node '{value}': {error}")
}
TermParseErrorKind::BlankNode { error, value } => {
write!(f, "Error while parsing the blank node '{value}': {error}")
}
TermParseErrorKind::LanguageTag { error, value } => {
write!(f, "Error while parsing the language tag '{value}': {error}")
}
TermParseErrorKind::Variable { error, value } => {
write!(f, "Error while parsing the variable '{value}': {error}")
}
TermParseErrorKind::Msg { msg } => f.write_str(msg),
}
}
}
impl Error for TermParseError {}
impl TermParseError {
pub(crate) fn msg(msg: &'static str) -> Self {
Self {
kind: TermParseErrorKind::Msg { msg },
}
Self::Msg { msg }
}
}

@ -1,6 +1,5 @@
use std::error::Error;
use std::io;
use std::ops::Range;
use std::{fmt, io};
use thiserror::Error;
/// Error returned during RDF format parsing.
@ -16,18 +15,7 @@ pub enum ParseError {
impl ParseError {
pub(crate) fn msg(msg: &'static str) -> Self {
Self::Syntax(SyntaxError {
inner: SyntaxErrorKind::Msg { msg },
})
}
}
impl From<oxttl::SyntaxError> for SyntaxError {
#[inline]
fn from(error: oxttl::SyntaxError) -> Self {
Self {
inner: SyntaxErrorKind::Turtle(error),
}
Self::Syntax(SyntaxError::Msg { msg })
}
}
@ -41,15 +29,6 @@ impl From<oxttl::ParseError> for ParseError {
}
}
impl From<oxrdfxml::SyntaxError> for SyntaxError {
#[inline]
fn from(error: oxrdfxml::SyntaxError) -> Self {
Self {
inner: SyntaxErrorKind::RdfXml(error),
}
}
}
impl From<oxrdfxml::ParseError> for ParseError {
#[inline]
fn from(error: oxrdfxml::ParseError) -> Self {
@ -71,15 +50,13 @@ impl From<ParseError> for io::Error {
}
/// An error in the syntax of the parsed file.
#[derive(Debug)]
pub struct SyntaxError {
inner: SyntaxErrorKind,
}
#[derive(Debug)]
enum SyntaxErrorKind {
Turtle(oxttl::SyntaxError),
RdfXml(oxrdfxml::SyntaxError),
#[derive(Debug, Error)]
pub enum SyntaxError {
#[error(transparent)]
Turtle(#[from] oxttl::SyntaxError),
#[error(transparent)]
RdfXml(#[from] oxrdfxml::SyntaxError),
#[error("{msg}")]
Msg { msg: &'static str },
}
@ -87,8 +64,8 @@ impl SyntaxError {
/// The location of the error inside of the file.
#[inline]
pub fn location(&self) -> Option<Range<TextPosition>> {
match &self.inner {
SyntaxErrorKind::Turtle(e) => {
match &self {
Self::Turtle(e) => {
let location = e.location();
Some(
TextPosition {
@ -102,29 +79,7 @@ impl SyntaxError {
},
)
}
SyntaxErrorKind::RdfXml(_) | SyntaxErrorKind::Msg { .. } => None,
}
}
}
impl fmt::Display for SyntaxError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
SyntaxErrorKind::Turtle(e) => e.fmt(f),
SyntaxErrorKind::RdfXml(e) => e.fmt(f),
SyntaxErrorKind::Msg { msg } => f.write_str(msg),
}
}
}
impl Error for SyntaxError {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self.inner {
SyntaxErrorKind::Turtle(e) => Some(e),
SyntaxErrorKind::RdfXml(e) => Some(e),
SyntaxErrorKind::Msg { .. } => None,
Self::RdfXml(_) | Self::Msg { .. } => None,
}
}
}
@ -132,10 +87,10 @@ impl Error for SyntaxError {
impl From<SyntaxError> for io::Error {
#[inline]
fn from(error: SyntaxError) -> Self {
match error.inner {
SyntaxErrorKind::Turtle(error) => error.into(),
SyntaxErrorKind::RdfXml(error) => error.into(),
SyntaxErrorKind::Msg { msg } => Self::new(io::ErrorKind::InvalidData, msg),
match error {
SyntaxError::Turtle(error) => error.into(),
SyntaxError::RdfXml(error) => error.into(),
SyntaxError::Msg { msg } => Self::new(io::ErrorKind::InvalidData, msg),
}
}
}

@ -1,8 +1,7 @@
use oxilangtag::LanguageTagParseError;
use oxiri::IriParseError;
use std::error::Error;
use std::io;
use std::sync::Arc;
use std::{fmt, io};
use thiserror::Error;
/// Error returned during RDF/XML parsing.
@ -33,78 +32,45 @@ impl From<quick_xml::Error> for ParseError {
quick_xml::Error::Io(error) => {
Self::Io(Arc::try_unwrap(error).unwrap_or_else(|e| io::Error::new(e.kind(), e)))
}
_ => Self::Syntax(SyntaxError {
inner: SyntaxErrorKind::Xml(error),
}),
_ => Self::Syntax(SyntaxError::Xml(error)),
}
}
}
/// An error in the syntax of the parsed file.
#[derive(Debug)]
pub struct SyntaxError {
pub(crate) inner: SyntaxErrorKind,
}
#[derive(Debug)]
pub enum SyntaxErrorKind {
Xml(quick_xml::Error),
#[derive(Debug, Error)]
pub enum SyntaxError {
#[error(transparent)]
Xml(#[from] quick_xml::Error),
#[error("error while parsing IRI '{iri}': {error}")]
InvalidIri {
iri: String,
#[source]
error: IriParseError,
},
#[error("error while parsing language tag '{tag}': {error}")]
InvalidLanguageTag {
tag: String,
#[source]
error: LanguageTagParseError,
},
Msg {
msg: String,
},
#[error("{msg}")]
Msg { msg: String },
}
impl SyntaxError {
/// Builds an error from a printable error message.
#[inline]
pub(crate) fn msg(msg: impl Into<String>) -> Self {
Self {
inner: SyntaxErrorKind::Msg { msg: msg.into() },
}
}
}
impl fmt::Display for SyntaxError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
SyntaxErrorKind::Xml(error) => error.fmt(f),
SyntaxErrorKind::InvalidIri { iri, error } => {
write!(f, "error while parsing IRI '{iri}': {error}")
}
SyntaxErrorKind::InvalidLanguageTag { tag, error } => {
write!(f, "error while parsing language tag '{tag}': {error}")
}
SyntaxErrorKind::Msg { msg } => f.write_str(msg),
}
}
}
impl Error for SyntaxError {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self.inner {
SyntaxErrorKind::Xml(error) => Some(error),
SyntaxErrorKind::InvalidIri { error, .. } => Some(error),
SyntaxErrorKind::InvalidLanguageTag { error, .. } => Some(error),
SyntaxErrorKind::Msg { .. } => None,
}
Self::Msg { msg: msg.into() }
}
}
impl From<SyntaxError> for io::Error {
#[inline]
fn from(error: SyntaxError) -> Self {
match error.inner {
SyntaxErrorKind::Xml(error) => match error {
match error {
SyntaxError::Xml(error) => match error {
quick_xml::Error::Io(error) => {
Arc::try_unwrap(error).unwrap_or_else(|e| Self::new(e.kind(), e))
}
@ -113,7 +79,7 @@ impl From<SyntaxError> for io::Error {
}
_ => Self::new(io::ErrorKind::InvalidData, error),
},
SyntaxErrorKind::Msg { msg } => Self::new(io::ErrorKind::InvalidData, msg),
SyntaxError::Msg { msg } => Self::new(io::ErrorKind::InvalidData, msg),
_ => Self::new(io::ErrorKind::InvalidData, error),
}
}

@ -1,4 +1,4 @@
use crate::error::{ParseError, SyntaxError, SyntaxErrorKind};
use crate::error::{ParseError, SyntaxError};
use crate::utils::*;
use oxilangtag::LanguageTag;
use oxiri::{Iri, IriParseError};
@ -575,9 +575,7 @@ impl<R> RdfXmlReader<R> {
tag
} else {
LanguageTag::parse(tag.to_ascii_lowercase())
.map_err(|error| SyntaxError {
inner: SyntaxErrorKind::InvalidLanguageTag { tag, error },
})?
.map_err(|error| SyntaxError::InvalidLanguageTag { tag, error })?
.into_inner()
});
} else if attribute.key.as_ref() == b"xml:base" {
@ -588,9 +586,7 @@ impl<R> RdfXmlReader<R> {
} else {
Iri::parse(iri.clone())
}
.map_err(|error| SyntaxError {
inner: SyntaxErrorKind::InvalidIri { iri, error },
})?,
.map_err(|error| SyntaxError::InvalidIri { iri, error })?,
)
} else {
// We ignore other xml attributes
@ -1169,11 +1165,9 @@ impl<R> RdfXmlReader<R> {
} else {
base_iri.resolve(&relative_iri)
}
.map_err(|error| SyntaxError {
inner: SyntaxErrorKind::InvalidIri {
iri: relative_iri,
error,
},
.map_err(|error| SyntaxError::InvalidIri {
iri: relative_iri,
error,
})?
.into_inner(),
))
@ -1187,11 +1181,9 @@ impl<R> RdfXmlReader<R> {
relative_iri
} else {
Iri::parse(relative_iri.clone())
.map_err(|error| SyntaxError {
inner: SyntaxErrorKind::InvalidIri {
iri: relative_iri,
error,
},
.map_err(|error| SyntaxError::InvalidIri {
iri: relative_iri,
error,
})?
.into_inner()
}))

@ -13,6 +13,9 @@ documentation = "https://docs.rs/oxsdatatypes"
edition.workspace = true
rust-version.workspace = true
[dependencies]
thiserror.workspace = true
[features]
js = ["js-sys"]
custom-now = []

@ -6,6 +6,7 @@ use std::error::Error;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::str::FromStr;
use thiserror::Error;
/// [XML Schema `dateTime` datatype](https://www.w3.org/TR/xmlschema11-2/#dateTime)
///
@ -2039,42 +2040,24 @@ fn time_on_timeline(props: &DateTimeSevenPropertyModel) -> Option<Decimal> {
}
/// A parsing error
#[derive(Debug, Clone)]
pub struct ParseDateTimeError {
kind: ParseDateTimeErrorKind,
}
#[derive(Debug, Clone)]
enum ParseDateTimeErrorKind {
#[derive(Debug, Clone, Error)]
pub enum ParseDateTimeError {
#[error("{day} is not a valid day of {month}")]
InvalidDayOfMonth { day: u8, month: u8 },
Overflow(DateTimeOverflowError),
#[error(transparent)]
Overflow(#[from] DateTimeOverflowError),
#[error(transparent)]
InvalidTimezone(InvalidTimezoneError),
#[error("{0}")]
Message(&'static str),
}
impl fmt::Display for ParseDateTimeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
ParseDateTimeErrorKind::InvalidDayOfMonth { day, month } => {
write!(f, "{day} is not a valid day of {month}")
}
ParseDateTimeErrorKind::Overflow(error) => error.fmt(f),
ParseDateTimeErrorKind::InvalidTimezone(error) => error.fmt(f),
ParseDateTimeErrorKind::Message(msg) => f.write_str(msg),
}
}
}
impl ParseDateTimeError {
const fn msg(message: &'static str) -> Self {
Self {
kind: ParseDateTimeErrorKind::Message(message),
}
Self::Message(message)
}
}
impl Error for ParseDateTimeError {}
// [16] dateTimeLexicalRep ::= yearFrag '-' monthFrag '-' dayFrag 'T' ((hourFrag ':' minuteFrag ':' secondFrag) | endOfDayFrag) timezoneFrag?
fn date_time_lexical_rep(input: &str) -> Result<(DateTime, &str), ParseDateTimeError> {
let (year, input) = year_frag(input)?;
@ -2326,11 +2309,8 @@ fn timezone_frag(input: &str) -> Result<(TimezoneOffset, &str), ParseDateTimeErr
}
Ok((
TimezoneOffset::new(sign * (hours * 60 + i16::from(minutes))).map_err(|e| {
ParseDateTimeError {
kind: ParseDateTimeErrorKind::InvalidTimezone(e),
}
})?,
TimezoneOffset::new(sign * (hours * 60 + i16::from(minutes)))
.map_err(|e| ParseDateTimeError::InvalidTimezone(e))?,
input,
))
}
@ -2400,9 +2380,7 @@ fn optional_end<T>(
fn validate_day_of_month(year: Option<i64>, month: u8, day: u8) -> Result<(), ParseDateTimeError> {
// Constraint: Day-of-month Values
if day > days_in_month(year, month) {
return Err(ParseDateTimeError {
kind: ParseDateTimeErrorKind::InvalidDayOfMonth { day, month },
});
return Err(ParseDateTimeError::InvalidDayOfMonth { day, month });
}
Ok(())
}
@ -2421,14 +2399,6 @@ impl fmt::Display for DateTimeOverflowError {
impl Error for DateTimeOverflowError {}
impl From<DateTimeOverflowError> for ParseDateTimeError {
fn from(error: DateTimeOverflowError) -> Self {
Self {
kind: ParseDateTimeErrorKind::Overflow(error),
}
}
}
/// The value provided as timezone is not valid.
///
/// Matches XPath [`FODT0003` error](https://www.w3.org/TR/xpath-functions-31/#ERRFODT0003).

@ -3,6 +3,7 @@ use std::error::Error;
use std::fmt;
use std::fmt::Write;
use std::str::FromStr;
use thiserror::Error;
const DECIMAL_PART_DIGITS: u32 = 18;
const DECIMAL_PART_POW: i128 = 1_000_000_000_000_000_000;
@ -466,7 +467,7 @@ impl FromStr for Decimal {
// (\+|-)?([0-9]+(\.[0-9]*)?|\.[0-9]+)
let input = input.as_bytes();
if input.is_empty() {
return Err(PARSE_UNEXPECTED_END);
return Err(ParseDecimalError::UnexpectedEnd);
}
let (sign, mut input) = match input.first() {
@ -481,9 +482,9 @@ impl FromStr for Decimal {
if c.is_ascii_digit() {
value = value
.checked_mul(10)
.ok_or(PARSE_OVERFLOW)?
.ok_or(ParseDecimalError::Overflow)?
.checked_add(sign * i128::from(*c - b'0'))
.ok_or(PARSE_OVERFLOW)?;
.ok_or(ParseDecimalError::Overflow)?;
input = &input[1..];
} else {
break;
@ -493,12 +494,12 @@ impl FromStr for Decimal {
let mut exp = DECIMAL_PART_POW;
if let Some(c) = input.first() {
if *c != b'.' {
return Err(PARSE_UNEXPECTED_CHAR);
return Err(ParseDecimalError::UnexpectedChar);
}
input = &input[1..];
if input.is_empty() && !with_before_dot {
// We only have a dot
return Err(PARSE_UNEXPECTED_END);
return Err(ParseDecimalError::UnexpectedEnd);
}
while input.last() == Some(&b'0') {
// Hack to avoid underflows
@ -509,25 +510,25 @@ impl FromStr for Decimal {
exp /= 10;
value = value
.checked_mul(10)
.ok_or(PARSE_OVERFLOW)?
.ok_or(ParseDecimalError::Overflow)?
.checked_add(sign * i128::from(*c - b'0'))
.ok_or(PARSE_OVERFLOW)?;
.ok_or(ParseDecimalError::Overflow)?;
input = &input[1..];
} else {
return Err(PARSE_UNEXPECTED_CHAR);
return Err(ParseDecimalError::UnexpectedChar);
}
}
if exp == 0 {
// Underflow
return Err(PARSE_UNDERFLOW);
return Err(ParseDecimalError::Underflow);
}
} else if !with_before_dot {
// It's empty
return Err(PARSE_UNEXPECTED_END);
return Err(ParseDecimalError::UnexpectedEnd);
}
Ok(Self {
value: value.checked_mul(exp).ok_or(PARSE_OVERFLOW)?,
value: value.checked_mul(exp).ok_or(ParseDecimalError::Overflow)?,
})
}
}
@ -609,50 +610,21 @@ impl fmt::Display for Decimal {
}
/// An error when parsing a [`Decimal`].
#[derive(Debug, Clone)]
pub struct ParseDecimalError {
kind: DecimalParseErrorKind,
}
#[derive(Debug, Clone)]
enum DecimalParseErrorKind {
#[derive(Debug, Clone, Error)]
pub enum ParseDecimalError {
#[error("Value overflow")]
Overflow,
#[error("Value underflow")]
Underflow,
#[error("Unexpected character")]
UnexpectedChar,
#[error("Unexpected end of string")]
UnexpectedEnd,
}
const PARSE_OVERFLOW: ParseDecimalError = ParseDecimalError {
kind: DecimalParseErrorKind::Overflow,
};
const PARSE_UNDERFLOW: ParseDecimalError = ParseDecimalError {
kind: DecimalParseErrorKind::Underflow,
};
const PARSE_UNEXPECTED_CHAR: ParseDecimalError = ParseDecimalError {
kind: DecimalParseErrorKind::UnexpectedChar,
};
const PARSE_UNEXPECTED_END: ParseDecimalError = ParseDecimalError {
kind: DecimalParseErrorKind::UnexpectedEnd,
};
impl fmt::Display for ParseDecimalError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
DecimalParseErrorKind::Overflow => f.write_str("Value overflow"),
DecimalParseErrorKind::Underflow => f.write_str("Value underflow"),
DecimalParseErrorKind::UnexpectedChar => f.write_str("Unexpected character"),
DecimalParseErrorKind::UnexpectedEnd => f.write_str("Unexpected end of string"),
}
}
}
impl Error for ParseDecimalError {}
impl From<TooLargeForDecimalError> for ParseDecimalError {
fn from(_: TooLargeForDecimalError) -> Self {
Self {
kind: DecimalParseErrorKind::Overflow,
}
Self::Overflow
}
}

@ -1,6 +1,6 @@
//! Implementation of [SPARQL 1.1 Query Results CSV and TSV Formats](https://www.w3.org/TR/sparql11-results-csv-tsv/)
use crate::error::{ParseError, SyntaxError, SyntaxErrorKind, TextPosition};
use crate::error::{ParseError, SyntaxError, TextPosition};
use memchr::memchr;
use oxrdf::vocab::xsd;
use oxrdf::*;
@ -508,23 +508,21 @@ impl<R: Read> TsvSolutionsReader<R> {
.sum::<usize>();
let start_position_bytes =
line.split('\t').take(i).map(|c| c.len() + 1).sum::<usize>();
SyntaxError {
inner: SyntaxErrorKind::Term {
error: e,
term: v.into(),
location: TextPosition {
line: self.reader.line_count - 1,
column: start_position_char.try_into().unwrap(),
offset: self.reader.last_line_start
+ u64::try_from(start_position_bytes).unwrap(),
}..TextPosition {
line: self.reader.line_count - 1,
column: (start_position_char + v.chars().count())
.try_into()
.unwrap(),
offset: self.reader.last_line_start
+ u64::try_from(start_position_bytes + v.len()).unwrap(),
},
SyntaxError::Term {
error: e,
term: v.into(),
location: TextPosition {
line: self.reader.line_count - 1,
column: start_position_char.try_into().unwrap(),
offset: self.reader.last_line_start
+ u64::try_from(start_position_bytes).unwrap(),
}..TextPosition {
line: self.reader.line_count - 1,
column: (start_position_char + v.chars().count())
.try_into()
.unwrap(),
offset: self.reader.last_line_start
+ u64::try_from(start_position_bytes + v.len()).unwrap(),
},
}
})?))

@ -1,8 +1,7 @@
use oxrdf::TermParseError;
use std::error::Error;
use std::io;
use std::ops::Range;
use std::sync::Arc;
use std::{fmt, io};
use thiserror::Error;
/// Error returned during SPARQL result formats format parsing.
@ -42,28 +41,26 @@ impl From<quick_xml::Error> for ParseError {
quick_xml::Error::Io(error) => {
Self::Io(Arc::try_unwrap(error).unwrap_or_else(|e| io::Error::new(e.kind(), e)))
}
_ => Self::Syntax(SyntaxError {
inner: SyntaxErrorKind::Xml(error),
}),
_ => Self::Syntax(SyntaxError::Xml(error)),
}
}
}
/// An error in the syntax of the parsed file.
#[derive(Debug)]
pub struct SyntaxError {
pub(crate) inner: SyntaxErrorKind,
}
#[derive(Debug)]
pub(crate) enum SyntaxErrorKind {
Json(json_event_parser::SyntaxError),
Xml(quick_xml::Error),
#[derive(Debug, Error)]
pub enum SyntaxError {
#[error(transparent)]
Json(#[from] json_event_parser::SyntaxError),
#[error(transparent)]
Xml(#[from] quick_xml::Error),
#[error("Error {error} on '{term}' in line {}", location.start.line + 1)]
Term {
#[source]
error: TermParseError,
term: String,
location: Range<TextPosition>,
},
#[error("{msg}")]
Msg {
msg: String,
location: Option<Range<TextPosition>>,
@ -74,30 +71,26 @@ impl SyntaxError {
/// Builds an error from a printable error message.
#[inline]
pub(crate) fn msg(msg: impl Into<String>) -> Self {
Self {
inner: SyntaxErrorKind::Msg {
msg: msg.into(),
location: None,
},
Self::Msg {
msg: msg.into(),
location: None,
}
}
/// Builds an error from a printable error message and a location
#[inline]
pub(crate) fn located_message(msg: impl Into<String>, location: Range<TextPosition>) -> Self {
Self {
inner: SyntaxErrorKind::Msg {
msg: msg.into(),
location: Some(location),
},
Self::Msg {
msg: msg.into(),
location: Some(location),
}
}
/// The location of the error inside of the file.
#[inline]
pub fn location(&self) -> Option<Range<TextPosition>> {
match &self.inner {
SyntaxErrorKind::Json(e) => {
match self {
Self::Json(e) => {
let location = e.location();
Some(
TextPosition {
@ -111,37 +104,9 @@ impl SyntaxError {
},
)
}
SyntaxErrorKind::Term { location, .. } => Some(location.clone()),
SyntaxErrorKind::Msg { location, .. } => location.clone(),
SyntaxErrorKind::Xml(_) => None,
}
}
}
impl fmt::Display for SyntaxError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
SyntaxErrorKind::Json(e) => e.fmt(f),
SyntaxErrorKind::Xml(e) => e.fmt(f),
SyntaxErrorKind::Term {
error,
term,
location,
} => write!(f, "{error} on '{term}' in line {}", location.start.line + 1),
SyntaxErrorKind::Msg { msg, .. } => f.write_str(msg),
}
}
}
impl Error for SyntaxError {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self.inner {
SyntaxErrorKind::Json(e) => Some(e),
SyntaxErrorKind::Xml(e) => Some(e),
SyntaxErrorKind::Term { error, .. } => Some(error),
SyntaxErrorKind::Msg { .. } => None,
Self::Term { location, .. } => Some(location.clone()),
Self::Msg { location, .. } => location.clone(),
Self::Xml(_) => None,
}
}
}
@ -149,9 +114,9 @@ impl Error for SyntaxError {
impl From<SyntaxError> for io::Error {
#[inline]
fn from(error: SyntaxError) -> Self {
match error.inner {
SyntaxErrorKind::Json(error) => Self::new(io::ErrorKind::InvalidData, error),
SyntaxErrorKind::Xml(error) => match error {
match error {
SyntaxError::Json(error) => Self::new(io::ErrorKind::InvalidData, error),
SyntaxError::Xml(error) => match error {
quick_xml::Error::Io(error) => {
Arc::try_unwrap(error).unwrap_or_else(|e| Self::new(e.kind(), e))
}
@ -160,16 +125,8 @@ impl From<SyntaxError> for io::Error {
}
_ => Self::new(io::ErrorKind::InvalidData, error),
},
SyntaxErrorKind::Term { .. } => Self::new(io::ErrorKind::InvalidData, error),
SyntaxErrorKind::Msg { msg, .. } => Self::new(io::ErrorKind::InvalidData, msg),
}
}
}
impl From<json_event_parser::SyntaxError> for SyntaxError {
fn from(error: json_event_parser::SyntaxError) -> Self {
Self {
inner: SyntaxErrorKind::Json(error),
SyntaxError::Term { .. } => Self::new(io::ErrorKind::InvalidData, error),
SyntaxError::Msg { msg, .. } => Self::new(io::ErrorKind::InvalidData, msg),
}
}
}

@ -25,6 +25,7 @@ oxiri.workspace = true
oxrdf.workspace = true
peg.workspace = true
rand.workspace = true
thiserror.workspace = true
[lints]
workspace = true

@ -9,26 +9,22 @@ use oxrdf::vocab::{rdf, xsd};
use peg::parser;
use peg::str::LineCol;
use rand::random;
use std::char;
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::mem::take;
use std::str::FromStr;
use std::{char, fmt};
use thiserror::Error;
/// Parses a SPARQL query with an optional base IRI to resolve relative IRIs in the query.
pub fn parse_query(query: &str, base_iri: Option<&str>) -> Result<Query, ParseError> {
let mut state = ParserState::from_base_iri(base_iri)?;
parser::QueryUnit(query, &mut state).map_err(|e| ParseError {
inner: ParseErrorKind::Parser(e),
})
parser::QueryUnit(query, &mut state).map_err(|e| ParseError::Parser(e))
}
/// Parses a SPARQL update with an optional base IRI to resolve relative IRIs in the query.
pub fn parse_update(update: &str, base_iri: Option<&str>) -> Result<Update, ParseError> {
let mut state = ParserState::from_base_iri(base_iri)?;
let operations = parser::UpdateInit(update, &mut state).map_err(|e| ParseError {
inner: ParseErrorKind::Parser(e),
})?;
let operations = parser::UpdateInit(update, &mut state).map_err(|e| ParseError::Parser(e))?;
Ok(Update {
operations,
base_iri: state.base_iri,
@ -36,37 +32,12 @@ pub fn parse_update(update: &str, base_iri: Option<&str>) -> Result<Update, Pars
}
/// Error returned during SPARQL parsing.
#[derive(Debug)]
pub struct ParseError {
inner: ParseErrorKind,
}
#[derive(Debug)]
enum ParseErrorKind {
InvalidBaseIri(IriParseError),
Parser(peg::error::ParseError<LineCol>),
}
impl fmt::Display for ParseError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
ParseErrorKind::InvalidBaseIri(e) => {
write!(f, "Invalid SPARQL base IRI provided: {e}")
}
ParseErrorKind::Parser(e) => e.fmt(f),
}
}
}
impl Error for ParseError {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self.inner {
ParseErrorKind::InvalidBaseIri(e) => Some(e),
ParseErrorKind::Parser(e) => Some(e),
}
}
#[derive(Debug, Error)]
pub enum ParseError {
#[error("Invalid SPARQL base IRI provided: {0}")]
InvalidBaseIri(#[from] IriParseError),
#[error(transparent)]
Parser(#[from] peg::error::ParseError<LineCol>),
}
struct AnnotatedTerm {
@ -697,9 +668,7 @@ impl ParserState {
pub(crate) fn from_base_iri(base_iri: Option<&str>) -> Result<Self, ParseError> {
Ok(Self {
base_iri: if let Some(base_iri) = base_iri {
Some(Iri::parse(base_iri.to_owned()).map_err(|e| ParseError {
inner: ParseErrorKind::InvalidBaseIri(e),
})?)
Some(Iri::parse(base_iri.to_owned()).map_err(|e| ParseError::InvalidBaseIri(e))?)
} else {
None
},

Loading…
Cancel
Save