1use std::{convert::Infallible, error, fmt};
2
3pub type Result<T, E = Error> = std::result::Result<T, E>;
5
6#[derive(Clone, Debug, Eq, PartialEq)]
8#[non_exhaustive]
9pub enum Error {
10 Music21Object(String),
12 Chord(String),
14 Pitch(String),
16 Microtone(String),
18 Accidental(String),
20 ChordTables(String),
22 Interval(String),
24 StepName(String),
26 PitchClass(String),
28 PitchClassString(String),
30 Ordinal(String),
32 Polyrhythm(String),
34 TuningSystem(String),
36 Midi(String),
38 Analysis(String),
40}
41
42impl fmt::Display for Error {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 match self {
45 Error::Music21Object(msg) => write!(f, "Music21Object error: {msg}"),
46 Error::Chord(msg) => write!(f, "Chord error: {msg}"),
47 Error::Pitch(msg) => write!(f, "Pitch error: {msg}"),
48 Error::Microtone(msg) => write!(f, "Microtone error: {msg}"),
49 Error::Accidental(msg) => write!(f, "Accidental error: {msg}"),
50 Error::ChordTables(msg) => write!(f, "ChordTables error: {msg}"),
51 Error::Interval(msg) => write!(f, "Interval error: {msg}"),
52 Error::StepName(msg) => write!(f, "StepName error: {msg}"),
53 Error::PitchClass(msg) => write!(f, "PitchClass error: {msg}"),
54 Error::PitchClassString(msg) => write!(f, "PitchClassString error: {msg}"),
55 Error::Ordinal(msg) => write!(f, "Ordinal error: {msg}"),
56 Error::Polyrhythm(msg) => write!(f, "Polyrhythm error: {msg}"),
57 Error::TuningSystem(msg) => write!(f, "TuningSystem error: {msg}"),
58 Error::Midi(msg) => write!(f, "Midi error: {msg}"),
59 Error::Analysis(msg) => write!(f, "Analysis error: {msg}"),
60 }
61 }
62}
63
64impl error::Error for Error {
65 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
66 None
67 }
68}
69
70impl From<Infallible> for Error {
71 fn from(value: Infallible) -> Self {
72 match value {}
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use std::error::Error as StdError;
80
81 #[test]
82 fn test_display_music21object() {
83 let err = Error::Music21Object("error message".to_string());
84 assert_eq!(format!("{err}"), "Music21Object error: error message");
85 }
86
87 #[test]
88 fn test_display_chord() {
89 let err = Error::Chord("chord error".to_string());
90 assert_eq!(format!("{err}"), "Chord error: chord error");
91 }
92
93 #[test]
94 fn test_display_pitch() {
95 let err = Error::Pitch("pitch error".to_string());
96 assert_eq!(format!("{err}"), "Pitch error: pitch error");
97 }
98
99 #[test]
100 fn test_display_microtone() {
101 let err = Error::Microtone("microtone error".to_string());
102 assert_eq!(format!("{err}"), "Microtone error: microtone error");
103 }
104
105 #[test]
106 fn test_display_accidental() {
107 let err = Error::Accidental("accidental error".to_string());
108 assert_eq!(format!("{err}"), "Accidental error: accidental error");
109 }
110
111 #[test]
112 fn test_display_chordtables() {
113 let err = Error::ChordTables("chordtables error".to_string());
114 assert_eq!(format!("{err}"), "ChordTables error: chordtables error");
115 }
116
117 #[test]
118 fn test_display_interval() {
119 let err = Error::Interval("interval error".to_string());
120 assert_eq!(format!("{err}"), "Interval error: interval error");
121 }
122
123 #[test]
124 fn test_display_stepname() {
125 let err = Error::StepName("step name error".to_string());
126 assert_eq!(format!("{err}"), "StepName error: step name error");
127 }
128
129 #[test]
130 fn test_display_pitchclassstring() {
131 let err = Error::PitchClassString("pitch class error".to_string());
132 assert_eq!(
133 format!("{err}"),
134 "PitchClassString error: pitch class error"
135 );
136 }
137
138 #[test]
139 fn test_display_ordinal() {
140 let err = Error::Ordinal("ordinal error".to_string());
141 assert_eq!(format!("{err}"), "Ordinal error: ordinal error");
142 }
143
144 #[test]
145 fn test_display_polyrhythm() {
146 let err = Error::Polyrhythm("polyrhythm error".to_string());
147 assert_eq!(format!("{err}"), "Polyrhythm error: polyrhythm error");
148 }
149
150 #[test]
151 fn test_display_tuningsystem() {
152 let err = Error::TuningSystem("tuning system error".to_string());
153 assert_eq!(format!("{err}"), "TuningSystem error: tuning system error");
154 }
155
156 #[test]
157 fn test_source_none() {
158 let errors = [
159 Error::Music21Object("music21".to_string()),
160 Error::Chord("chord".to_string()),
161 Error::Pitch("pitch".to_string()),
162 Error::Microtone("microtone".to_string()),
163 Error::Accidental("accidental".to_string()),
164 Error::ChordTables("chordtables".to_string()),
165 Error::Interval("interval".to_string()),
166 Error::StepName("step".to_string()),
167 Error::PitchClass("pitch class".to_string()),
168 Error::PitchClassString("pitch class".to_string()),
169 Error::Ordinal("ordinal".to_string()),
170 Error::Polyrhythm("polyrhythm".to_string()),
171 Error::TuningSystem("tuning system".to_string()),
172 Error::Midi("midi".to_string()),
173 Error::Analysis("analysis".to_string()),
174 ];
175
176 for err in errors.iter() {
177 assert!(
179 err.source().is_none(),
180 "Expected None for source() in {err:?}"
181 );
182 }
183 }
184
185 #[test]
186 fn test_all_errors_display() {
187 let cases = [
188 (
189 Error::Music21Object("music21".to_string()),
190 "Music21Object error: music21",
191 ),
192 (Error::Chord("chord".to_string()), "Chord error: chord"),
193 (Error::Pitch("pitch".to_string()), "Pitch error: pitch"),
194 (
195 Error::Microtone("microtone".to_string()),
196 "Microtone error: microtone",
197 ),
198 (
199 Error::Accidental("accidental".to_string()),
200 "Accidental error: accidental",
201 ),
202 (
203 Error::ChordTables("chordtables".to_string()),
204 "ChordTables error: chordtables",
205 ),
206 (
207 Error::Interval("interval".to_string()),
208 "Interval error: interval",
209 ),
210 (Error::StepName("step".to_string()), "StepName error: step"),
211 (
212 Error::PitchClass("pitchclass".to_string()),
213 "PitchClass error: pitchclass",
214 ),
215 (
216 Error::PitchClassString("pitchclass".to_string()),
217 "PitchClassString error: pitchclass",
218 ),
219 (
220 Error::Ordinal("ordinal".to_string()),
221 "Ordinal error: ordinal",
222 ),
223 (
224 Error::Polyrhythm("polyrhythm".to_string()),
225 "Polyrhythm error: polyrhythm",
226 ),
227 (
228 Error::TuningSystem("tuning system".to_string()),
229 "TuningSystem error: tuning system",
230 ),
231 (Error::Midi("midi".to_string()), "Midi error: midi"),
232 (
233 Error::Analysis("analysis".to_string()),
234 "Analysis error: analysis",
235 ),
236 ];
237
238 for (err, expected) in cases.iter() {
239 assert_eq!(format!("{err}"), *expected);
240 assert!(err.source().is_none());
241 }
242 }
243}