1use std::ops::Range;
2use std::{fmt, io};
3
4#[derive(Eq, PartialEq, Debug, Copy, Clone)]
6pub struct TextPosition {
7 pub line: u64,
8 pub column: u64,
9 pub offset: u64,
10}
11
12#[derive(Debug, thiserror::Error)]
16pub struct TurtleSyntaxError {
17 location: Range<TextPosition>,
18 message: String,
19}
20
21impl TurtleSyntaxError {
22 pub(crate) fn new(location: Range<TextPosition>, message: impl Into<String>) -> Self {
23 Self {
24 location,
25 message: message.into(),
26 }
27 }
28
29 #[inline]
31 pub fn location(&self) -> Range<TextPosition> {
32 self.location.clone()
33 }
34
35 #[inline]
37 pub fn message(&self) -> &str {
38 &self.message
39 }
40}
41
42impl fmt::Display for TurtleSyntaxError {
43 #[inline]
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 if self.location.start.offset + 1 >= self.location.end.offset {
46 write!(
47 f,
48 "Parser error at line {} column {}: {}",
49 self.location.start.line + 1,
50 self.location.start.column + 1,
51 self.message
52 )
53 } else if self.location.start.line == self.location.end.line {
54 write!(
55 f,
56 "Parser error at line {} between columns {} and {}: {}",
57 self.location.start.line + 1,
58 self.location.start.column + 1,
59 self.location.end.column + 1,
60 self.message
61 )
62 } else {
63 write!(
64 f,
65 "Parser error between line {} column {} and line {} column {}: {}",
66 self.location.start.line + 1,
67 self.location.start.column + 1,
68 self.location.end.line + 1,
69 self.location.end.column + 1,
70 self.message
71 )
72 }
73 }
74}
75
76impl From<TurtleSyntaxError> for io::Error {
77 #[inline]
78 fn from(error: TurtleSyntaxError) -> Self {
79 Self::new(io::ErrorKind::InvalidData, error)
80 }
81}
82
83#[derive(Debug, thiserror::Error)]
87pub enum TurtleParseError {
88 #[error(transparent)]
90 Io(#[from] io::Error),
91 #[error(transparent)]
93 Syntax(#[from] TurtleSyntaxError),
94}
95
96impl From<TurtleParseError> for io::Error {
97 #[inline]
98 fn from(error: TurtleParseError) -> Self {
99 match error {
100 TurtleParseError::Syntax(e) => e.into(),
101 TurtleParseError::Io(e) => e,
102 }
103 }
104}