1use thiserror::Error;
2
3#[derive(Debug, Error, PartialEq, Eq)]
4pub enum FormatError {
5 #[error("not a FLAC stream (missing fLaC marker)")]
6 NotFlac,
7 #[error("not an MP3 stream (no MPEG frame sync at the audio offset)")]
8 NotMp3,
9 #[error("truncated or malformed metadata")]
10 Malformed,
11 #[error("synthesized metadata exceeds the format's size limit")]
12 TooLarge,
13 #[error("not a supported MP4/M4A file")]
14 NotMp4,
15 #[error("not a supported WAV/RIFF file")]
16 NotWav,
17 #[error("synthesized region layout violates producer invariants: {0}")]
18 InvalidLayout(#[from] crate::layout::LayoutError),
19 #[error("producer invariant violated: {0}")]
20 ProducerBug(&'static str),
21 #[error("failed to read art {art_id} bytes for synthesis")]
22 ArtRead { art_id: i64 },
23 #[error("DB-sourced {field} contains an embedded NUL byte (crafted or corrupt DB)")]
24 EmbeddedNul { field: &'static str },
25}
26
27pub type Result<T> = std::result::Result<T, FormatError>;
28
29#[cfg(test)]
30mod tests {
31 use super::FormatError;
32 use crate::layout::LayoutError;
33
34 #[test]
35 fn invalid_layout_carries_inner_layout_error() {
36 let e: FormatError = LayoutError::EmptySegment.into();
37 assert!(matches!(
38 e,
39 FormatError::InvalidLayout(LayoutError::EmptySegment)
40 ));
41 assert!(e.to_string().contains("zero length"));
43 }
44
45 #[test]
46 fn producer_bug_carries_reason() {
47 let e = FormatError::ProducerBug("no leading Inline");
48 assert!(e.to_string().contains("no leading Inline"));
49 }
50}