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}