1use std::fmt;
2use std::path::{Path, PathBuf};
3
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7#[error("Expected {expected} {location} but observed: {observed}")]
8pub struct ParseError {
9 expected: &'static str,
10 observed: String,
11 location: Location,
12}
13
14#[derive(Debug)]
15pub enum Location {
16 Unknown,
17 File { path: PathBuf, line: usize },
18 Item { type_: &'static str, index: usize },
19}
20
21impl fmt::Display for Location {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 Location::Unknown => write!(f, "at unknown location"),
25 Location::File { path, line } => {
26 write!(f, "in file {} on line {}", path.as_path().display(), line)
27 }
28 Location::Item { type_, index } => {
29 write!(f, "for item of type {} at index {}", type_, index)
30 }
31 }
32 }
33}
34
35impl ParseError {
36 pub fn somewhere(expected: &'static str, observed: String) -> Self {
37 Self {
38 expected,
39 observed,
40 location: Location::Unknown,
41 }
42 }
43
44 pub fn file(path: PathBuf, line: usize, expected: &'static str, observed: String) -> Self {
45 let location = Location::File { path, line };
46 Self {
47 observed,
48 expected,
49 location,
50 }
51 }
52
53 pub fn item(
54 type_: &'static str,
55 index: usize,
56 expected: &'static str,
57 observed: String,
58 ) -> Self {
59 let location = Location::Item { type_, index };
60 Self {
61 observed,
62 expected,
63 location,
64 }
65 }
66}
67
68#[derive(Debug, Error)]
69pub struct FileError {
70 path: Option<PathBuf>,
71 #[source]
72 source: FileErrorSource,
73}
74
75impl FileError {
76 pub fn io<P: AsRef<Path>>(path: Option<P>, error: std::io::Error) -> Self {
77 let path = match path {
78 Some(p) => Some(p.as_ref().to_path_buf()),
79 None => None,
80 };
81 Self {
82 path,
83 source: error.into(),
84 }
85 }
86
87 pub fn parse<P: AsRef<Path>>(path: Option<P>, error: ParseError) -> Self {
88 let path = match path {
89 Some(p) => Some(p.as_ref().to_path_buf()),
90 None => None,
91 };
92 Self {
93 path,
94 source: error.into(),
95 }
96 }
97}
98
99impl fmt::Display for FileError {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match &self.path {
102 Some(path) => write!(f, "Failed to work with file {}", path.display()),
103 None => write!(f, "Failed to work fith anonymous file"),
104 }
105 }
106}
107
108#[derive(Debug, Error)]
109pub enum FileErrorSource {
110 #[error("Failed to parse file")]
111 Parse {
112 #[from]
113 source: ParseError,
114 },
115 #[error("Failed to read/write to file")]
116 IO {
117 #[from]
118 source: std::io::Error,
119 },
120}
121
122#[derive(Debug, Error)]
123pub struct SequenceError {
124 sequence_name: String,
125 message: &'static str,
126 #[source]
127 source: Option<Box<dyn std::error::Error>>,
128}
129
130impl SequenceError {
131 pub fn new(
132 sequence_name: String,
133 message: &'static str,
134 source: Option<Box<dyn std::error::Error>>,
135 ) -> Self {
136 Self {
137 sequence_name,
138 message,
139 source,
140 }
141 }
142}
143
144impl fmt::Display for SequenceError {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 write!(
147 f,
148 "Error in Sequence {}: {}",
149 self.sequence_name, self.message
150 )
151 }
152}
153
154#[derive(Debug, Error)]
156pub enum MutexpectError {
157 #[error(transparent)]
158 ParseError(#[from] ParseError),
159 #[error(transparent)]
160 FileError(#[from] FileError),
161 #[error(transparent)]
162 SequenceError(#[from] SequenceError),
163}