1use json_event_parser::{JsonParseError, JsonSyntaxError};
2use oxrdf::TermParseError;
3use quick_xml::encoding::EncodingError;
4use std::io;
5use std::ops::Range;
6use std::sync::Arc;
7
8#[derive(Debug, thiserror::Error)]
10pub enum QueryResultsParseError {
11 #[error(transparent)]
13 Io(#[from] io::Error),
14 #[error(transparent)]
16 Syntax(#[from] QueryResultsSyntaxError),
17}
18
19impl From<QueryResultsParseError> for io::Error {
20 #[inline]
21 fn from(error: QueryResultsParseError) -> Self {
22 match error {
23 QueryResultsParseError::Io(error) => error,
24 QueryResultsParseError::Syntax(error) => error.into(),
25 }
26 }
27}
28
29#[doc(hidden)]
30impl From<JsonParseError> for QueryResultsParseError {
31 fn from(error: JsonParseError) -> Self {
32 match error {
33 JsonParseError::Syntax(error) => QueryResultsSyntaxError::from(error).into(),
34 JsonParseError::Io(error) => error.into(),
35 }
36 }
37}
38
39#[doc(hidden)]
40impl From<quick_xml::Error> for QueryResultsParseError {
41 #[inline]
42 fn from(error: quick_xml::Error) -> Self {
43 match error {
44 quick_xml::Error::Io(error) => {
45 Self::Io(Arc::try_unwrap(error).unwrap_or_else(|e| io::Error::new(e.kind(), e)))
46 }
47 _ => Self::Syntax(QueryResultsSyntaxError(SyntaxErrorKind::Xml(error))),
48 }
49 }
50}
51
52#[doc(hidden)]
53impl From<quick_xml::escape::EscapeError> for QueryResultsParseError {
54 #[inline]
55 fn from(error: quick_xml::escape::EscapeError) -> Self {
56 quick_xml::Error::from(error).into()
57 }
58}
59#[derive(Debug, thiserror::Error)]
61#[error(transparent)]
62pub struct QueryResultsSyntaxError(#[from] SyntaxErrorKind);
63
64#[derive(Debug, thiserror::Error)]
65enum SyntaxErrorKind {
66 #[error(transparent)]
67 Json(#[from] JsonSyntaxError),
68 #[error(transparent)]
69 Xml(#[from] quick_xml::Error),
70 #[error("Error {error} on '{term}' in line {}", location.start.line + 1)]
71 Term {
72 #[source]
73 error: TermParseError,
74 term: String,
75 location: Range<TextPosition>,
76 },
77 #[error("{msg}")]
78 Msg {
79 msg: String,
80 location: Option<Range<TextPosition>>,
81 },
82}
83
84impl QueryResultsSyntaxError {
85 pub(crate) fn msg(msg: impl Into<String>) -> Self {
87 Self(SyntaxErrorKind::Msg {
88 msg: msg.into(),
89 location: None,
90 })
91 }
92
93 pub(crate) fn term(error: TermParseError, term: String, location: Range<TextPosition>) -> Self {
94 Self(SyntaxErrorKind::Term {
95 error,
96 term,
97 location,
98 })
99 }
100
101 #[inline]
103 pub(crate) fn located_message(msg: impl Into<String>, location: Range<TextPosition>) -> Self {
104 Self(SyntaxErrorKind::Msg {
105 msg: msg.into(),
106 location: Some(location),
107 })
108 }
109
110 #[inline]
112 pub fn location(&self) -> Option<Range<TextPosition>> {
113 match &self.0 {
114 SyntaxErrorKind::Json(e) => {
115 let location = e.location();
116 Some(
117 TextPosition {
118 line: location.start.line,
119 column: location.start.column,
120 offset: location.start.offset,
121 }..TextPosition {
122 line: location.end.line,
123 column: location.end.column,
124 offset: location.end.offset,
125 },
126 )
127 }
128 SyntaxErrorKind::Term { location, .. } => Some(location.clone()),
129 SyntaxErrorKind::Msg { location, .. } => location.clone(),
130 SyntaxErrorKind::Xml(_) => None,
131 }
132 }
133}
134
135impl From<QueryResultsSyntaxError> for io::Error {
136 #[inline]
137 fn from(error: QueryResultsSyntaxError) -> Self {
138 match error.0 {
139 SyntaxErrorKind::Json(error) => Self::new(io::ErrorKind::InvalidData, error),
140 SyntaxErrorKind::Xml(error) => match error {
141 quick_xml::Error::Io(error) => {
142 Arc::try_unwrap(error).unwrap_or_else(|e| Self::new(e.kind(), e))
143 }
144 _ => Self::new(io::ErrorKind::InvalidData, error),
145 },
146 SyntaxErrorKind::Term { .. } => Self::new(io::ErrorKind::InvalidData, error),
147 SyntaxErrorKind::Msg { msg, .. } => Self::new(io::ErrorKind::InvalidData, msg),
148 }
149 }
150}
151
152#[doc(hidden)]
153impl From<JsonSyntaxError> for QueryResultsSyntaxError {
154 fn from(error: JsonSyntaxError) -> Self {
155 Self(SyntaxErrorKind::Json(error))
156 }
157}
158
159#[doc(hidden)]
160impl From<EncodingError> for QueryResultsParseError {
161 fn from(error: EncodingError) -> Self {
162 quick_xml::Error::from(error).into()
163 }
164}
165
166#[derive(Eq, PartialEq, Debug, Clone, Copy)]
168pub struct TextPosition {
169 pub line: u64,
170 pub column: u64,
171 pub offset: u64,
172}