Skip to main content

flac_io/
error.rs

1// The public error type for the crate.
2
3use std::fmt;
4
5/// Errors returned when decoding or encoding a FLAC stream.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum FlacError {
8    /// The input does not begin with the `fLaC` stream marker.
9    NotFlac,
10
11    /// The stream ended in the middle of a field that was still being read.
12    Truncated,
13
14    /// A structural value in the stream is impossible or out of range (an
15    /// unknown subframe type, a reserved code, a partition order that does
16    /// not divide the block, and so on). The string names the specific fault.
17    CorruptStream(String),
18
19    /// The stream uses a feature this crate does not implement (for example a
20    /// reserved sample-rate or bit-depth code, or Ogg encapsulation).
21    Unsupported(String),
22
23    /// A computed CRC did not match the value stored in the stream, so the
24    /// data is damaged.
25    CrcMismatch,
26
27    /// The stream is structurally valid but asks the decoder to produce more
28    /// than a built-in safety limit allows (for example a sample total or a
29    /// run of maximum-size constant subframes that would exhaust memory). The
30    /// string names the limit that was hit.
31    LimitExceeded(String),
32
33    /// The samples handed to the encoder are inconsistent (channel lengths
34    /// differ, bit depth out of range, no channels, and so on). The string
35    /// names the specific fault.
36    InvalidInput(String),
37}
38
39impl fmt::Display for FlacError {
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41        match self {
42            FlacError::NotFlac => write!(f, "input is not a FLAC stream (missing fLaC marker)"),
43            FlacError::Truncated => write!(f, "FLAC stream ended unexpectedly"),
44            FlacError::CorruptStream(why) => write!(f, "corrupt FLAC stream: {why}"),
45            FlacError::Unsupported(what) => write!(f, "unsupported FLAC feature: {what}"),
46            FlacError::CrcMismatch => write!(f, "FLAC CRC check failed; the data is damaged"),
47            FlacError::LimitExceeded(what) => {
48                write!(f, "FLAC stream exceeds a decoder safety limit: {what}")
49            }
50            FlacError::InvalidInput(why) => write!(f, "invalid input to the FLAC encoder: {why}"),
51        }
52    }
53}
54
55impl std::error::Error for FlacError {}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn every_variant_displays_a_message() {
63        let variants = [
64            FlacError::NotFlac,
65            FlacError::Truncated,
66            FlacError::CorruptStream("why".into()),
67            FlacError::Unsupported("what".into()),
68            FlacError::CrcMismatch,
69            FlacError::LimitExceeded("cap".into()),
70            FlacError::InvalidInput("why".into()),
71        ];
72        for v in &variants {
73            let s = v.to_string();
74            assert!(!s.is_empty());
75            // The detail string is carried through for the parameterised ones.
76            let _ = format!("{v:?}");
77        }
78        assert!(FlacError::CorruptStream("partition".into())
79            .to_string()
80            .contains("partition"));
81        // The error implements the standard Error trait.
82        let _: &dyn std::error::Error = &FlacError::NotFlac;
83    }
84}