Skip to main content

musefs_format/
error.rs

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        // Display includes the inner reason, not just a generic string.
42        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}