rustwav_lib/
errors.rs

1#![allow(dead_code)]
2
3use std::{io::{self, ErrorKind}, fmt::{Formatter, Display}, error};
4
5#[derive(Debug, Clone)]
6pub struct IOErrorInfo {
7    pub kind: ErrorKind,
8    pub message: String,
9}
10
11impl IOErrorInfo {
12    pub fn new(kind: ErrorKind, message: String) -> Self {
13        Self {
14            kind,
15            message,
16        }
17    }
18}
19
20#[derive(Debug, Clone)]
21pub enum AudioReadError {
22    IncompleteFile(u64),
23    IncompleteData(String),
24    BufferTooSmall(String),
25    InvalidArguments(String),
26    IOError(IOErrorInfo),
27    MissingData(String),
28    FormatError(String),
29    DataCorrupted(String),
30    Unimplemented(String),
31    Unsupported(String),
32    UnexpectedFlag(String, String),
33    StringDecodeError(Vec<u8>),
34    OtherReason(String),
35}
36
37impl error::Error for AudioReadError {}
38
39impl Display for AudioReadError {
40    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
41        match self {
42            Self::IncompleteFile(offset) => write!(f, "The file is incomplete, the content from 0x{:x} is empty", offset),
43            Self::IncompleteData(info) => write!(f, "Incomplete data: {info}"),
44            Self::BufferTooSmall(info) => write!(f, "The buffer is too small: {info}"),
45            Self::InvalidArguments(info) => write!(f, "Invalid arguments: {info}"),
46            Self::IOError(ioerror) => write!(f, "IO error: {:?}", ioerror),
47            Self::MissingData(data) => write!(f, "Missing data: \"{data}\""),
48            Self::FormatError(info) => write!(f, "Invalid format: {info}"),
49            Self::DataCorrupted(info) => write!(f, "Data corrupted: {info}"),
50            Self::Unimplemented(info) => write!(f, "Unimplemented for the file format: {info}"),
51            Self::Unsupported(feature) => write!(f, "Unsupported feature: {feature}"),
52            Self::UnexpectedFlag(expected, got) => write!(f, "Expect \"{expected}\", got \"{got}\"."),
53            Self::StringDecodeError(bytes) => write!(f, "String decode error: {}", String::from_utf8_lossy(bytes)),
54            Self::OtherReason(info) => write!(f, "Unknown error: {info}"),
55        }
56    }
57}
58
59impl From<io::Error> for AudioReadError {
60    fn from(ioerr: io::Error) -> Self {
61        AudioReadError::IOError(IOErrorInfo{kind: ioerr.kind(), message: ioerr.to_string()})
62    }
63}
64
65impl From<crate::adpcm::ima::ImaAdpcmError> for AudioReadError {
66    fn from(imaerr: crate::adpcm::ima::ImaAdpcmError) -> Self {
67        match imaerr{
68            crate::adpcm::ima::ImaAdpcmError::InvalidArgument(info) => Self::InvalidArguments(info),
69        }
70    }
71}
72
73impl From<AudioReadError> for io::Error {
74    fn from(err: AudioReadError) -> Self {
75        match err {
76            AudioReadError::IOError(ioerr) => {
77                io::Error::from(ioerr.kind)
78            },
79            other => panic!("When converting `AudioReadError` to `io::Error`, the given error is unrelated: {:?}", other),
80        }
81    }
82}
83
84#[derive(Debug, Clone)]
85pub enum AudioWriteError {
86    InvalidArguments(String),
87    InvalidInput(String),
88    IOError(IOErrorInfo),
89    Unsupported(String),
90    Unimplemented(String),
91    AlreadyFinished(String),
92    NotPreparedFor4GBFile,
93    ChunkSizeTooBig(String),
94    StringDecodeError(Vec<u8>),
95    BufferIsFull(String),
96    MultipleMonosAreNotSameSize,
97    FrameChannelsNotSame,
98    WrongChannels(String),
99    NotStereo,
100    MissingData(String),
101    OtherReason(String),
102}
103
104impl error::Error for AudioWriteError {}
105
106impl Display for AudioWriteError {
107    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
108        match self {
109            Self::InvalidArguments(info) => write!(f, "Invalid arguments: {info}"),
110            Self::InvalidInput(info) => write!(f, "Invalid input: {info}"),
111            Self::IOError(errkind) => write!(f, "IO error: {:?}", errkind),
112            Self::Unsupported(info) => write!(f, "Unsupported format: {info}"),
113            Self::Unimplemented(info) => write!(f, "Unimplemented format: {info}"),
114            Self::AlreadyFinished(info) => write!(f, "Already finished writing {info}"),
115            Self::NotPreparedFor4GBFile => write!(f, "The WAV file wasn't prepared for being larger than 4GB, please check `file_size_option` when creating the `WaveWriter`."),
116            Self::ChunkSizeTooBig(info) => write!(f, "Chunk size is too big: {info}"),
117            Self::StringDecodeError(bytes) => write!(f, "String decode error: {}", String::from_utf8_lossy(bytes)),
118            Self::BufferIsFull(info) => write!(f, "The buffer is full: {info}"),
119            Self::MultipleMonosAreNotSameSize => write!(f, "The lengths of the channels are not equal."),
120            Self::FrameChannelsNotSame => write!(f, "The channels of each frames are not equal."),
121            Self::WrongChannels(prompt) => write!(f, "Wrong channels: {prompt}"),
122            Self::NotStereo => write!(f, "The samples are not stereo audio samples"),
123            Self::MissingData(data) => write!(f, "Missing data: \"{data}\""),
124            Self::OtherReason(info) => write!(f, "Unknown error: {info}"),
125       }
126    }
127}
128
129impl From<io::Error> for AudioWriteError {
130    fn from(ioerr: io::Error) -> Self {
131        AudioWriteError::IOError(IOErrorInfo{kind: ioerr.kind(), message: ioerr.to_string()})
132    }
133}
134
135impl From<AudioWriteError> for io::Error {
136    fn from(err: AudioWriteError) -> Self {
137        match err {
138            AudioWriteError::IOError(ioerr) => {
139                io::Error::from(ioerr.kind)
140            },
141            other => panic!("When converting `AudioWriteError` to `io::Error`, the given error is unrelated: {:?}", other),
142        }
143    }
144}
145
146#[derive(Debug, Clone)]
147pub enum AudioError {
148    GuessChannelMaskFailed(u16),
149    ChannelNotMatchMask,
150    Unparseable(String),
151    NoSuchData(String),
152    Unimplemented(String),
153    InvalidArguments(String),
154}
155
156impl error::Error for AudioError {}
157
158impl Display for AudioError {
159    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
160       match self {
161           Self::GuessChannelMaskFailed(channels) => write!(f, "Can't guess channel mask for channels = {channels}"),
162           Self::ChannelNotMatchMask => write!(f, "The number of the channels doesn't match the channel mask."),
163           Self::Unparseable(data) => write!(f, "Could not parse {data}"),
164           Self::NoSuchData(data) => write!(f, "Could not find data \"{data}\""),
165           Self::Unimplemented(info) => write!(f, "Unimplemented behavior: {info}"),
166           Self::InvalidArguments(info) => write!(f, "Invalid arguments: {info}"),
167       }
168    }
169}
170
171impl From<AudioError> for AudioReadError {
172    fn from(err: AudioError) -> Self {
173        match err {
174            AudioError::GuessChannelMaskFailed(channels) => Self::InvalidArguments(format!("can't guess channel mask by channel number {channels}")),
175            AudioError::ChannelNotMatchMask => Self::DataCorrupted("the channel number does not match the channel mask".to_owned()),
176            AudioError::Unparseable(data) => Self::DataCorrupted(format!("The data \"{data}\" is not parseable")),
177            AudioError::NoSuchData(data) => Self::MissingData(format!("Missing data: \"{data}\"")),
178            AudioError::Unimplemented(info) => Self::Unimplemented(info),
179            AudioError::InvalidArguments(info) => Self::InvalidArguments(info),
180        }
181    }
182}
183
184impl From<AudioError> for AudioWriteError {
185    fn from(err: AudioError) -> Self {
186        match err {
187            AudioError::GuessChannelMaskFailed(channels) => Self::InvalidArguments(format!("can't guess channel mask by channel number {channels}")),
188            AudioError::ChannelNotMatchMask => Self::InvalidArguments("the channel number does not match the channel mask".to_owned()),
189            AudioError::Unparseable(data) => Self::InvalidInput(format!("The input data is unparseable: \"{data}\"")),
190            AudioError::NoSuchData(data) => Self::MissingData(format!("Missing data: \"{data}\"")),
191            AudioError::Unimplemented(info) => Self::Unimplemented(info),
192            AudioError::InvalidArguments(info) => Self::InvalidArguments(info),
193        }
194    }
195}
196
197#[cfg(feature = "mp3enc")]
198impl From<mp3lame_encoder::BuildError> for AudioWriteError {
199    fn from(err: mp3lame_encoder::BuildError) -> Self {
200        match err {
201            mp3lame_encoder::BuildError::Generic => Self::OtherReason("Generic error".to_owned()),
202            mp3lame_encoder::BuildError::NoMem => Self::OtherReason("No enough memory".to_owned()),
203            mp3lame_encoder::BuildError::BadBRate => Self::InvalidInput("Bad bit rate".to_owned()),
204            mp3lame_encoder::BuildError::BadSampleFreq => Self::InvalidInput("Bad sample rate".to_owned()),
205            mp3lame_encoder::BuildError::InternalError => Self::OtherReason("Internal error".to_owned()),
206            mp3lame_encoder::BuildError::Other(c_int) => Self::OtherReason(format!("Other lame error code: {c_int}")),
207        }
208    }
209}
210
211#[cfg(feature = "mp3enc")]
212impl From<mp3lame_encoder::Id3TagError> for AudioWriteError {
213    fn from(err: mp3lame_encoder::Id3TagError) -> Self {
214        match err {
215            mp3lame_encoder::Id3TagError::AlbumArtOverflow => Self::BufferIsFull("Specified Id3 tag buffer exceed limit of 128kb".to_owned()),
216        }
217    }
218}
219
220#[cfg(feature = "mp3enc")]
221impl From<mp3lame_encoder::EncodeError> for AudioWriteError {
222    fn from(err: mp3lame_encoder::EncodeError) -> Self {
223        match err {
224            mp3lame_encoder::EncodeError::BufferTooSmall => Self::BufferIsFull("Buffer is too small".to_owned()),
225            mp3lame_encoder::EncodeError::NoMem => Self::OtherReason("No enough memory".to_owned()),
226            mp3lame_encoder::EncodeError::InvalidState => Self::OtherReason("Invalid state".to_owned()),
227            mp3lame_encoder::EncodeError::PsychoAcoustic => Self::OtherReason("Psycho acoustic problems".to_owned()),
228            mp3lame_encoder::EncodeError::Other(c_int) => Self::OtherReason(format!("Other lame error code: {c_int}")),
229        }
230    }
231}
232
233#[cfg(feature = "opus")]
234impl From<opus::Error> for AudioReadError {
235    fn from(err: opus::Error) -> Self {
236        match err.code() {
237            opus::ErrorCode::BadArg => Self::InvalidArguments(format!("On calling `{}`: {}", err.function(), err.description())),
238            opus::ErrorCode::BufferTooSmall => Self::BufferTooSmall(format!("On calling `{}`: {}", err.function(), err.description())),
239            opus::ErrorCode::InternalError => Self::OtherReason(format!("On calling `{}`: {}", err.function(), err.description())),
240            opus::ErrorCode::InvalidPacket => Self::DataCorrupted(format!("On calling `{}`: {}", err.function(), err.description())),
241            opus::ErrorCode::Unimplemented => Self::Unimplemented(format!("On calling `{}`: {}", err.function(), err.description())),
242            opus::ErrorCode::InvalidState => Self::OtherReason(format!("On calling `{}`: {}", err.function(), err.description())),
243            opus::ErrorCode::AllocFail => Self::OtherReason(format!("On calling `{}`: {}", err.function(), err.description())),
244            opus::ErrorCode::Unknown => Self::OtherReason(format!("On calling `{}`: {}", err.function(), err.description())),
245        }
246    }
247}
248
249#[cfg(feature = "opus")]
250impl From<opus::Error> for AudioWriteError {
251    fn from(err: opus::Error) -> Self {
252        match err.code() {
253            opus::ErrorCode::BadArg => Self::InvalidArguments(format!("On calling `{}`: {}", err.function(), err.description())),
254            opus::ErrorCode::BufferTooSmall => Self::BufferIsFull(format!("On calling `{}`: {}", err.function(), err.description())),
255            opus::ErrorCode::InternalError => Self::OtherReason(format!("On calling `{}`: {}", err.function(), err.description())),
256            opus::ErrorCode::InvalidPacket => Self::OtherReason(format!("On calling `{}`: {}", err.function(), err.description())),
257            opus::ErrorCode::Unimplemented => Self::Unimplemented(format!("On calling `{}`: {}", err.function(), err.description())),
258            opus::ErrorCode::InvalidState => Self::OtherReason(format!("On calling `{}`: {}", err.function(), err.description())),
259            opus::ErrorCode::AllocFail => Self::OtherReason(format!("On calling `{}`: {}", err.function(), err.description())),
260            opus::ErrorCode::Unknown => Self::OtherReason(format!("On calling `{}`: {}", err.function(), err.description())),
261        }
262    }
263}
264
265#[cfg(feature = "flac")]
266use crate::flac;
267
268#[cfg(feature = "flac")]
269impl From<flac::FlacEncoderError> for AudioReadError {
270    fn from(err: flac::FlacEncoderError) -> Self {
271        let err_code = err.code;
272        let err_func = err.function;
273        let err_desc = err.message;
274        use flac::FlacEncoderErrorCode::*;
275        let err_code = flac::FlacEncoderErrorCode::from(err_code);
276        let err_string = format!("On function `{err_func}`: {err_desc}: {err_code}");
277        match err_code {
278            StreamEncoderOk => Self::OtherReason(err_string),
279            StreamEncoderUninitialized => Self::OtherReason(err_string),
280            StreamEncoderOggError => Self::OtherReason(err_string),
281            StreamEncoderVerifyDecoderError => Self::OtherReason(err_string),
282            StreamEncoderVerifyMismatchInAudioData => Self::OtherReason(err_string),
283            StreamEncoderClientError => Self::OtherReason(err_string),
284            StreamEncoderIOError => Self::IOError(IOErrorInfo::new(ErrorKind::Other, err_string)),
285            StreamEncoderFramingError => Self::FormatError(err_string),
286            StreamEncoderMemoryAllocationError => Self::OtherReason(err_string),
287        }
288    }
289}
290
291#[cfg(feature = "flac")]
292impl From<flac::FlacEncoderInitError> for AudioReadError {
293    fn from(err: flac::FlacEncoderInitError) -> Self {
294        let err_code = err.code;
295        let err_func = err.function;
296        let err_desc = err.message;
297        use flac::FlacEncoderInitErrorCode::*;
298        let err_code = flac::FlacEncoderInitErrorCode::from(err_code);
299        let err_string = format!("On function `{err_func}`: {err_desc}: {err_code}");
300        match err_code {
301            StreamEncoderInitStatusOk => Self::OtherReason(err_string),
302            StreamEncoderInitStatusEncoderError => Self::OtherReason(err_string),
303            StreamEncoderInitStatusUnsupportedContainer => Self::OtherReason(err_string),
304            StreamEncoderInitStatusInvalidCallbacks => Self::InvalidArguments(err_string),
305            StreamEncoderInitStatusInvalidNumberOfChannels => Self::InvalidArguments(err_string),
306            StreamEncoderInitStatusInvalidBitsPerSample => Self::InvalidArguments(err_string),
307            StreamEncoderInitStatusInvalidSampleRate => Self::InvalidArguments(err_string),
308            StreamEncoderInitStatusInvalidBlockSize => Self::InvalidArguments(err_string),
309            StreamEncoderInitStatusInvalidMaxLpcOrder => Self::InvalidArguments(err_string),
310            StreamEncoderInitStatusInvalidQlpCoeffPrecision => Self::InvalidArguments(err_string),
311            StreamEncoderInitStatusBlockSizeTooSmallForLpcOrder => Self::BufferTooSmall(err_string),
312            StreamEncoderInitStatusNotStreamable => Self::OtherReason(err_string),
313            StreamEncoderInitStatusInvalidMetadata => Self::FormatError(err_string),
314            StreamEncoderInitStatusAlreadyInitialized => Self::InvalidArguments(err_string),
315        }
316    }
317}
318
319#[cfg(feature = "flac")]
320impl From<flac::FlacDecoderError> for AudioReadError {
321    fn from(err: flac::FlacDecoderError) -> Self {
322        let err_code = err.code;
323        let err_func = err.function;
324        let err_desc = err.message;
325        use flac::FlacDecoderInitErrorCode::*;
326        let err_code = flac::FlacDecoderInitErrorCode::from(err_code);
327        let err_string = format!("On function `{err_func}`: {err_desc}: {err_code}");
328        match err_code {
329            StreamDecoderInitStatusOk => Self::OtherReason(err_string),
330            StreamDecoderInitStatusUnsupportedContainer => Self::Unsupported(err_string),
331            StreamDecoderInitStatusInvalidCallbacks => Self::InvalidArguments(err_string),
332            StreamDecoderInitStatusMemoryAllocationError => Self::OtherReason(err_string),
333            StreamDecoderInitStatusErrorOpeningFile => Self::IOError(IOErrorInfo::new(ErrorKind::Other, err_string)),
334            StreamDecoderInitStatusAlreadyInitialized => Self::InvalidArguments(err_string),
335        }
336    }
337}
338
339
340#[cfg(feature = "flac")]
341impl From<flac::FlacDecoderInitError> for AudioReadError {
342    fn from(err: flac::FlacDecoderInitError) -> Self {
343        let err_code = err.code;
344        let err_func = err.function;
345        let err_desc = err.message;
346        use flac::FlacDecoderErrorCode::*;
347        let err_code = flac::FlacDecoderErrorCode::from(err_code);
348        let err_string = format!("On function `{err_func}`: {err_desc}: {err_code}");
349        match err_code {
350            StreamDecoderSearchForMetadata => Self::OtherReason(err_string),
351            StreamDecoderReadMetadata => Self::OtherReason(err_string),
352            StreamDecoderSearchForFrameSync => Self::OtherReason(err_string),
353            StreamDecoderReadFrame => Self::OtherReason(err_string),
354            StreamDecoderEndOfStream => Self::OtherReason(err_string),
355            StreamDecoderOggError => Self::OtherReason(err_string),
356            StreamDecoderSeekError => Self::OtherReason(err_string),
357            StreamDecoderAborted => Self::OtherReason(err_string),
358            StreamDecoderMemoryAllocationError => Self::OtherReason(err_string),
359            StreamDecoderUninitialized => Self::InvalidArguments(err_string),
360        }
361    }
362}
363
364#[cfg(feature = "flac")]
365impl From<&dyn flac::FlacError> for AudioReadError {
366    fn from(err: &dyn flac::FlacError) -> Self {
367        let err_code = err.get_code();
368        let err_func = err.get_function();
369        let err_desc = err.get_message();
370        if let Some(encoder_err) = err.as_any().downcast_ref::<flac::FlacEncoderError>() {
371            AudioReadError::from(*encoder_err)
372        } else  if let Some(encoder_err) = err.as_any().downcast_ref::<flac::FlacEncoderInitError>() {
373            AudioReadError::from(*encoder_err)
374        } else if let Some(decoder_err) = err.as_any().downcast_ref::<flac::FlacDecoderError>() {
375            AudioReadError::from(*decoder_err)
376        } else if let Some(decoder_err) = err.as_any().downcast_ref::<flac::FlacDecoderInitError>() {
377            AudioReadError::from(*decoder_err)
378        } else {
379            Self::OtherReason(format!("Unknown error type from `flac::FlacError`: `{err_func}`: {err_code}: {err_desc}"))
380        }
381    }
382}
383
384#[cfg(feature = "flac")]
385impl From<flac::FlacEncoderError> for AudioWriteError {
386    fn from(err: flac::FlacEncoderError) -> Self {
387        let err_code = err.code;
388        let err_func = err.function;
389        let err_desc = err.message;
390        use flac::FlacEncoderErrorCode::*;
391        let err_code = flac::FlacEncoderErrorCode::from(err_code);
392        let err_string = format!("On function `{err_func}`: {err_desc}: {err_code}");
393        match err_code {
394            StreamEncoderOk => Self::OtherReason(err_string),
395            StreamEncoderUninitialized => Self::OtherReason(err_string),
396            StreamEncoderOggError => Self::OtherReason(err_string),
397            StreamEncoderVerifyDecoderError => Self::OtherReason(err_string),
398            StreamEncoderVerifyMismatchInAudioData => Self::OtherReason(err_string),
399            StreamEncoderClientError => Self::OtherReason(err_string),
400            StreamEncoderIOError => Self::IOError(IOErrorInfo::new(ErrorKind::Other, err_string)),
401            StreamEncoderFramingError => Self::InvalidInput(err_string),
402            StreamEncoderMemoryAllocationError => Self::OtherReason(err_string),
403        }
404    }
405}
406
407#[cfg(feature = "flac")]
408impl From<flac::FlacEncoderInitError> for AudioWriteError {
409    fn from(err: flac::FlacEncoderInitError) -> Self {
410        let err_code = err.code;
411        let err_func = err.function;
412        let err_desc = err.message;
413        use flac::FlacEncoderInitErrorCode::*;
414        let err_code = flac::FlacEncoderInitErrorCode::from(err_code);
415        let err_string = format!("On function `{err_func}`: {err_desc}: {err_code}");
416        match err_code {
417            StreamEncoderInitStatusOk => Self::OtherReason(err_string),
418            StreamEncoderInitStatusEncoderError => Self::OtherReason(err_string),
419            StreamEncoderInitStatusUnsupportedContainer => Self::OtherReason(err_string),
420            StreamEncoderInitStatusInvalidCallbacks => Self::InvalidArguments(err_string),
421            StreamEncoderInitStatusInvalidNumberOfChannels => Self::InvalidArguments(err_string),
422            StreamEncoderInitStatusInvalidBitsPerSample => Self::InvalidArguments(err_string),
423            StreamEncoderInitStatusInvalidSampleRate => Self::InvalidArguments(err_string),
424            StreamEncoderInitStatusInvalidBlockSize => Self::InvalidArguments(err_string),
425            StreamEncoderInitStatusInvalidMaxLpcOrder => Self::InvalidArguments(err_string),
426            StreamEncoderInitStatusInvalidQlpCoeffPrecision => Self::InvalidArguments(err_string),
427            StreamEncoderInitStatusBlockSizeTooSmallForLpcOrder => Self::BufferIsFull(err_string),
428            StreamEncoderInitStatusNotStreamable => Self::OtherReason(err_string),
429            StreamEncoderInitStatusInvalidMetadata => Self::InvalidInput(err_string),
430            StreamEncoderInitStatusAlreadyInitialized => Self::InvalidArguments(err_string),
431        }
432    }
433}
434
435#[cfg(feature = "flac")]
436impl From<flac::FlacDecoderError> for AudioWriteError {
437    fn from(err: flac::FlacDecoderError) -> Self {
438        let err_code = err.code;
439        let err_func = err.function;
440        let err_desc = err.message;
441        use flac::FlacDecoderErrorCode::*;
442        let err_code = flac::FlacDecoderErrorCode::from(err_code);
443        let err_string = format!("On function `{err_func}`: {err_desc}: {err_code}");
444        match err_code {
445            StreamDecoderSearchForMetadata => Self::OtherReason(err_string),
446            StreamDecoderReadMetadata => Self::OtherReason(err_string),
447            StreamDecoderSearchForFrameSync => Self::OtherReason(err_string),
448            StreamDecoderReadFrame => Self::OtherReason(err_string),
449            StreamDecoderEndOfStream => Self::OtherReason(err_string),
450            StreamDecoderOggError => Self::OtherReason(err_string),
451            StreamDecoderSeekError => Self::OtherReason(err_string),
452            StreamDecoderAborted => Self::OtherReason(err_string),
453            StreamDecoderMemoryAllocationError => Self::OtherReason(err_string),
454            StreamDecoderUninitialized => Self::InvalidArguments(err_string),
455        }
456    }
457}
458
459#[cfg(feature = "flac")]
460impl From<flac::FlacDecoderInitError> for AudioWriteError {
461    fn from(err: flac::FlacDecoderInitError) -> Self {
462        let err_code = err.code;
463        let err_func = err.function;
464        let err_desc = err.message;
465        use flac::FlacDecoderInitErrorCode::*;
466        let err_code = flac::FlacDecoderInitErrorCode::from(err_code);
467        let err_string = format!("On function `{err_func}`: {err_desc}: {err_code}");
468        match err_code {
469            StreamDecoderInitStatusOk => Self::OtherReason(err_string),
470            StreamDecoderInitStatusUnsupportedContainer => Self::Unsupported(err_string),
471            StreamDecoderInitStatusInvalidCallbacks => Self::InvalidArguments(err_string),
472            StreamDecoderInitStatusMemoryAllocationError => Self::OtherReason(err_string),
473            StreamDecoderInitStatusErrorOpeningFile => Self::IOError(IOErrorInfo::new(ErrorKind::Other, err_string)),
474            StreamDecoderInitStatusAlreadyInitialized => Self::InvalidArguments(err_string),
475        }
476    }
477}
478
479#[cfg(feature = "flac")]
480impl From<&dyn flac::FlacError> for AudioWriteError {
481    fn from(err: &dyn flac::FlacError) -> Self {
482        let err_code = err.get_code();
483        let err_func = err.get_function();
484        let err_desc = err.get_message();
485        if let Some(encoder_err) = err.as_any().downcast_ref::<flac::FlacEncoderError>() {
486            AudioWriteError::from(*encoder_err)
487        } else if let Some(encoder_err) = err.as_any().downcast_ref::<flac::FlacEncoderInitError>() {
488            AudioWriteError::from(*encoder_err)
489        } else if let Some(decoder_err) = err.as_any().downcast_ref::<flac::FlacDecoderError>() {
490            AudioWriteError::from(*decoder_err)
491        } else if let Some(decoder_err) = err.as_any().downcast_ref::<flac::FlacDecoderInitError>() {
492            AudioWriteError::from(*decoder_err)
493        } else {
494            Self::OtherReason(format!("Unknown error type from `flac::FlacError`: `{err_func}`: {err_code}: {err_desc}"))
495        }
496    }
497}