Address feedback, preserving inner err

pull/775/head
Yuri Astrakhan 1 year ago
parent 463a7bd796
commit b50a6fa13a
  1. 4
      lib/oxigraph/src/storage/error.rs
  2. 106
      lib/oxrdf/src/parser.rs
  3. 33
      lib/oxrdfio/src/error.rs
  4. 23
      lib/oxrdfxml/src/error.rs
  5. 26
      lib/oxrdfxml/src/parser.rs
  6. 20
      lib/oxsdatatypes/src/date_time.rs
  7. 37
      lib/oxsdatatypes/src/decimal.rs
  8. 34
      lib/sparesults/src/csv.rs
  9. 57
      lib/sparesults/src/error.rs
  10. 16
      lib/spargebra/src/parser.rs

@ -49,7 +49,7 @@ 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 {
CorruptionErrorKind::Other(error.into()).into()
Self(CorruptionErrorKind::Other(error.into()))
}
#[inline]
@ -67,7 +67,7 @@ impl CorruptionError {
/// Builds an error from a printable error message.
#[inline]
pub(crate) fn msg(msg: impl Into<String>) -> Self {
CorruptionErrorKind::Msg(msg.into()).into()
Self(CorruptionErrorKind::Msg(msg.into()))
}
}

@ -29,9 +29,9 @@ impl FromStr for NamedNode {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (term, left) = read_named_node(s)?;
if !left.is_empty() {
return Err(TermParseErrorKind::msg(
return Err(Self::Err::msg(
"Named node serialization should end with a >",
))?;
));
}
Ok(term)
}
@ -54,9 +54,9 @@ impl FromStr for BlankNode {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (term, left) = read_blank_node(s)?;
if !left.is_empty() {
return Err(TermParseErrorKind::msg(
return Err(Self::Err::msg(
"Blank node serialization should not contain whitespaces",
))?;
));
}
Ok(term)
}
@ -107,7 +107,7 @@ impl FromStr for Literal {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (term, left) = read_literal(s)?;
if !left.is_empty() {
return Err(TermParseErrorKind::msg("Invalid literal serialization"))?;
return Err(Self::Err::msg("Invalid literal serialization"));
}
Ok(term)
}
@ -139,7 +139,7 @@ impl FromStr for Term {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (term, left) = read_term(s, 0)?;
if !left.is_empty() {
return Err(TermParseErrorKind::msg("Invalid term serialization"))?;
return Err(Self::Err::msg("Invalid term serialization"));
}
Ok(term)
}
@ -161,40 +161,42 @@ impl FromStr for Variable {
/// ```
fn from_str(s: &str) -> Result<Self, Self::Err> {
if !s.starts_with('?') && !s.starts_with('$') {
return Err(TermParseErrorKind::msg(
return Err(Self::Err::msg(
"Variable serialization should start with ? or $",
))?;
));
}
Ok(
Self::new(&s[1..]).map_err(|error| TermParseErrorKind::Variable {
Self::new(&s[1..]).map_err(|error| {
TermParseError(TermParseErrorKind::Variable {
value: s.to_owned(),
error,
})?,
)
})
})
}
}
fn read_named_node(s: &str) -> Result<(NamedNode, &str), TermParseErrorKind> {
fn read_named_node(s: &str) -> Result<(NamedNode, &str), TermParseError> {
let s = s.trim();
if let Some(remain) = s.strip_prefix('<') {
let end = remain.find('>').ok_or_else(|| {
TermParseErrorKind::msg("Named node serialization should end with a >")
})?;
let end = remain
.find('>')
.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| TermParseErrorKind::Iri {
value: value.to_owned(),
error,
let term = NamedNode::new(value).map_err(|error| {
TermParseError(TermParseErrorKind::Iri {
value: value.to_owned(),
error,
})
})?;
Ok((term, remain))
} else {
Err(TermParseErrorKind::msg(
Err(TermParseError::msg(
"Named node serialization should start with a <",
))
}
}
fn read_blank_node(s: &str) -> Result<(BlankNode, &str), TermParseErrorKind> {
fn read_blank_node(s: &str) -> Result<(BlankNode, &str), TermParseError> {
let s = s.trim();
if let Some(remain) = s.strip_prefix("_:") {
let end = remain
@ -204,19 +206,21 @@ fn read_blank_node(s: &str) -> Result<(BlankNode, &str), TermParseErrorKind> {
})
.unwrap_or(remain.len());
let (value, remain) = remain.split_at(end);
let term = BlankNode::new(value).map_err(|error| TermParseErrorKind::BlankNode {
value: value.to_owned(),
error,
let term = BlankNode::new(value).map_err(|error| {
TermParseError(TermParseErrorKind::BlankNode {
value: value.to_owned(),
error,
})
})?;
Ok((term, remain))
} else {
Err(TermParseErrorKind::msg(
Err(TermParseError::msg(
"Blank node serialization should start with '_:'",
))?
))
}
}
fn read_literal(s: &str) -> Result<(Literal, &str), TermParseErrorKind> {
fn read_literal(s: &str) -> Result<(Literal, &str), TermParseError> {
let s = s.trim();
if let Some(s) = s.strip_prefix('"') {
let mut value = String::with_capacity(s.len());
@ -232,9 +236,11 @@ fn read_literal(s: &str) -> Result<(Literal, &str), TermParseErrorKind> {
let (language, remain) = remain.split_at(end);
Ok((
Literal::new_language_tagged_literal(value, language).map_err(
|error| TermParseErrorKind::LanguageTag {
value: language.to_owned(),
error,
|error| {
TermParseError(TermParseErrorKind::LanguageTag {
value: language.to_owned(),
error,
})
},
)?,
remain,
@ -259,16 +265,16 @@ fn read_literal(s: &str) -> Result<(Literal, &str), TermParseErrorKind> {
'\\' => '\\',
'u' => read_hexa_char(&mut chars, 4)?,
'U' => read_hexa_char(&mut chars, 8)?,
_ => return Err(TermParseErrorKind::msg("Unexpected escaped char"))?,
_ => return Err(TermParseError::msg("Unexpected escaped char")),
})
} else {
return Err(TermParseErrorKind::msg("Unexpected literal end"));
return Err(TermParseError::msg("Unexpected literal end"));
}
}
_ => value.push(c),
}
}
Err(TermParseErrorKind::msg("Unexpected literal end"))
Err(TermParseError::msg("Unexpected literal end"))
} else if let Some(remain) = s.strip_prefix("true") {
Ok((Literal::new_typed_literal("true", xsd::BOOLEAN), remain))
} else if let Some(remain) = s.strip_prefix("false") {
@ -276,7 +282,7 @@ fn read_literal(s: &str) -> Result<(Literal, &str), TermParseErrorKind> {
} else {
let input = s.as_bytes();
if input.is_empty() {
return Err(TermParseErrorKind::msg("Empty term serialization"));
return Err(TermParseError::msg("Empty term serialization"));
}
let mut cursor = match input.first() {
@ -315,7 +321,7 @@ fn read_literal(s: &str) -> Result<(Literal, &str), TermParseErrorKind> {
if count_exponent > 0 {
Ok((Literal::new_typed_literal(s, xsd::DOUBLE), &s[cursor..]))
} else {
Err(TermParseErrorKind::msg(
Err(TermParseError::msg(
"Double serialization with an invalid exponent",
))
}
@ -323,24 +329,21 @@ fn read_literal(s: &str) -> Result<(Literal, &str), TermParseErrorKind> {
if count_after > 0 {
Ok((Literal::new_typed_literal(s, xsd::DECIMAL), &s[cursor..]))
} else {
Err(TermParseErrorKind::msg(
Err(TermParseError::msg(
"Decimal serialization without floating part",
))
}
} else if count_before > 0 {
Ok((Literal::new_typed_literal(s, xsd::INTEGER), &s[cursor..]))
} else {
Err(TermParseErrorKind::msg("Empty integer serialization"))
Err(TermParseError::msg("Empty integer serialization"))
}
}
}
fn read_term(
s: &str,
number_of_recursive_calls: usize,
) -> Result<(Term, &str), TermParseErrorKind> {
fn read_term(s: &str, number_of_recursive_calls: usize) -> Result<(Term, &str), TermParseError> {
if number_of_recursive_calls == MAX_NUMBER_OF_NESTED_TRIPLES {
return Err(TermParseErrorKind::msg(
return Err(TermParseError::msg(
"Too many nested triples. The parser fails here to avoid a stack overflow.",
));
}
@ -360,7 +363,7 @@ fn read_term(
Term::NamedNode(s) => s.into(),
Term::BlankNode(s) => s.into(),
Term::Literal(_) => {
return Err(TermParseErrorKind::msg(
return Err(TermParseError::msg(
"Literals are not allowed in subject position",
))
}
@ -373,14 +376,14 @@ fn read_term(
remain,
))
} else {
Err(TermParseErrorKind::msg(
Err(TermParseError::msg(
"Nested triple serialization should be enclosed between << and >>",
))
}
}
#[cfg(not(feature = "rdf-star"))]
{
Err(TermParseErrorKind::msg("RDF-star is not supported"))
Err(TermParseError::msg("RDF-star is not supported"))
}
} else if s.starts_with('<') {
let (term, remain) = read_named_node(s)?;
@ -394,7 +397,7 @@ fn read_term(
}
}
fn read_hexa_char(input: &mut Chars<'_>, len: usize) -> Result<char, TermParseErrorKind> {
fn read_hexa_char(input: &mut Chars<'_>, len: usize) -> Result<char, TermParseError> {
let mut value = 0;
for _ in 0..len {
if let Some(c) = input.next() {
@ -404,17 +407,16 @@ fn read_hexa_char(input: &mut Chars<'_>, len: usize) -> Result<char, TermParseEr
'a'..='f' => u32::from(c) - u32::from('a') + 10,
'A'..='F' => u32::from(c) - u32::from('A') + 10,
_ => {
return Err(TermParseErrorKind::msg(
return Err(TermParseError::msg(
"Unexpected character in a unicode escape",
))
}
}
} else {
return Err(TermParseErrorKind::msg("Unexpected literal string end"));
return Err(TermParseError::msg("Unexpected literal string end"));
}
}
char::from_u32(value)
.ok_or_else(|| TermParseErrorKind::msg("Invalid encoded unicode code point"))
char::from_u32(value).ok_or_else(|| TermParseError::msg("Invalid encoded unicode code point"))
}
/// An error raised during term serialization parsing using the [`FromStr`] trait.
@ -446,8 +448,8 @@ enum TermParseErrorKind {
Msg { msg: &'static str },
}
impl TermParseErrorKind {
impl TermParseError {
pub(crate) fn msg(msg: &'static str) -> Self {
TermParseErrorKind::Msg { msg }
Self(TermParseErrorKind::Msg { msg })
}
}

@ -14,24 +14,16 @@ pub enum ParseError {
impl ParseError {
pub(crate) fn msg(msg: &'static str) -> Self {
Self::Syntax(SyntaxErrorKind::Msg { msg }.into())
Self::Syntax(SyntaxError(SyntaxErrorKind::Msg { msg }))
}
}
// impl From<oxttl::SyntaxError> for SyntaxError {
// #[inline]
// fn from(error: oxttl::SyntaxError) -> Self {
// Self(SyntaxErrorKind::Turtle(error))
// }
// }
//
// impl From<oxrdfxml::SyntaxError> for SyntaxError {
// #[inline]
// fn from(error: oxrdfxml::SyntaxError) -> Self {
// Self(SyntaxErrorKind::RdfXml(error))
// }
// }
//
impl From<oxttl::SyntaxError> for SyntaxError {
#[inline]
fn from(error: oxttl::SyntaxError) -> Self {
Self(SyntaxErrorKind::Turtle(error))
}
}
impl From<oxttl::ParseError> for ParseError {
#[inline]
@ -43,6 +35,13 @@ impl From<oxttl::ParseError> for ParseError {
}
}
impl From<oxrdfxml::SyntaxError> for SyntaxError {
#[inline]
fn from(error: oxrdfxml::SyntaxError) -> Self {
Self(SyntaxErrorKind::RdfXml(error))
}
}
impl From<oxrdfxml::ParseError> for ParseError {
#[inline]
fn from(error: oxrdfxml::ParseError) -> Self {
@ -83,7 +82,7 @@ impl SyntaxError {
/// The location of the error inside of the file.
#[inline]
pub fn location(&self) -> Option<Range<TextPosition>> {
match self {
match &self.0 {
SyntaxErrorKind::Turtle(e) => {
let location = e.location();
Some(
@ -106,7 +105,7 @@ impl SyntaxError {
impl From<SyntaxError> for io::Error {
#[inline]
fn from(error: SyntaxError) -> Self {
match error {
match error.0 {
SyntaxErrorKind::Turtle(error) => error.into(),
SyntaxErrorKind::RdfXml(error) => error.into(),
SyntaxErrorKind::Msg { msg } => Self::new(io::ErrorKind::InvalidData, msg),

@ -31,14 +31,23 @@ 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::Xml(error)),
_ => Self::Syntax(SyntaxError {
inner: SyntaxErrorKind::Xml(error),
}),
}
}
}
/// An error in the syntax of the parsed file.
#[derive(Debug, thiserror::Error)]
pub enum SyntaxError {
#[error(transparent)]
pub struct SyntaxError {
#[from]
pub(crate) inner: SyntaxErrorKind,
}
#[derive(Debug, thiserror::Error)]
pub enum SyntaxErrorKind {
#[error(transparent)]
Xml(#[from] quick_xml::Error),
#[error("error while parsing IRI '{iri}': {error}")]
@ -61,15 +70,17 @@ impl SyntaxError {
/// Builds an error from a printable error message.
#[inline]
pub(crate) fn msg(msg: impl Into<String>) -> Self {
Self::Msg { msg: msg.into() }
Self {
inner: SyntaxErrorKind::Msg { msg: msg.into() },
}
}
}
impl From<SyntaxError> for io::Error {
#[inline]
fn from(error: SyntaxError) -> Self {
match error {
SyntaxError::Xml(error) => match error {
match error.inner {
SyntaxErrorKind::Xml(error) => match error {
quick_xml::Error::Io(error) => {
Arc::try_unwrap(error).unwrap_or_else(|e| Self::new(e.kind(), e))
}
@ -78,7 +89,7 @@ impl From<SyntaxError> for io::Error {
}
_ => Self::new(io::ErrorKind::InvalidData, error),
},
SyntaxError::Msg { msg } => Self::new(io::ErrorKind::InvalidData, msg),
SyntaxErrorKind::Msg { msg } => Self::new(io::ErrorKind::InvalidData, msg),
_ => Self::new(io::ErrorKind::InvalidData, error),
}
}

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

@ -2038,8 +2038,12 @@ fn time_on_timeline(props: &DateTimeSevenPropertyModel) -> Option<Decimal> {
}
/// A parsing error
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct ParseDateTimeError(#[from] ParseDateTimeErrorKind);
#[derive(Debug, Clone, thiserror::Error)]
pub enum ParseDateTimeError {
enum ParseDateTimeErrorKind {
#[error("{day} is not a valid day of {month}")]
InvalidDayOfMonth { day: u8, month: u8 },
#[error(transparent)]
@ -2052,7 +2056,7 @@ pub enum ParseDateTimeError {
impl ParseDateTimeError {
const fn msg(message: &'static str) -> Self {
Self::Message(message)
Self(ParseDateTimeErrorKind::Message(message))
}
}
@ -2308,7 +2312,7 @@ fn timezone_frag(input: &str) -> Result<(TimezoneOffset, &str), ParseDateTimeErr
Ok((
TimezoneOffset::new(sign * (hours * 60 + i16::from(minutes)))
.map_err(ParseDateTimeError::InvalidTimezone)?,
.map_err(|e| ParseDateTimeError(ParseDateTimeErrorKind::InvalidTimezone(e)))?,
input,
))
}
@ -2378,7 +2382,9 @@ 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::InvalidDayOfMonth { day, month });
return Err(ParseDateTimeError(
ParseDateTimeErrorKind::InvalidDayOfMonth { day, month },
));
}
Ok(())
}
@ -2390,6 +2396,12 @@ fn validate_day_of_month(year: Option<i64>, month: u8, day: u8) -> Result<(), Pa
#[error("overflow during xsd:dateTime computation")]
pub struct DateTimeOverflowError;
impl From<DateTimeOverflowError> for ParseDateTimeError {
fn from(error: DateTimeOverflowError) -> Self {
Self(ParseDateTimeErrorKind::Overflow(error))
}
}
/// The value provided as timezone is not valid.
///
/// Matches XPath [`FODT0003` error](https://www.w3.org/TR/xpath-functions-31/#ERRFODT0003).

@ -465,7 +465,7 @@ impl FromStr for Decimal {
// (\+|-)?([0-9]+(\.[0-9]*)?|\.[0-9]+)
let input = input.as_bytes();
if input.is_empty() {
return Err(ParseDecimalError::UnexpectedEnd);
return Err(PARSE_UNEXPECTED_END);
}
let (sign, mut input) = match input.first() {
@ -480,9 +480,9 @@ impl FromStr for Decimal {
if c.is_ascii_digit() {
value = value
.checked_mul(10)
.ok_or(ParseDecimalError::Overflow)?
.ok_or(PARSE_OVERFLOW)?
.checked_add(sign * i128::from(*c - b'0'))
.ok_or(ParseDecimalError::Overflow)?;
.ok_or(PARSE_OVERFLOW)?;
input = &input[1..];
} else {
break;
@ -492,12 +492,12 @@ impl FromStr for Decimal {
let mut exp = DECIMAL_PART_POW;
if let Some(c) = input.first() {
if *c != b'.' {
return Err(ParseDecimalError::UnexpectedChar);
return Err(PARSE_UNEXPECTED_CHAR);
}
input = &input[1..];
if input.is_empty() && !with_before_dot {
// We only have a dot
return Err(ParseDecimalError::UnexpectedEnd);
return Err(PARSE_UNEXPECTED_END);
}
while input.last() == Some(&b'0') {
// Hack to avoid underflows
@ -508,25 +508,25 @@ impl FromStr for Decimal {
exp /= 10;
value = value
.checked_mul(10)
.ok_or(ParseDecimalError::Overflow)?
.ok_or(PARSE_OVERFLOW)?
.checked_add(sign * i128::from(*c - b'0'))
.ok_or(ParseDecimalError::Overflow)?;
.ok_or(PARSE_OVERFLOW)?;
input = &input[1..];
} else {
return Err(ParseDecimalError::UnexpectedChar);
return Err(PARSE_UNEXPECTED_CHAR);
}
}
if exp == 0 {
// Underflow
return Err(ParseDecimalError::Underflow);
return Err(PARSE_UNDERFLOW);
}
} else if !with_before_dot {
// It's empty
return Err(ParseDecimalError::UnexpectedEnd);
return Err(PARSE_UNEXPECTED_END);
}
Ok(Self {
value: value.checked_mul(exp).ok_or(ParseDecimalError::Overflow)?,
value: value.checked_mul(exp).ok_or(PARSE_OVERFLOW)?,
})
}
}
@ -608,8 +608,12 @@ impl fmt::Display for Decimal {
}
/// An error when parsing a [`Decimal`].
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct ParseDecimalError(#[from] DecimalParseErrorKind);
#[derive(Debug, Clone, thiserror::Error)]
pub enum ParseDecimalError {
enum DecimalParseErrorKind {
#[error("Value overflow")]
Overflow,
#[error("Value underflow")]
@ -620,9 +624,16 @@ pub enum ParseDecimalError {
UnexpectedEnd,
}
const PARSE_OVERFLOW: ParseDecimalError = ParseDecimalError(DecimalParseErrorKind::Overflow);
const PARSE_UNDERFLOW: ParseDecimalError = ParseDecimalError(DecimalParseErrorKind::Underflow);
const PARSE_UNEXPECTED_CHAR: ParseDecimalError =
ParseDecimalError(DecimalParseErrorKind::UnexpectedChar);
const PARSE_UNEXPECTED_END: ParseDecimalError =
ParseDecimalError(DecimalParseErrorKind::UnexpectedEnd);
impl From<TooLargeForDecimalError> for ParseDecimalError {
fn from(_: TooLargeForDecimalError) -> Self {
Self::Overflow
Self(DecimalParseErrorKind::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, TextPosition};
use crate::error::{ParseError, SyntaxError, SyntaxErrorKind, TextPosition};
use memchr::memchr;
use oxrdf::vocab::xsd;
use oxrdf::*;
@ -508,21 +508,23 @@ impl<R: Read> TsvSolutionsReader<R> {
.sum::<usize>();
let start_position_bytes =
line.split('\t').take(i).map(|c| c.len() + 1).sum::<usize>();
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(),
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(),
},
},
}
})?))

@ -40,14 +40,23 @@ 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::Xml(error)),
_ => Self::Syntax(SyntaxError {
inner: SyntaxErrorKind::Xml(error),
}),
}
}
}
/// An error in the syntax of the parsed file.
#[derive(Debug, thiserror::Error)]
pub enum SyntaxError {
#[error(transparent)]
pub struct SyntaxError {
#[from]
pub(crate) inner: SyntaxErrorKind,
}
#[derive(Debug, thiserror::Error)]
pub(crate) enum SyntaxErrorKind {
#[error(transparent)]
Json(#[from] json_event_parser::SyntaxError),
#[error(transparent)]
@ -70,26 +79,30 @@ impl SyntaxError {
/// Builds an error from a printable error message.
#[inline]
pub(crate) fn msg(msg: impl Into<String>) -> Self {
Self::Msg {
msg: msg.into(),
location: None,
Self {
inner: SyntaxErrorKind::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::Msg {
msg: msg.into(),
location: Some(location),
Self {
inner: SyntaxErrorKind::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 {
Self::Json(e) => {
match &self.inner {
SyntaxErrorKind::Json(e) => {
let location = e.location();
Some(
TextPosition {
@ -103,9 +116,9 @@ impl SyntaxError {
},
)
}
Self::Term { location, .. } => Some(location.clone()),
Self::Msg { location, .. } => location.clone(),
Self::Xml(_) => None,
SyntaxErrorKind::Term { location, .. } => Some(location.clone()),
SyntaxErrorKind::Msg { location, .. } => location.clone(),
SyntaxErrorKind::Xml(_) => None,
}
}
}
@ -113,9 +126,9 @@ impl SyntaxError {
impl From<SyntaxError> for io::Error {
#[inline]
fn from(error: SyntaxError) -> Self {
match error {
SyntaxError::Json(error) => Self::new(io::ErrorKind::InvalidData, error),
SyntaxError::Xml(error) => match error {
match error.inner {
SyntaxErrorKind::Json(error) => Self::new(io::ErrorKind::InvalidData, error),
SyntaxErrorKind::Xml(error) => match error {
quick_xml::Error::Io(error) => {
Arc::try_unwrap(error).unwrap_or_else(|e| Self::new(e.kind(), e))
}
@ -124,8 +137,16 @@ impl From<SyntaxError> for io::Error {
}
_ => Self::new(io::ErrorKind::InvalidData, error),
},
SyntaxError::Term { .. } => Self::new(io::ErrorKind::InvalidData, error),
SyntaxError::Msg { msg, .. } => Self::new(io::ErrorKind::InvalidData, msg),
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),
}
}
}

@ -17,13 +17,14 @@ use std::str::FromStr;
/// 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(ParseError::Parser)
parser::QueryUnit(query, &mut state).map_err(|e| ParseError(ParseErrorKind::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(ParseError::Parser)?;
let operations = parser::UpdateInit(update, &mut state)
.map_err(|e| ParseError(ParseErrorKind::Parser(e)))?;
Ok(Update {
operations,
base_iri: state.base_iri,
@ -32,7 +33,11 @@ pub fn parse_update(update: &str, base_iri: Option<&str>) -> Result<Update, Pars
/// Error returned during SPARQL parsing.
#[derive(Debug, thiserror::Error)]
pub enum ParseError {
#[error(transparent)]
pub struct ParseError(#[from] ParseErrorKind);
#[derive(Debug, thiserror::Error)]
enum ParseErrorKind {
#[error("Invalid SPARQL base IRI provided: {0}")]
InvalidBaseIri(#[from] IriParseError),
#[error(transparent)]
@ -667,7 +672,10 @@ 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(ParseError::InvalidBaseIri)?)
Some(
Iri::parse(base_iri.to_owned())
.map_err(|e| ParseError(ParseErrorKind::InvalidBaseIri(e)))?,
)
} else {
None
},

Loading…
Cancel
Save