abc_parser/datatypes/
mod.rs

1//! Structures representing parsed ABC music.
2
3pub mod builder;
4pub mod writer;
5
6#[derive(Clone, Debug, PartialEq)]
7pub struct TuneBook {
8    pub comments: Vec<IgnoredLine>,
9    pub header: Option<FileHeader>,
10    pub tunes: Vec<Tune>,
11}
12impl TuneBook {
13    pub fn new(
14        comments: Vec<IgnoredLine>,
15        header: Option<FileHeader>,
16        tunes: Vec<Tune>,
17    ) -> TuneBook {
18        TuneBook {
19            comments,
20            header,
21            tunes,
22        }
23    }
24}
25
26#[derive(Clone, Debug, Eq, PartialEq)]
27pub struct FileHeader {
28    pub lines: Vec<HeaderLine>,
29}
30impl FileHeader {
31    pub fn new(lines: Vec<HeaderLine>) -> FileHeader {
32        FileHeader { lines }
33    }
34}
35
36#[derive(Clone, Debug, PartialEq)]
37pub struct Tune {
38    pub header: TuneHeader,
39    pub body: Option<TuneBody>,
40}
41impl Tune {
42    pub fn new(header: TuneHeader, body: Option<TuneBody>) -> Tune {
43        Tune { header, body }
44    }
45}
46
47#[derive(Clone, Debug, Eq, PartialEq)]
48pub struct TuneHeader {
49    pub lines: Vec<HeaderLine>,
50}
51impl TuneHeader {
52    pub fn new(lines: Vec<HeaderLine>) -> TuneHeader {
53        TuneHeader { lines }
54    }
55}
56
57#[derive(Clone, Debug, Eq, PartialEq)]
58pub enum IgnoredLine {
59    Comment(Comment),
60    EmptyLine,
61}
62
63#[derive(Clone, Debug, Eq, PartialEq)]
64pub enum HeaderLine {
65    Field(InfoField, Option<Comment>),
66    Comment(Comment),
67}
68
69#[derive(Clone, Debug, Eq, PartialEq)]
70pub struct InfoField(pub char, pub String);
71impl InfoField {
72    pub fn new(c: char, s: String) -> InfoField {
73        InfoField(c, s)
74    }
75}
76
77#[derive(Clone, Debug, PartialEq)]
78pub struct TuneBody {
79    pub lines: Vec<TuneLine>,
80}
81impl TuneBody {
82    pub fn new(lines: Vec<TuneLine>) -> TuneBody {
83        TuneBody { lines }
84    }
85}
86
87#[derive(Clone, Debug, PartialEq)]
88pub enum TuneLine {
89    Comment(Comment),
90    Music(MusicLine),
91    Symbol(SymbolLine),
92    Lyric(LyricLine),
93}
94
95#[derive(Clone, Debug, PartialEq)]
96pub struct MusicLine {
97    pub symbols: Vec<MusicSymbol>,
98}
99impl MusicLine {
100    pub fn new(symbols: Vec<MusicSymbol>) -> MusicLine {
101        MusicLine { symbols }
102    }
103}
104
105#[derive(Clone, Debug, Eq, PartialEq)]
106pub struct SymbolLine {
107    pub symbols: Vec<SymbolLineSymbol>,
108}
109impl SymbolLine {
110    pub fn new(symbols: Vec<SymbolLineSymbol>) -> SymbolLine {
111        SymbolLine { symbols }
112    }
113}
114
115#[derive(Clone, Debug, PartialEq)]
116pub struct LyricLine {
117    pub symbols: Vec<LyricSymbol>,
118}
119impl LyricLine {
120    pub fn new(symbols: Vec<LyricSymbol>) -> LyricLine {
121        LyricLine { symbols }
122    }
123}
124
125#[derive(Clone, Debug, PartialEq)]
126pub enum MusicSymbol {
127    Note {
128        accidental: Option<Accidental>,
129        note: Note,
130        octave: i8,
131        length: Option<Length>,
132        tie: Option<Tie>,
133    },
134    Chord {
135        notes: Vec<MusicSymbol>,
136        length: Option<Length>,
137        tie: Option<Tie>,
138    },
139    GraceNotes {
140        acciaccatura: Option<()>,
141        notes: Vec<MusicSymbol>,
142    },
143    /// An `r` value of 0 indicates that the parser does not have enough information and it must
144    /// be determined from the time signature.
145    Tuplet {
146        p: u32,
147        q: Option<u32>,
148        r: Option<u32>,
149    },
150    BrokenRhythm {
151        rhythm: String,
152        before: Vec<MusicSymbol>,
153        after: Vec<MusicSymbol>,
154    },
155    Decoration(Decoration),
156    Annotation(Annotation),
157    Bar(String, Option<String>),
158    Beam(String),
159    Slur(Slur),
160    Comment(Comment),
161    Rest(Rest),
162    Spacer,
163    Ending(String),
164    InlineField(InfoField, bool),
165    Space(String),
166    Reserved(String),
167}
168
169impl MusicSymbol {
170    pub fn new_note(
171        accidental: Option<Accidental>,
172        note: Note,
173        octave: i8,
174        length: Option<Length>,
175        tie: Option<Tie>,
176    ) -> MusicSymbol {
177        MusicSymbol::Note {
178            accidental,
179            note,
180            octave,
181            length,
182            tie,
183        }
184    }
185
186    pub fn new_tuplet(p: u32, q: Option<u32>, r: Option<u32>) -> MusicSymbol {
187        assert!(p > 1 && p < 10);
188        assert_ne!(r, Some(0));
189
190        MusicSymbol::Tuplet { p, q, r }
191    }
192}
193
194#[derive(Clone, Debug, Eq, PartialEq)]
195pub enum SymbolLineSymbol {
196    Annotation(Annotation),
197    Decoration(Decoration),
198    SymbolAlignment(SymbolAlignment),
199    Space(String),
200}
201
202#[derive(Clone, Debug, Eq, PartialEq)]
203pub enum LyricSymbol {
204    Syllable(String),
205    SymbolAlignment(SymbolAlignment),
206    Space(String),
207}
208
209#[derive(Copy, Clone, Debug, Eq, PartialEq)]
210pub enum SymbolAlignment {
211    /// (hyphen) break between syllables within a word
212    Break,
213    /// (underscore) previous syllable is to be held for an extra note
214    Extend,
215    /// (star) one note is skipped (i.e. * is equivalent to a blank syllable)
216    Skip,
217    /// (tilde) appears as a space; aligns multiple words under one note
218    Space,
219    /// (backslash hyphen) appears as hyphen; aligns multiple syllables under one note
220    Hyphen,
221    /// (vertical bar) advances to the next bar
222    Bar,
223}
224
225#[derive(Clone, Debug, Eq, PartialEq)]
226pub struct Annotation {
227    placement: Option<Placement>,
228    text: String,
229}
230
231impl Annotation {
232    pub fn new(placement: Option<Placement>, text: String) -> Annotation {
233        Annotation { placement, text }
234    }
235}
236
237/// The placement of an annotation.
238#[derive(Copy, Clone, Debug, Eq, PartialEq)]
239pub enum Placement {
240    Above,
241    Below,
242    Left,
243    Right,
244    Auto,
245}
246
247/// A tie which may apply between a note and the following note of the same pitch.
248#[derive(Copy, Clone, Debug, Eq, PartialEq)]
249pub enum Tie {
250    /// A normal tie.
251    Solid,
252    /// A dotted tie.
253    Dotted,
254}
255
256#[derive(Copy, Clone, Debug, Eq, PartialEq)]
257pub enum Slur {
258    Begin,
259    BeginDotted,
260    End,
261}
262
263#[derive(Copy, Clone, Debug, Eq, PartialEq)]
264pub enum Note {
265    C,
266    D,
267    E,
268    F,
269    G,
270    A,
271    B,
272}
273
274impl From<Note> for char {
275    fn from(note: Note) -> Self {
276        match note {
277            Note::C => 'C',
278            Note::D => 'D',
279            Note::E => 'E',
280            Note::F => 'F',
281            Note::G => 'G',
282            Note::A => 'A',
283            Note::B => 'B',
284        }
285    }
286}
287
288#[derive(Clone, Debug, Eq, PartialEq)]
289pub enum Decoration {
290    Staccato,
291    Roll,
292    Fermata,
293    Accent,
294    LowerMordent,
295    Coda,
296    UpperMordent,
297    Segno,
298    Trill,
299    UpBow,
300    DownBow,
301    Unresolved(String),
302}
303
304#[derive(Copy, Clone, Debug, Eq, PartialEq)]
305pub enum Accidental {
306    Natural,
307    Sharp,
308    Flat,
309    DoubleSharp,
310    DoubleFlat,
311}
312
313#[derive(Copy, Clone, Debug, PartialEq)]
314pub enum Rest {
315    Note(Option<Length>),
316    Measure(Option<Length>),
317    NoteHidden(Option<Length>),
318    MeasureHidden(Option<Length>),
319}
320
321#[derive(Copy, Clone, Debug, PartialEq)]
322pub struct Length(f32);
323
324impl Length {
325    pub fn new(length: f32) -> Length {
326        Length(length)
327    }
328}
329
330#[derive(Clone, Debug, Eq, PartialEq)]
331pub enum Comment {
332    Comment(String),
333    CommentLine(String, String),
334    StylesheetDirective(String),
335}