1use std::error::Error as StdError;
2
3use thiserror::Error as ThisError;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum ErrorKind {
7 NotImplemented,
8 Encode,
9 Decode,
10 Serialize,
11 Deserialize,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum ErrorStage {
16 Encode,
17 Decode,
18 Unknown,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct Location {
23 pub offset: usize,
24 pub line: usize,
25 pub column: usize,
26}
27
28#[derive(Debug, ThisError)]
29#[error("{message}")]
30pub struct Error {
31 pub kind: ErrorKind,
32 pub stage: ErrorStage,
33 pub message: String,
34 pub location: Option<Location>,
35 #[source]
36 source: Option<Box<dyn StdError + Send + Sync + 'static>>,
37}
38
39impl Error {
40 pub fn not_implemented(context: &'static str) -> Self {
41 Self::new(
42 ErrorKind::NotImplemented,
43 ErrorStage::Unknown,
44 format!("not implemented: {context}"),
45 )
46 }
47
48 pub fn encode(message: impl Into<String>) -> Self {
49 Self::new(ErrorKind::Encode, ErrorStage::Encode, message)
50 }
51
52 pub fn encode_with_source(
53 message: impl Into<String>,
54 source: impl StdError + Send + Sync + 'static,
55 ) -> Self {
56 Self::new_with_source(ErrorKind::Encode, ErrorStage::Encode, message, source)
57 }
58
59 pub fn decode(message: impl Into<String>) -> Self {
60 Self::new(ErrorKind::Decode, ErrorStage::Decode, message)
61 }
62
63 pub fn decode_with_source(
64 message: impl Into<String>,
65 source: impl StdError + Send + Sync + 'static,
66 ) -> Self {
67 Self::new_with_source(ErrorKind::Decode, ErrorStage::Decode, message, source)
68 }
69
70 pub fn serialize(message: impl Into<String>) -> Self {
71 Self::new(ErrorKind::Serialize, ErrorStage::Encode, message)
72 }
73
74 pub fn serialize_with_source(
75 message: impl Into<String>,
76 source: impl StdError + Send + Sync + 'static,
77 ) -> Self {
78 Self::new_with_source(ErrorKind::Serialize, ErrorStage::Encode, message, source)
79 }
80
81 pub fn deserialize(message: impl Into<String>) -> Self {
82 Self::new(ErrorKind::Deserialize, ErrorStage::Decode, message)
83 }
84
85 pub fn deserialize_with_source(
86 message: impl Into<String>,
87 source: impl StdError + Send + Sync + 'static,
88 ) -> Self {
89 Self::new_with_source(ErrorKind::Deserialize, ErrorStage::Decode, message, source)
90 }
91
92 pub fn with_stage(mut self, stage: ErrorStage) -> Self {
93 self.stage = stage;
94 self
95 }
96
97 pub fn with_source(mut self, source: impl StdError + Send + Sync + 'static) -> Self {
98 self.source = Some(Box::new(source));
99 self
100 }
101
102 pub fn with_location(mut self, location: Location) -> Self {
103 self.location = Some(location);
104 self
105 }
106
107 fn new(kind: ErrorKind, stage: ErrorStage, message: impl Into<String>) -> Self {
108 Self {
109 kind,
110 stage,
111 message: message.into(),
112 location: None,
113 source: None,
114 }
115 }
116
117 fn new_with_source(
118 kind: ErrorKind,
119 stage: ErrorStage,
120 message: impl Into<String>,
121 source: impl StdError + Send + Sync + 'static,
122 ) -> Self {
123 Self {
124 kind,
125 stage,
126 message: message.into(),
127 location: None,
128 source: Some(Box::new(source)),
129 }
130 }
131}