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}