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