1use serde::{Deserialize, Serialize};
9
10#[non_exhaustive]
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15pub enum AudioError {
16 DeviceNotFound(String),
18 DeviceInUse(String),
20 UnsupportedFormat {
22 requested: String,
24 supported: Vec<String>,
26 },
27 UnsupportedSampleRate {
29 requested: u32,
31 supported: Vec<u32>,
33 },
34 BufferOverflow {
36 samples_lost: usize,
38 },
39 BufferUnderrun {
41 silence_inserted: usize,
43 },
44 InvalidState {
46 current: String,
48 required: String,
50 },
51 VolumeOutOfRange(String),
53 CodecError(String),
55 PlatformError(String),
57}
58
59impl std::fmt::Display for AudioError {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 match self {
62 Self::DeviceNotFound(id) => write!(f, "audio device not found: {id}"),
63 Self::DeviceInUse(id) => write!(f, "audio device in use: {id}"),
64 Self::UnsupportedFormat {
65 requested,
66 supported,
67 } => {
68 write!(
69 f,
70 "unsupported format {requested}, supported: {supported:?}"
71 )
72 }
73 Self::UnsupportedSampleRate {
74 requested,
75 supported,
76 } => {
77 write!(
78 f,
79 "unsupported sample rate {requested}Hz, supported: {supported:?}"
80 )
81 }
82 Self::BufferOverflow { samples_lost } => {
83 write!(f, "buffer overflow: {samples_lost} samples lost")
84 }
85 Self::BufferUnderrun { silence_inserted } => {
86 write!(f, "buffer underrun: {silence_inserted} samples of silence")
87 }
88 Self::InvalidState { current, required } => {
89 write!(f, "invalid state: {current}, required: {required}")
90 }
91 Self::VolumeOutOfRange(v) => write!(f, "volume out of range: {v}"),
92 Self::CodecError(msg) => write!(f, "codec error: {msg}"),
93 Self::PlatformError(msg) => write!(f, "platform error: {msg}"),
94 }
95 }
96}
97
98impl std::error::Error for AudioError {}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn device_not_found_display() {
106 let e = AudioError::DeviceNotFound("hw:0".into());
107 assert!(e.to_string().contains("hw:0"));
108 }
109
110 #[test]
111 fn buffer_overflow_display() {
112 let e = AudioError::BufferOverflow { samples_lost: 42 };
113 assert!(e.to_string().contains("42"));
114 }
115
116 #[test]
117 fn unsupported_format_display() {
118 let e = AudioError::UnsupportedFormat {
119 requested: "F64".into(),
120 supported: vec!["S16".into(), "F32".into()],
121 };
122 let s = e.to_string();
123 assert!(s.contains("F64"));
124 assert!(s.contains("S16"));
125 }
126
127 #[test]
128 fn all_variants_display() {
129 let variants: Vec<AudioError> = vec![
130 AudioError::DeviceNotFound("x".into()),
131 AudioError::DeviceInUse("x".into()),
132 AudioError::UnsupportedFormat {
133 requested: "x".into(),
134 supported: vec![],
135 },
136 AudioError::UnsupportedSampleRate {
137 requested: 96000,
138 supported: vec![44100, 48000],
139 },
140 AudioError::BufferOverflow { samples_lost: 0 },
141 AudioError::BufferUnderrun {
142 silence_inserted: 0,
143 },
144 AudioError::InvalidState {
145 current: "a".into(),
146 required: "b".into(),
147 },
148 AudioError::VolumeOutOfRange("1.5".into()),
149 AudioError::CodecError("bad".into()),
150 AudioError::PlatformError("driver".into()),
151 ];
152 for v in &variants {
153 assert!(!v.to_string().is_empty());
154 }
155 assert_eq!(variants.len(), 10);
156 }
157
158 #[test]
159 fn error_trait_impl() {
160 let e = AudioError::CodecError("test".into());
161 let _: &dyn std::error::Error = &e;
162 }
163
164 #[test]
165 fn clone_and_eq() {
166 let a = AudioError::DeviceNotFound("hw:0".into());
167 let b = a.clone();
168 assert_eq!(a, b);
169 }
170
171 #[test]
172 fn debug_format() {
173 let e = AudioError::BufferUnderrun {
174 silence_inserted: 10,
175 };
176 let debug = format!("{e:?}");
177 assert!(debug.contains("BufferUnderrun"));
178 }
179}