horned_owl/
error.rs

1//! Errors for the Horned-OWL library
2use std::fmt::{Display, Formatter};
3use std::ops::Range;
4
5use pest::RuleType;
6use thiserror::Error;
7
8/// The location in a file of an error
9#[derive(Debug)]
10pub enum Location {
11    BytePosition(usize),
12    ByteSpan(Range<usize>),
13    Unknown,
14}
15
16impl From<usize> for Location {
17    fn from(u: usize) -> Self {
18        Location::BytePosition(u)
19    }
20}
21
22impl From<Range<usize>> for Location {
23    fn from(r: Range<usize>) -> Self {
24        Location::ByteSpan(r)
25    }
26}
27
28impl From<pest::error::InputLocation> for Location {
29    fn from(l: pest::error::InputLocation) -> Self {
30        match l {
31            pest::error::InputLocation::Pos(x) => Location::BytePosition(x),
32            pest::error::InputLocation::Span((x, y)) => Location::ByteSpan(x..y),
33        }
34    }
35}
36
37impl<'i> From<pest::Span<'i>> for Location {
38    fn from(span: pest::Span<'i>) -> Self {
39        Location::ByteSpan(span.start()..span.end())
40    }
41}
42
43impl Display for Location {
44    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
45        match self {
46            Self::BytePosition(u) => write!(f, "Byte Position: {u}"),
47            Self::ByteSpan(r) => write!(f, "Byte Span: {} to {}", r.start, r.end),
48            Self::Unknown => write!(f, "Unknown"),
49        }
50    }
51}
52
53/// Error for the Horned library
54#[derive(Debug, Error)]
55pub enum HornedError {
56    /// An IO Error
57    #[error("IO Error: {0}")]
58    IOError(#[from] std::io::Error),
59
60    /// An error found during the parsing of an underlying format
61    #[error("Parsing Error: {0}")]
62    ParserError(Box<dyn std::error::Error>, Location),
63
64    /// Data has been given that would we cannot make sense or would
65    /// result in invalid OWL
66    #[error("Validity Error: {0} at {1}")]
67    ValidityError(String, Location),
68
69    /// A command has been given that is invalid
70    #[error("Command Error: {0}")]
71    CommandError(String),
72
73    /// Import Error
74    #[error("Cannot import IRI: {0}")]
75    ImportError(String),
76}
77
78macro_rules! invalid {
79    ($($arg:tt)*) => {
80        HornedError::ValidityError(format!($($arg)*), crate::error::Location::Unknown)
81    }
82}
83
84pub(crate) use invalid;
85
86impl HornedError {
87    pub fn invalid_at<S: Into<String>, L: Into<Location>>(s: S, l: L) -> HornedError {
88        HornedError::ValidityError(s.into(), l.into())
89    }
90    pub fn invalid<S: Into<String>>(s: S) -> HornedError {
91        HornedError::ValidityError(s.into(), Location::Unknown)
92    }
93}
94
95impl From<quick_xml::Error> for HornedError {
96    fn from(e: quick_xml::Error) -> Self {
97        Self::ParserError(e.into(), Location::Unknown)
98    }
99}
100
101impl From<rio_xml::RdfXmlError> for HornedError {
102    fn from(e: rio_xml::RdfXmlError) -> Self {
103        Self::ParserError(e.into(), Location::Unknown)
104    }
105}
106
107impl<R: RuleType + 'static> From<pest::error::Error<R>> for HornedError {
108    fn from(e: pest::error::Error<R>) -> Self {
109        let location = e.location.clone().into();
110        Self::ParserError(e.into(), location)
111    }
112}
113
114#[cfg(feature = "remote")]
115impl From<ureq::Error> for HornedError {
116    fn from(e: ureq::Error) -> Self {
117        Self::ParserError(e.into(), Location::Unknown)
118    }
119}