streamkit_core/error.rs
1// SPDX-FileCopyrightText: © 2025 StreamKit Contributors
2//
3// SPDX-License-Identifier: MPL-2.0
4
5//! Structured error types for StreamKit.
6//!
7//! This module provides a hierarchy of error types for better error handling
8//! and programmatic error inspection. All errors implement `Display` and can
9//! be converted to/from `String` for backward compatibility.
10
11use thiserror::Error;
12
13/// Main error type for StreamKit operations.
14///
15/// This enum categorizes errors into distinct types to enable better error handling,
16/// logging, and recovery strategies. Each variant includes a descriptive message.
17#[derive(Debug, Error)]
18pub enum StreamKitError {
19 /// Configuration or parameter validation error.
20 ///
21 /// Examples:
22 /// - Invalid node parameters (negative gain, invalid sample rate)
23 /// - Missing required configuration fields
24 /// - Invalid pipeline structure (circular dependencies)
25 #[error("Configuration error: {0}")]
26 Configuration(String),
27
28 /// Runtime processing error during normal operation.
29 ///
30 /// Examples:
31 /// - Audio buffer processing failure
32 /// - Codec encoding/decoding error
33 /// - Data format conversion failure
34 #[error("Runtime error: {0}")]
35 Runtime(String),
36
37 /// Network-related error (sockets, HTTP, WebSocket, etc.).
38 ///
39 /// Examples:
40 /// - Connection timeout
41 /// - Socket closed unexpectedly
42 /// - HTTP request failed
43 #[error("Network error: {0}")]
44 Network(String),
45
46 /// Codec-specific error (encoding, decoding, format negotiation).
47 ///
48 /// Examples:
49 /// - Opus encoder initialization failed
50 /// - Invalid audio format for codec
51 /// - Unsupported codec feature
52 #[error("Codec error: {0}")]
53 Codec(String),
54
55 /// Plugin loading, initialization, or execution error.
56 ///
57 /// Examples:
58 /// - Plugin file not found
59 /// - ABI version mismatch
60 /// - Plugin initialization failed
61 /// - Plugin processing error
62 #[error("Plugin error: {0}")]
63 Plugin(String),
64
65 /// I/O error (file operations, device access).
66 ///
67 /// Examples:
68 /// - File not found
69 /// - Permission denied
70 /// - Disk full
71 #[error("I/O error: {0}")]
72 Io(#[from] std::io::Error),
73
74 /// Resource exhaustion or limit exceeded.
75 ///
76 /// Examples:
77 /// - Memory allocation failed
78 /// - Too many open files
79 /// - Queue capacity exceeded
80 #[error("Resource exhaustion: {0}")]
81 ResourceExhausted(String),
82}
83
84/// Convenience type alias for Results using `StreamKitError`.
85pub type Result<T> = std::result::Result<T, StreamKitError>;
86
87// Backward compatibility: Allow conversion from StreamKitError to String
88impl From<StreamKitError> for String {
89 fn from(err: StreamKitError) -> Self {
90 err.to_string()
91 }
92}
93
94// Backward compatibility: Allow conversion from String to StreamKitError
95// This defaults to Runtime error for generic string errors
96impl From<String> for StreamKitError {
97 fn from(s: String) -> Self {
98 Self::Runtime(s)
99 }
100}
101
102// Backward compatibility: Allow conversion from &str to StreamKitError
103impl From<&str> for StreamKitError {
104 fn from(s: &str) -> Self {
105 Self::Runtime(s.to_string())
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_error_display() {
115 let err = StreamKitError::Configuration("Invalid sample rate".to_string());
116 assert_eq!(err.to_string(), "Configuration error: Invalid sample rate");
117
118 let err = StreamKitError::Network("Connection timeout".to_string());
119 assert_eq!(err.to_string(), "Network error: Connection timeout");
120 }
121
122 #[test]
123 fn test_error_to_string_conversion() {
124 let err = StreamKitError::Runtime("Processing failed".to_string());
125 let s: String = err.into();
126 assert_eq!(s, "Runtime error: Processing failed");
127 }
128
129 #[test]
130 fn test_string_to_error_conversion() {
131 let err: StreamKitError = "Something went wrong".into();
132 assert_eq!(err.to_string(), "Runtime error: Something went wrong");
133 }
134
135 #[test]
136 fn test_io_error_conversion() {
137 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
138 let err: StreamKitError = io_err.into();
139 assert!(err.to_string().contains("I/O error"));
140 assert!(err.to_string().contains("File not found"));
141 }
142}