Skip to main content

croma_core/
error.rs

1use std::error::Error;
2use std::fmt::{Display, Formatter};
3
4use crate::Diagnostic;
5
6/// Why an ABC conversion failed.
7///
8/// Every failure today is [`CromaError::ParseFailed`], carrying the error
9/// diagnostics; an empty file, a missing `K:` and a tune without music arrive
10/// there with the codes `abc.file.empty`, `abc.file.missing_k` and
11/// `abc.file.no_music`.
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum CromaError {
14    #[deprecated(
15        since = "1.4.0",
16        note = "never constructed; an empty source is ParseFailed with code abc.file.empty"
17    )]
18    EmptyInput,
19    #[deprecated(
20        since = "1.4.0",
21        note = "never constructed; a missing K: is ParseFailed with code abc.file.missing_k"
22    )]
23    MissingKey,
24    #[deprecated(
25        since = "1.4.0",
26        note = "never constructed; a tune without music is ParseFailed with code abc.file.no_music"
27    )]
28    NoMusic,
29    /// The source has errors; the diagnostics say which and where.
30    ParseFailed(Vec<Diagnostic>),
31}
32
33impl Display for CromaError {
34    // The deprecated variants still need a message while they exist.
35    #[allow(deprecated)]
36    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
37        match self {
38            Self::EmptyInput => formatter.write_str("ABC source is empty"),
39            Self::MissingKey => formatter.write_str("ABC source is missing a K: field"),
40            Self::NoMusic => formatter.write_str("ABC source does not contain body music"),
41            Self::ParseFailed(diagnostics) => {
42                if let Some(diagnostic) = diagnostics.first() {
43                    formatter.write_str(&diagnostic.message)
44                } else {
45                    formatter.write_str("ABC parse failed")
46                }
47            }
48        }
49    }
50}
51
52impl Error for CromaError {}
53
54impl CromaError {
55    pub fn diagnostics(&self) -> &[Diagnostic] {
56        match self {
57            Self::ParseFailed(diagnostics) => diagnostics,
58            _ => &[],
59        }
60    }
61
62    pub(crate) fn from_diagnostics(diagnostics: Vec<Diagnostic>) -> Self {
63        Self::ParseFailed(diagnostics)
64    }
65}
66
67pub type Result<T> = std::result::Result<T, CromaError>;