use oxrdf::TermParseError;
use quick_xml::encoding::EncodingError;
use std::io;
use std::ops::Range;
use std::sync::Arc;
#[derive(Debug, thiserror::Error)]
pub enum QueryResultsParseError {
#[error(transparent)]
Io(#[from] io::Error),
#[error(transparent)]
Syntax(#[from] QueryResultsSyntaxError),
}
impl From<QueryResultsParseError> for io::Error {
#[inline]
fn from(error: QueryResultsParseError) -> Self {
match error {
QueryResultsParseError::Io(error) => error,
QueryResultsParseError::Syntax(error) => error.into(),
}
}
}
#[doc(hidden)]
impl From<json_event_parser::ParseError> for QueryResultsParseError {
fn from(error: json_event_parser::ParseError) -> Self {
match error {
json_event_parser::ParseError::Syntax(error) => {
QueryResultsSyntaxError::from(error).into()
}
json_event_parser::ParseError::Io(error) => error.into(),
}
}
}
#[doc(hidden)]
impl From<quick_xml::Error> for QueryResultsParseError {
#[inline]
fn from(error: quick_xml::Error) -> Self {
match error {
quick_xml::Error::Io(error) => {
Self::Io(Arc::try_unwrap(error).unwrap_or_else(|e| io::Error::new(e.kind(), e)))
}
_ => Self::Syntax(QueryResultsSyntaxError(SyntaxErrorKind::Xml(error))),
}
}
}
#[doc(hidden)]
impl From<quick_xml::escape::EscapeError> for QueryResultsParseError {
#[inline]
fn from(error: quick_xml::escape::EscapeError) -> Self {
quick_xml::Error::from(error).into()
}
}
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct QueryResultsSyntaxError(#[from] SyntaxErrorKind);
#[derive(Debug, thiserror::Error)]
enum SyntaxErrorKind {
#[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>>,
},
}
impl QueryResultsSyntaxError {
pub(crate) fn msg(msg: impl Into<String>) -> Self {
Self(SyntaxErrorKind::Msg {
msg: msg.into(),
location: None,
})
}
pub(crate) fn term(error: TermParseError, term: String, location: Range<TextPosition>) -> Self {
Self(SyntaxErrorKind::Term {
error,
term,
location,
})
}
#[inline]
pub(crate) fn located_message(msg: impl Into<String>, location: Range<TextPosition>) -> Self {
Self(SyntaxErrorKind::Msg {
msg: msg.into(),
location: Some(location),
})
}
#[inline]
pub fn location(&self) -> Option<Range<TextPosition>> {
match &self.0 {
SyntaxErrorKind::Json(e) => {
let location = e.location();
Some(
TextPosition {
line: location.start.line,
column: location.start.column,
offset: location.start.offset,
}..TextPosition {
line: location.end.line,
column: location.end.column,
offset: location.end.offset,
},
)
}
SyntaxErrorKind::Term { location, .. } => Some(location.clone()),
SyntaxErrorKind::Msg { location, .. } => location.clone(),
SyntaxErrorKind::Xml(_) => None,
}
}
}
impl From<QueryResultsSyntaxError> for io::Error {
#[inline]
fn from(error: QueryResultsSyntaxError) -> Self {
match error.0 {
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))
}
_ => Self::new(io::ErrorKind::InvalidData, error),
},
SyntaxErrorKind::Term { .. } => Self::new(io::ErrorKind::InvalidData, error),
SyntaxErrorKind::Msg { msg, .. } => Self::new(io::ErrorKind::InvalidData, msg),
}
}
}
#[doc(hidden)]
impl From<json_event_parser::SyntaxError> for QueryResultsSyntaxError {
fn from(error: json_event_parser::SyntaxError) -> Self {
Self(SyntaxErrorKind::Json(error))
}
}
#[doc(hidden)]
impl From<EncodingError> for QueryResultsParseError {
fn from(error: EncodingError) -> Self {
quick_xml::Error::from(error).into()
}
}
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub struct TextPosition {
pub line: u64,
pub column: u64,
pub offset: u64,
}