Skip to main content

ember_plus/
error.rs

1//! Error types for the Ember+ library.
2
3use thiserror::Error;
4
5/// Result type alias for Ember+ operations.
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// Ember+ error types.
9#[derive(Debug, Error)]
10pub enum Error {
11    /// I/O error during network operations.
12    #[error("I/O error: {0}")]
13    Io(#[from] std::io::Error),
14
15    /// UTF-8 conversion error.
16    #[error("UTF-8 error: {0}")]
17    Utf8(#[from] std::string::FromUtf8Error),
18
19    /// BER encoding/decoding error.
20    #[error("BER codec error: {0}")]
21    Ber(#[from] BerError),
22
23    /// S101 framing error.
24    #[error("S101 framing error: {0}")]
25    S101(#[from] S101Error),
26
27    /// Glow protocol error.
28    #[error("Glow protocol error: {0}")]
29    Glow(#[from] GlowError),
30
31    /// Connection error.
32    #[error("Connection error: {0}")]
33    Connection(String),
34
35    /// Timeout error.
36    #[error("Operation timed out")]
37    Timeout,
38
39    /// Path not found in tree.
40    #[error("Path not found: {0}")]
41    PathNotFound(String),
42
43    /// Invalid operation.
44    #[error("Invalid operation: {0}")]
45    InvalidOperation(String),
46
47    /// Protocol version mismatch.
48    #[error("Protocol version mismatch: expected {expected}, got {actual}")]
49    VersionMismatch { expected: u8, actual: u8 },
50
51    /// Server rejected the request.
52    #[error("Server rejected request: {0}")]
53    Rejected(String),
54
55    /// Internal error.
56    #[error("Internal error: {0}")]
57    Internal(String),
58}
59
60/// BER encoding/decoding errors.
61#[derive(Debug, Error)]
62pub enum BerError {
63    /// Unexpected end of input.
64    #[error("Unexpected end of input")]
65    UnexpectedEof,
66
67    /// Invalid tag encoding.
68    #[error("Invalid tag: {0}")]
69    InvalidTag(String),
70
71    /// Invalid length encoding.
72    #[error("Invalid length encoding")]
73    InvalidLength,
74
75    /// Length overflow.
76    #[error("Length overflow: value too large")]
77    LengthOverflow,
78
79    /// Invalid value encoding.
80    #[error("Invalid value encoding for type {type_name}: {details}")]
81    InvalidValue { type_name: String, details: String },
82
83    /// Unsupported tag class.
84    #[error("Unsupported tag class: {0}")]
85    UnsupportedTagClass(u8),
86
87    /// Buffer too small.
88    #[error("Buffer too small: need {needed}, have {available}")]
89    BufferTooSmall { needed: usize, available: usize },
90
91    /// Invalid UTF-8 string.
92    #[error("Invalid UTF-8 string: {0}")]
93    InvalidUtf8(#[from] std::string::FromUtf8Error),
94
95    /// Integer conversion error.
96    #[error("Integer conversion error")]
97    IntegerConversion,
98}
99
100/// S101 framing errors.
101#[derive(Debug, Error)]
102pub enum S101Error {
103    /// Invalid frame marker.
104    #[error("Invalid frame marker: expected 0xFE, got 0x{0:02X}")]
105    InvalidFrameMarker(u8),
106
107    /// Invalid slot number.
108    #[error("Invalid slot number: {0}")]
109    InvalidSlot(u8),
110
111    /// Invalid message type.
112    #[error("Invalid message type: 0x{0:02X}")]
113    InvalidMessageType(u8),
114
115    /// Invalid command.
116    #[error("Invalid command: 0x{0:02X}")]
117    InvalidCommand(u8),
118
119    /// CRC mismatch.
120    #[error("CRC mismatch: expected 0x{expected:04X}, got 0x{actual:04X}")]
121    CrcMismatch { expected: u16, actual: u16 },
122
123    /// Frame too large.
124    #[error("Frame too large: {size} bytes exceeds maximum {max}")]
125    FrameTooLarge { size: usize, max: usize },
126
127    /// Incomplete frame.
128    #[error("Incomplete frame: need more data")]
129    IncompleteFrame,
130
131    /// Invalid escape sequence.
132    #[error("Invalid escape sequence")]
133    InvalidEscapeSequence,
134}
135
136/// Glow protocol errors.
137#[derive(Debug, Error)]
138pub enum GlowError {
139    /// Unknown element type.
140    #[error("Unknown element type: {0}")]
141    UnknownElementType(u8),
142
143    /// Missing required field.
144    #[error("Missing required field: {0}")]
145    MissingField(String),
146
147    /// Invalid field value.
148    #[error("Invalid field value for {field}: {details}")]
149    InvalidField { field: String, details: String },
150
151    /// Invalid tree structure.
152    #[error("Invalid tree structure: {0}")]
153    InvalidTree(String),
154
155    /// Unsupported feature.
156    #[error("Unsupported feature: {0}")]
157    Unsupported(String),
158
159    /// Invalid path format.
160    #[error("Invalid path format: {0}")]
161    InvalidPath(String),
162
163    /// Type mismatch.
164    #[error("Type mismatch: expected {expected}, got {actual}")]
165    TypeMismatch { expected: String, actual: String },
166
167    /// Invalid matrix operation.
168    #[error("Invalid matrix operation: {0}")]
169    InvalidMatrixOperation(String),
170
171    /// Invocation failed.
172    #[error("Function invocation failed: {0}")]
173    InvocationFailed(String),
174}
175
176impl Error {
177    /// Create a connection error.
178    pub fn connection<S: Into<String>>(msg: S) -> Self {
179        Error::Connection(msg.into())
180    }
181
182    /// Create an invalid operation error.
183    pub fn invalid_operation<S: Into<String>>(msg: S) -> Self {
184        Error::InvalidOperation(msg.into())
185    }
186
187    /// Create a path not found error.
188    pub fn path_not_found<S: Into<String>>(path: S) -> Self {
189        Error::PathNotFound(path.into())
190    }
191
192    /// Create an internal error.
193    pub fn internal<S: Into<String>>(msg: S) -> Self {
194        Error::Internal(msg.into())
195    }
196}
197
198impl BerError {
199    /// Create an invalid value error.
200    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    /// Create a missing field error.
210    pub fn missing_field<S: Into<String>>(field: S) -> Self {
211        GlowError::MissingField(field.into())
212    }
213
214    /// Create an invalid field error.
215    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}