1use std::fmt::{Debug, Display};
7
8pub trait ErrorSource: std::error::Error {
13 fn as_error_source(&self) -> &(dyn std::error::Error + 'static);
14}
15
16#[derive(Debug)]
20pub enum Error {
21 Tokenizer {
25 representation: String,
26 source: Box<dyn std::error::Error>,
27 },
28 ParserExpected {
32 rule_fn: String,
33 expecting: String,
34 },
35 ParserUnexpected {
39 rule_fn: String,
40 given: String,
41 expecting: Vec<String>,
42 },
43 ParserUnreachable {
44 rule_fn: String,
45 given: String,
46 },
47 InvalidFromStr {
51 value: String,
52 name: String,
53 },
54 InvalidLiteralTypeCooercion {
58 from_type: String,
59 to_type: String,
60 },
61 HexDecoder {
65 value: String,
66 index: usize,
67 },
68
69 InvalidBlankNodeName {
73 name: String,
74 },
75 EmptyQName,
79 InvalidQName {
83 name: String,
84 },
85 ProviderMismatch {
89 lhs: String,
90 rhs: String,
91 },
92 InvalidMatch,
96 AbsoluteIriExpected {
100 uri: String,
101 },
102
103 InvalidState,
107 RdfStarNotSupported {
111 representation: String,
112 },
113 FormulaeNotSupported {
117 representation: String,
118 },
119 QueryResultsFormat {
123 representation: String,
124 },
125
126 Borrow(::std::cell::BorrowError),
130 Io(::std::io::Error),
134 Iri(::rdftk_iri::Error),
138 LanguageTag(::language_tags::ParseError),
142 Name(::rdftk_iri::NameParseError),
146 Utf8(::std::string::FromUtf8Error),
150
151 #[cfg(feature = "binary_types")]
155 Base64Decoder(::base64::DecodeError),
156}
157
158pub type Result<T> = std::result::Result<T, Error>;
162
163#[inline(always)]
171pub fn invalid_from_str_error<S1, S2>(value: S1, type_name: S2) -> Error
172where
173 S1: Into<String>,
174 S2: Into<String>,
175{
176 Error::InvalidFromStr {
177 value: value.into(),
178 name: type_name.into(),
179 }
180}
181
182#[inline(always)]
186pub fn invalid_blank_node_name_error<S>(name: S) -> Error
187where
188 S: Into<String>,
189{
190 Error::InvalidBlankNodeName { name: name.into() }
191}
192
193#[inline(always)]
197pub fn empty_qname_error() -> Error {
198 Error::EmptyQName
199}
200
201#[inline(always)]
205pub fn invalid_qname_error<S>(name: S) -> Error
206where
207 S: Into<String>,
208{
209 Error::InvalidQName { name: name.into() }
210}
211
212#[inline(always)]
216pub fn provider_mismatch_error<S1, S2>(lhs: S1, rhs: S2) -> Error
217where
218 S1: Into<String>,
219 S2: Into<String>,
220{
221 Error::ProviderMismatch {
222 lhs: lhs.into(),
223 rhs: rhs.into(),
224 }
225}
226
227#[inline(always)]
231pub fn invalid_match_error() -> Error {
232 Error::InvalidMatch
233}
234
235#[inline(always)]
239pub fn absolute_iri_expected_error<S>(uri: S) -> Error
240where
241 S: Into<String>,
242{
243 Error::AbsoluteIriExpected { uri: uri.into() }
244}
245
246#[inline(always)]
250pub fn invalid_state_error() -> Error {
251 Error::InvalidState
252}
253
254#[inline(always)]
258pub fn rdf_star_not_supported_error<S>(representation: S) -> Error
259where
260 S: Into<String>,
261{
262 Error::RdfStarNotSupported {
263 representation: representation.into(),
264 }
265}
266
267#[inline(always)]
271pub fn formulae_not_supported_error<S>(representation: S) -> Error
272where
273 S: Into<String>,
274{
275 Error::FormulaeNotSupported {
276 representation: representation.into(),
277 }
278}
279
280#[inline(always)]
284pub fn query_results_format_error<S>(representation: S) -> Error
285where
286 S: Into<String>,
287{
288 Error::QueryResultsFormat {
289 representation: representation.into(),
290 }
291}
292
293#[inline(always)]
299pub fn print_trace(e: &dyn std::error::Error) {
300 println!("{}", error_trace(e));
301}
302
303#[inline(always)]
307pub fn eprint_trace(e: &dyn std::error::Error) {
308 eprintln!("{}", error_trace(e));
309}
310
311#[inline(always)]
315pub fn error_trace(e: &dyn std::error::Error) -> String {
316 trace_one(e, 1)
317}
318
319impl Display for Error {
324 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
325 write!(
326 f,
327 "{}",
328 match self {
329 Self::Tokenizer { representation, source } => format!("The tokenizer for {representation} generated an error: {source}"),
330 Self::ParserExpected { rule_fn, expecting } => format!("Parser was expecting `{expecting}` in function `{rule_fn}`."),
331 Self::ParserUnexpected { rule_fn, given, expecting } => format!("Parser was not expecting `{given}` in function `{rule_fn}`; expecting {expecting:?}."),
332 Self::ParserUnreachable { rule_fn, given } => format!("Parser should not have reached `{given}` in function `{rule_fn}`."),
333 Self::InvalidFromStr { value, name } => format!(
334 "The String value `{value}` is not a valid value for it's type: '{name}'."
335 ),
336 Self::InvalidBlankNodeName { name } =>
337 format!("The String value `{name}` is not a valid Blank Node name."),
338 Self::InvalidLiteralTypeCooercion { from_type, to_type } =>
339 format!("Not possible to coerce a literal from `{from_type}` into `{to_type}`."),
340 Self::HexDecoder { value, index } => format!("Could not decode a hex-encoded string, bad value `{value}` at index {index}"),
341 Self::EmptyQName => "A QName may not have an empty name part.".to_string(),
342 Self::InvalidQName { name } =>
343 format!("The String value `{name}` is not a valid QName."),
344 Self::ProviderMismatch { lhs, rhs } => format!(
345 "Values from these different providers cannot be combined ({lhs:?}, {rhs:?})."
346 ),
347 Self::InvalidMatch => "The match combination is not valid.".to_string(),
348 Self::AbsoluteIriExpected { uri } =>
349 format!("An Absolute IRI was expected at, not '{uri}'."),
350 Self::InvalidState =>
351 "Some model element was in an invalid state for the requested operation.".to_string(),
352 Self::RdfStarNotSupported { representation } => format!("Statements as objects, from RDF*, are not supported by the {representation:?} representation."),
353 Self::FormulaeNotSupported { representation } => format!("Cited model.formulae, from N3, are not supported by the {representation:?} representation."),
354 Self::QueryResultsFormat { representation } => format!("Could not read or write query results in the {representation:?} representation."),
355 Self::Borrow(source) => format!("A cell borrow error occurred; source: {source}"),
356 Self::Io(source) => format!("An I/O error occurred; source: {source}"),
357 Self::Iri(source) =>format!("An error occurred parsing an IRI; source: {source}"),
358 Self::LanguageTag(source) => format!("An error occurred parsing a language tag; source: {source}"),
359 Self::Name(source) => format!("An error occurred parsing a name; source: {source}"),
360 Self::Utf8(source) => format!("An error occurred parsing a UTF-8 string; source: {source}"),
361 #[cfg(feature = "binary_types")]
362 Self::Base64Decoder(source) => format!("An error occurred parsing a base64 encoded string; source: {source}"),
363 }
364 )
365 }
366}
367
368impl std::error::Error for Error {
369 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
370 match self {
371 Self::Borrow(source) => Some(source),
373 Self::Io(source) => Some(source),
374 Self::Iri(source) => Some(source),
375 Self::LanguageTag(source) => Some(source),
376 Self::Name(source) => Some(source),
377 Self::Utf8(source) => Some(source),
378 Self::Base64Decoder(source) => Some(source),
379 _ => None,
380 }
381 }
382}
383
384impl From<::std::cell::BorrowError> for Error {
385 fn from(source: ::std::cell::BorrowError) -> Self {
386 Self::Borrow(source)
387 }
388}
389
390impl From<::std::io::Error> for Error {
391 fn from(source: ::std::io::Error) -> Self {
392 Self::Io(source)
393 }
394}
395
396impl From<::rdftk_iri::Error> for Error {
397 fn from(source: ::rdftk_iri::Error) -> Self {
398 Self::Iri(source)
399 }
400}
401
402impl From<::language_tags::ParseError> for Error {
403 fn from(source: ::language_tags::ParseError) -> Self {
404 Self::LanguageTag(source)
405 }
406}
407
408impl From<::rdftk_iri::NameParseError> for Error {
409 fn from(source: ::rdftk_iri::NameParseError) -> Self {
410 Self::Name(source)
411 }
412}
413
414impl From<::std::string::FromUtf8Error> for Error {
415 fn from(source: ::std::string::FromUtf8Error) -> Self {
416 Self::Utf8(source)
417 }
418}
419
420#[cfg(feature = "binary_types")]
421impl From<::base64::DecodeError> for Error {
422 fn from(source: ::base64::DecodeError) -> Self {
423 Self::Base64Decoder(source)
424 }
425}
426
427#[allow(clippy::from_over_into)]
428impl<T> Into<Result<T>> for Error {
429 fn into(self) -> Result<T> {
430 Err(self)
431 }
432}
433
434fn trace_one(e: &dyn std::error::Error, count: i32) -> String {
439 use std::fmt::Write;
440
441 let mut trace = String::new();
442
443 writeln!(&mut trace, "{}. {}", count, e).expect("Failed to write message.");
444
445 if let Some(source) = e.source() {
446 write!(&mut trace, "{}", trace_one(source, count + 1)).expect("Failed to write source.");
447 }
448
449 writeln!(&mut trace).expect("Failed to write line break");
450 trace
451}