Skip to main content

sonos_stream/
error.rs

1//! Error types for the sonos-stream crate
2//!
3//! This module defines all error types used throughout the crate, providing
4//! clear error messages and proper error chaining.
5
6use std::net::IpAddr;
7
8/// Main error type for the EventBroker
9#[derive(Debug, thiserror::Error)]
10pub enum BrokerError {
11    #[error("Registry error: {0}")]
12    Registry(#[from] RegistryError),
13
14    #[error("Subscription error: {0}")]
15    Subscription(#[from] SubscriptionError),
16
17    #[error("Polling error: {0}")]
18    Polling(#[from] PollingError),
19
20    #[error("Event processing error: {0}")]
21    EventProcessing(String),
22
23    #[error("Callback server error: {0}")]
24    CallbackServer(String),
25
26    #[error("Configuration error: {0}")]
27    Configuration(String),
28
29    #[error("Firewall detection error: {0}")]
30    FirewallDetection(String),
31
32    #[error("IO error: {0}")]
33    Io(#[from] std::io::Error),
34
35    #[error("Serialization error: {0}")]
36    Serialization(#[from] serde_json::Error),
37}
38
39/// Errors related to speaker/service registry operations
40#[derive(Debug, thiserror::Error)]
41pub enum RegistryError {
42    #[error("Speaker/service pair already registered: {speaker_ip} {service:?}")]
43    DuplicateRegistration {
44        speaker_ip: IpAddr,
45        service: sonos_api::Service,
46    },
47
48    #[error("Registration not found: {0}")]
49    NotFound(crate::RegistrationId),
50
51    #[error("Invalid speaker IP address: {0}")]
52    InvalidIpAddress(String),
53
54    #[error("Registry is full (max registrations: {max_registrations})")]
55    RegistryFull { max_registrations: usize },
56}
57
58/// Errors related to subscription management
59#[derive(Debug, thiserror::Error)]
60pub enum SubscriptionError {
61    #[error("Subscription expired")]
62    Expired,
63
64    #[error("Subscription failed to create: {0}")]
65    CreationFailed(String),
66
67    #[error("Subscription renewal failed: {0}")]
68    RenewalFailed(String),
69
70    #[error("Network error: {0}")]
71    NetworkError(String),
72
73    #[error("UPnP service error: {0}")]
74    ServiceError(String),
75
76    #[error("Callback registration failed: {0}")]
77    CallbackRegistration(String),
78
79    #[error("Invalid subscription state")]
80    InvalidState,
81}
82
83/// Errors related to polling operations
84#[derive(Debug, thiserror::Error)]
85pub enum PollingError {
86    #[error("Network error during polling: {0}")]
87    Network(String),
88
89    #[error("State parsing error: {0}")]
90    StateParsing(String),
91
92    #[error("Service not supported for polling: {service:?}")]
93    UnsupportedService { service: sonos_api::Service },
94
95    #[error("Device unreachable: {device_ip}")]
96    DeviceUnreachable { device_ip: IpAddr },
97
98    #[error("Polling task spawn failed: {0}")]
99    TaskSpawn(String),
100
101    #[error("Too many consecutive errors: {error_count}")]
102    TooManyErrors { error_count: u32 },
103
104    #[error("SOAP client error: {0}")]
105    SoapClient(String),
106}
107
108/// Errors related to event processing and iteration
109#[derive(Debug, thiserror::Error)]
110pub enum EventProcessingError {
111    #[error("Event parsing failed: {0}")]
112    Parsing(String),
113
114    #[error("Event enrichment failed: {0}")]
115    Enrichment(String),
116
117    #[error("Channel closed")]
118    ChannelClosed,
119
120    #[error("Timeout waiting for event")]
121    Timeout,
122
123    #[error("Iterator already consumed")]
124    IteratorConsumed,
125}
126
127/// Result type alias for BrokerError
128pub type BrokerResult<T> = Result<T, BrokerError>;
129
130/// Result type alias for RegistryError
131pub type RegistryResult<T> = Result<T, RegistryError>;
132
133/// Result type alias for SubscriptionError
134pub type SubscriptionResult<T> = Result<T, SubscriptionError>;
135
136/// Result type alias for PollingError
137pub type PollingResult<T> = Result<T, PollingError>;
138
139/// Result type alias for EventProcessingError
140pub type EventProcessingResult<T> = Result<T, EventProcessingError>;
141
142#[cfg(test)]
143mod tests {
144    use std::error::Error;
145
146    use super::*;
147
148    #[test]
149    fn test_error_display() {
150        let err = BrokerError::Configuration("test error".to_string());
151        assert!(err.to_string().contains("Configuration error"));
152
153        let registry_err = RegistryError::DuplicateRegistration {
154            speaker_ip: "192.168.1.100".parse().unwrap(),
155            service: sonos_api::Service::AVTransport,
156        };
157        assert!(registry_err.to_string().contains("already registered"));
158    }
159
160    #[test]
161    fn test_error_chaining() {
162        let registry_err = RegistryError::NotFound(crate::RegistrationId::new(1));
163        let broker_err = BrokerError::Registry(registry_err);
164
165        assert!(broker_err.to_string().contains("Registry error"));
166        assert!(broker_err.source().is_some());
167    }
168}