1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Debug, Error)]
10pub enum Error {
11 #[error("I/O error: {0}")]
13 Io(#[from] std::io::Error),
14
15 #[error("UTF-8 error: {0}")]
17 Utf8(#[from] std::string::FromUtf8Error),
18
19 #[error("BER codec error: {0}")]
21 Ber(#[from] BerError),
22
23 #[error("S101 framing error: {0}")]
25 S101(#[from] S101Error),
26
27 #[error("Glow protocol error: {0}")]
29 Glow(#[from] GlowError),
30
31 #[error("Connection error: {0}")]
33 Connection(String),
34
35 #[error("Operation timed out")]
37 Timeout,
38
39 #[error("Path not found: {0}")]
41 PathNotFound(String),
42
43 #[error("Invalid operation: {0}")]
45 InvalidOperation(String),
46
47 #[error("Protocol version mismatch: expected {expected}, got {actual}")]
49 VersionMismatch { expected: u8, actual: u8 },
50
51 #[error("Server rejected request: {0}")]
53 Rejected(String),
54
55 #[error("Internal error: {0}")]
57 Internal(String),
58}
59
60#[derive(Debug, Error)]
62pub enum BerError {
63 #[error("Unexpected end of input")]
65 UnexpectedEof,
66
67 #[error("Invalid tag: {0}")]
69 InvalidTag(String),
70
71 #[error("Invalid length encoding")]
73 InvalidLength,
74
75 #[error("Length overflow: value too large")]
77 LengthOverflow,
78
79 #[error("Invalid value encoding for type {type_name}: {details}")]
81 InvalidValue { type_name: String, details: String },
82
83 #[error("Unsupported tag class: {0}")]
85 UnsupportedTagClass(u8),
86
87 #[error("Buffer too small: need {needed}, have {available}")]
89 BufferTooSmall { needed: usize, available: usize },
90
91 #[error("Invalid UTF-8 string: {0}")]
93 InvalidUtf8(#[from] std::string::FromUtf8Error),
94
95 #[error("Integer conversion error")]
97 IntegerConversion,
98}
99
100#[derive(Debug, Error)]
102pub enum S101Error {
103 #[error("Invalid frame marker: expected 0xFE, got 0x{0:02X}")]
105 InvalidFrameMarker(u8),
106
107 #[error("Invalid slot number: {0}")]
109 InvalidSlot(u8),
110
111 #[error("Invalid message type: 0x{0:02X}")]
113 InvalidMessageType(u8),
114
115 #[error("Invalid command: 0x{0:02X}")]
117 InvalidCommand(u8),
118
119 #[error("CRC mismatch: expected 0x{expected:04X}, got 0x{actual:04X}")]
121 CrcMismatch { expected: u16, actual: u16 },
122
123 #[error("Frame too large: {size} bytes exceeds maximum {max}")]
125 FrameTooLarge { size: usize, max: usize },
126
127 #[error("Incomplete frame: need more data")]
129 IncompleteFrame,
130
131 #[error("Invalid escape sequence")]
133 InvalidEscapeSequence,
134}
135
136#[derive(Debug, Error)]
138pub enum GlowError {
139 #[error("Unknown element type: {0}")]
141 UnknownElementType(u8),
142
143 #[error("Missing required field: {0}")]
145 MissingField(String),
146
147 #[error("Invalid field value for {field}: {details}")]
149 InvalidField { field: String, details: String },
150
151 #[error("Invalid tree structure: {0}")]
153 InvalidTree(String),
154
155 #[error("Unsupported feature: {0}")]
157 Unsupported(String),
158
159 #[error("Invalid path format: {0}")]
161 InvalidPath(String),
162
163 #[error("Type mismatch: expected {expected}, got {actual}")]
165 TypeMismatch { expected: String, actual: String },
166
167 #[error("Invalid matrix operation: {0}")]
169 InvalidMatrixOperation(String),
170
171 #[error("Function invocation failed: {0}")]
173 InvocationFailed(String),
174}
175
176impl Error {
177 pub fn connection<S: Into<String>>(msg: S) -> Self {
179 Error::Connection(msg.into())
180 }
181
182 pub fn invalid_operation<S: Into<String>>(msg: S) -> Self {
184 Error::InvalidOperation(msg.into())
185 }
186
187 pub fn path_not_found<S: Into<String>>(path: S) -> Self {
189 Error::PathNotFound(path.into())
190 }
191
192 pub fn internal<S: Into<String>>(msg: S) -> Self {
194 Error::Internal(msg.into())
195 }
196}
197
198impl BerError {
199 pub fn invalid_value<S1: Into<String>, S2: Into<String>>(type_name: S1, details: S2) -> Self {
201 BerError::InvalidValue {
202 type_name: type_name.into(),
203 details: details.into(),
204 }
205 }
206}
207
208impl GlowError {
209 pub fn missing_field<S: Into<String>>(field: S) -> Self {
211 GlowError::MissingField(field.into())
212 }
213
214 pub fn invalid_field<S1: Into<String>, S2: Into<String>>(field: S1, details: S2) -> Self {
216 GlowError::InvalidField {
217 field: field.into(),
218 details: details.into(),
219 }
220 }
221}