Skip to main content

music21_rs/abc/
read.rs

1//! Reading ABC: music21's `abcFormat`, its tokens and handlers, and
2//! `abcFormat.translate`, which turns them into a score.
3//!
4//! The text is cut into tokens one character at a time, each token is told
5//! what is in force where it stands -- the default length, the key, a tuplet,
6//! a tie -- and the tokens of each voice are then read off measure by
7//! measure. The order and the oddities are music21's throughout, since the
8//! score it makes is what this one is held to.
9
10use crate::articulations::{Articulation, ArticulationKind};
11use crate::bar::{Barline, BarlineType, Ending, RepeatDirection};
12use crate::chord::Chord;
13use crate::chordsymbol::ChordSymbol;
14use crate::clef::Clef;
15use crate::defaults::{FloatType, IntegerType};
16use crate::duration::{Duration, Tuplet};
17use crate::error::{Error, Result};
18use crate::interval::Interval;
19use crate::key::KeySignature;
20use crate::makenotation::split_element;
21use crate::metadata::Metadata;
22use crate::meter::TimeSignature;
23use crate::notation::{Tie, TieStyle, TieType};
24use crate::note::Note;
25use crate::pitch::Pitch;
26use crate::rest::Rest;
27use crate::spanner::{Spanner, SpannerKind};
28use crate::stream::{Stream, StreamElement, StreamEvent, StreamKind};
29use crate::tempo::MetronomeMark;
30
31fn abc_error(message: impl Into<String>) -> Error {
32    Error::Abc(message.into())
33}
34
35/// The ABC version a file is read as where it names none: music21's
36/// `defaults.abcVersionDefault`.
37const DEFAULT_VERSION: (u32, u32, u32) = (1, 3, 0);
38
39/// Every bar token, in the order music21 tries them.
40const BARS: [(&str, &str); 14] = [
41    (":|1", "light-heavy-repeat-end-first"),
42    (":|2", "light-heavy-repeat-end-second"),
43    ("|]", "light-heavy"),
44    ("||", "light-light"),
45    ("[|", "heavy-light"),
46    ("[1", "regular-first"),
47    ("[2", "regular-second"),
48    ("|1", "regular-first"),
49    ("|2", "regular-second"),
50    (":|", "light-heavy-repeat-end"),
51    ("|:", "heavy-light-repeat-start"),
52    ("::", "heavy-heavy-repeat-bidirectional"),
53    ("|", "regular"),
54    (":", "dotted"),
55];
56
57/// music21's `opFrac`, near enough for lengths: the nearest fraction with a
58/// small denominator where the float is within a hair of one.
59fn op_frac(value: FloatType) -> FloatType {
60    if (value * 32768.0).fract() == 0.0 {
61        return value;
62    }
63    for denominator in 1..=65535u32 {
64        let scaled = value * FloatType::from(denominator);
65        if (scaled - scaled.round()).abs() < 1e-9 * FloatType::from(denominator).max(1.0) {
66            return scaled.round() / FloatType::from(denominator);
67        }
68    }
69    value
70}
71
72// ------------------------------------------------------------------ tokens
73
74/// music21's `ABCBar`.
75#[derive(Clone, Debug, Default, PartialEq)]
76struct Bar {
77    src: String,
78    /// `repeat` or `barline`, nothing where the text is no bar at all.
79    repeat: bool,
80    style: String,
81    /// `end`, `start`, `first` or `second`.
82    form: String,
83}
84
85impl Bar {
86    fn new(src: &str) -> Self {
87        let mut bar = Self {
88            src: src.to_string(),
89            ..Self::default()
90        };
91        let Some((_, described)) = BARS.iter().find(|(text, _)| *text == src.trim()) else {
92            return bar;
93        };
94        let parts: Vec<&str> = described.split('-').collect();
95        bar.repeat = parts.contains(&"repeat");
96        if parts.len() == 1 {
97            bar.style = parts[0].to_string();
98        } else if parts.contains(&"first") {
99            bar.style = "regular".to_string();
100            bar.form = "first".to_string();
101        } else if parts.contains(&"second") {
102            bar.style = "regular".to_string();
103            bar.form = "second".to_string();
104        } else {
105            bar.style = format!("{}-{}", parts[0], parts[1]);
106        }
107        if parts.len() > 2 {
108            bar.form = parts[3].to_string();
109        }
110        bar
111    }
112
113    fn is_regular(&self) -> bool {
114        !self.repeat && self.style == "regular"
115    }
116
117    /// Which ending the bar opens, where it opens one.
118    fn repeat_bracket(&self) -> Option<u32> {
119        match self.form.as_str() {
120            "first" => Some(1),
121            "second" => Some(2),
122            _ => None,
123        }
124    }
125
126    /// music21's `getBarObject`.
127    fn barline(&self) -> Option<Barline> {
128        if self.repeat {
129            return match self.form.as_str() {
130                "start" => Some(Barline::repeat(RepeatDirection::Start, None)),
131                "end" => Some(Barline::repeat(RepeatDirection::End, None)),
132                _ => None,
133            };
134        }
135        if self.style == "regular" || self.style.is_empty() || self.repeat_bracket().is_some() {
136            return None;
137        }
138        BarlineType::from_name(&self.style).ok().map(Barline::new)
139    }
140}
141
142/// music21's `ABCNote`, and `ABCChord` where it holds notes of its own.
143#[derive(Clone, Debug, Default)]
144struct AbcNote {
145    src: String,
146    is_chord: bool,
147    carried_accidental: String,
148    chord_symbols: Vec<String>,
149    in_grace: bool,
150    default_quarter_length: Option<FloatType>,
151    /// The mark and whether this note stands to its left.
152    broken_rhythm: Option<(String, bool)>,
153    key: Option<KeySignature>,
154    tuplet: Option<Tuplet>,
155    /// The spanners in force, by where they stand among the handler's.
156    spanners: Vec<usize>,
157    tie: Option<TieType>,
158    articulations: Vec<&'static str>,
159    accidental_display: Option<bool>,
160    is_rest: bool,
161    pitch_name: Option<String>,
162    quarter_length: FloatType,
163    sub_tokens: Vec<AbcNote>,
164}
165
166#[derive(Clone, Debug)]
167enum Token {
168    Metadata {
169        tag: String,
170        data: String,
171    },
172    Bar(Bar),
173    Tuplet {
174        src: String,
175    },
176    Tie,
177    /// A slur or a hairpin opening: the spanner it starts.
178    SpannerStart(SpannerKind, Option<usize>),
179    ParenStop,
180    Staccato,
181    Upbow,
182    Downbow,
183    Accent,
184    Straccent,
185    Tenuto,
186    GraceStart,
187    GraceStop,
188    BrokenRhythm(String),
189    Note(Box<AbcNote>),
190}
191
192impl Token {
193    fn is_note(&self) -> bool {
194        matches!(self, Self::Note(_))
195    }
196
197    fn metadata(&self) -> Option<(&str, &str)> {
198        match self {
199            Self::Metadata { tag, data } => Some((tag, data)),
200            _ => None,
201        }
202    }
203}
204
205/// music21's `ABCMetadata.preParse`: the tag before the colon and what
206/// follows it, a comment taken off.
207fn metadata_token(src: &str) -> Token {
208    let chars: Vec<char> = src.chars().collect();
209    let is_tag =
210        chars.len() >= 2 && (chars[0].is_ascii_uppercase() || chars[0] == 'w') && chars[1] == ':';
211    if !is_tag {
212        return Token::Metadata {
213            tag: String::new(),
214            data: String::new(),
215        };
216    }
217    let stripped = src.split('%').next().unwrap_or("");
218    let mut pieces = stripped.chars();
219    let tag: String = pieces.by_ref().take(1).collect();
220    let data: String = pieces.skip(1).collect();
221    Token::Metadata {
222        tag,
223        data: data.trim().to_string(),
224    }
225}
226
227/// music21's `getTimeSignatureParameters`.
228fn meter_parameters(data: &str) -> Result<Option<(u32, u32)>> {
229    if data.to_lowercase() == "none" {
230        return Ok(None);
231    }
232    match data {
233        "C" => return Ok(Some((4, 4))),
234        "C|" => return Ok(Some((2, 2))),
235        _ => {}
236    }
237    let (numerator, denominator) = data
238        .split_once('/')
239        .ok_or_else(|| abc_error(format!("cannot read the meter {data:?}")))?;
240    let digits = |text: &str| -> Result<u32> {
241        text.chars()
242            .filter(char::is_ascii_digit)
243            .collect::<String>()
244            .parse()
245            .map_err(|_| abc_error(format!("cannot read the meter {data:?}")))
246    };
247    Ok(Some((digits(numerator)?, digits(denominator)?)))
248}
249
250fn meter_of(data: &str) -> Result<Option<TimeSignature>> {
251    match meter_parameters(data)? {
252        Some((numerator, denominator)) => Ok(Some(TimeSignature::new(numerator, denominator)?)),
253        None => Ok(None),
254    }
255}
256
257/// music21's `getKeySignatureParameters`: the signed count of sharps and the
258/// mode, where the key names one.
259fn key_parameters(data: &str) -> Result<(IntegerType, Option<&'static str>)> {
260    const NAMES: [&str; 20] = [
261        "c", "g", "d", "a", "e", "b", "f#", "g#", "a#", "f", "bb", "eb", "d#", "ab", "e#", "db",
262        "c#", "gb", "cb", "hp",
263    ];
264    let mut names: Vec<&str> = NAMES.to_vec();
265    // Longest first, and the sort is stable.
266    names.sort_by_key(|name| std::cmp::Reverse(name.len()));
267    let chars: Vec<char> = data.chars().collect();
268    let mut standard = "C".to_string();
269    let mut remain = String::new();
270    for target in names {
271        let length = target.chars().count();
272        let head: String = chars.iter().take(length).collect();
273        if head.to_lowercase() == target {
274            standard = head;
275            remain = chars.iter().skip(length).collect();
276            break;
277        }
278    }
279    let letters: Vec<char> = standard.chars().collect();
280    if letters.len() > 1 && letters[1] == 'b' {
281        standard = format!("{}-", letters[0]);
282    }
283    let remain = remain.trim().to_lowercase();
284    let mut mode: Option<&'static str> = if remain.is_empty() {
285        Some("major")
286    } else {
287        [
288            ("dor", "dorian"),
289            ("phr", "phrygian"),
290            ("lyd", "lydian"),
291            ("mix", "mixolydian"),
292            ("maj", "major"),
293            ("ion", "ionian"),
294            ("aeo", "aeolian"),
295            ("m", "minor"),
296        ]
297        .into_iter()
298        .find(|(prefix, _)| remain.starts_with(prefix))
299        .map(|(_, mode)| mode)
300    };
301    // The Highland pipes: no signature written, or two sharps and a natural.
302    if standard == "HP" {
303        standard = "C".to_string();
304        mode = None;
305    } else if standard == "Hp" {
306        standard = "D".to_string();
307        mode = None;
308    }
309    let tonic = Pitch::from_name(&standard)?;
310    let sharps = crate::key::pitch_to_sharps(&tonic, mode)?;
311    Ok((sharps, mode))
312}
313
314/// music21's `getKeySignatureObject`: a key where there is a mode, a
315/// signature otherwise.
316fn key_of(data: &str) -> Result<StreamElement> {
317    let (sharps, mode) = key_parameters(data)?;
318    let signature = KeySignature::new(sharps);
319    Ok(match mode {
320        Some(mode) => match signature.try_as_key(Some(mode), None) {
321            Ok(key) => key.into(),
322            Err(_) => signature.into(),
323        },
324        None => signature.into(),
325    })
326}
327
328/// music21's `getClefObject`: the clef a key line names, and how far the
329/// notes under it are moved.
330fn clef_of(data: &str) -> Option<(Clef, IntegerType)> {
331    let lower = data.to_lowercase();
332    if lower.contains("-8va") {
333        Clef::from_string("treble8vb", 0)
334            .ok()
335            .map(|clef| (clef, -12))
336    } else if lower.contains("bass") {
337        Some((Clef::bass(), -24))
338    } else {
339        None
340    }
341}
342
343/// music21's `getMetronomeMarkObject`.
344fn tempo_of(data: &str) -> Result<MetronomeMark> {
345    let mut text: Option<String> = None;
346    let non_text = if data.contains('"') {
347        let mut quoted = String::new();
348        let mut outside = String::new();
349        let mut open = false;
350        for character in data.chars() {
351            if character == '"' {
352                open = !open;
353            } else if open {
354                quoted.push(character);
355            } else {
356                outside.push(character);
357            }
358        }
359        text = Some(quoted.trim().to_string()).filter(|text| !text.is_empty());
360        outside.trim().to_string()
361    } else {
362        data.trim().to_string()
363    };
364    let read = |number: &str| -> Result<FloatType> {
365        number
366            .trim()
367            .parse::<FloatType>()
368            .map_err(|_| abc_error(format!("cannot read the tempo {data:?}")))
369    };
370    let mut number: Option<FloatType> = None;
371    let mut referent: Option<FloatType> = None;
372    if !non_text.is_empty() {
373        if let Some((lengths, count)) = non_text.split_once('=') {
374            number = Some(read(count)?);
375            let mut quarters = 0.0;
376            for length in lengths.split(' ') {
377                let (numerator, denominator) = length.split_once('/').unwrap_or(("1", "1"));
378                quarters += read(numerator)? / read(denominator)? * 4.0;
379            }
380            referent = Some(quarters);
381        } else {
382            number = Some(read(&non_text)?);
383        }
384    }
385    let mut mark = match (number, text) {
386        (Some(number), Some(text)) => MetronomeMark::with_number_and_text(number, text),
387        (Some(number), None) => MetronomeMark::new(number),
388        (None, Some(text)) => MetronomeMark::from_text(text),
389        (None, None) => MetronomeMark::default(),
390    };
391    if let Some(referent) = referent {
392        mark.set_referent(Duration::new(referent)?);
393    }
394    Ok(mark)
395}
396
397/// music21's `getDefaultQuarterLength`, for an `L:` or an `M:` line.
398fn default_quarter_length(tag: &str, data: &str) -> Result<FloatType> {
399    if tag == "L" && data.contains('/') {
400        let (numerator, denominator) = data.split_once('/').unwrap_or(("1", "8"));
401        let numerator: FloatType = numerator
402            .trim()
403            .parse()
404            .map_err(|_| abc_error(format!("cannot read the default length {data:?}")))?;
405        let denominator: FloatType = if denominator == "G" {
406            4.0
407        } else {
408            denominator
409                .trim()
410                .parse()
411                .map_err(|_| abc_error(format!("cannot read the default length {data:?}")))?
412        };
413        return Ok(numerator * 4.0 / denominator);
414    }
415    if tag == "M" {
416        return Ok(match meter_parameters(data)? {
417            None => 0.5,
418            // Under three quarters of a whole note the unit is a sixteenth.
419            Some((numerator, denominator))
420                if FloatType::from(numerator) / FloatType::from(denominator) < 0.75 =>
421            {
422                0.25
423            }
424            Some(_) => 0.5,
425        });
426    }
427    Err(abc_error(format!(
428        "no quarter length associated with this metadata: {data}"
429    )))
430}
431
432impl AbcNote {
433    fn new(src: &str, carried_accidental: &str, is_chord: bool) -> Self {
434        Self {
435            src: src.to_string(),
436            is_chord,
437            carried_accidental: carried_accidental.to_string(),
438            ..Self::default()
439        }
440    }
441
442    /// music21's `_splitChordSymbols`: the quoted strings, and what is left
443    /// after the last of them.
444    fn split_chord_symbols(src: &str) -> (Vec<String>, String) {
445        if !src.contains('"') {
446            return (Vec::new(), src.to_string());
447        }
448        let chars: Vec<char> = src.chars().collect();
449        let mut symbols = Vec::new();
450        let mut index = 0;
451        let mut after = 0;
452        while index < chars.len() {
453            if chars[index] == '"'
454                && let Some(length) = chars[index + 1..].iter().position(|c| *c == '"')
455            {
456                let close = index + 1 + length;
457                symbols.push(chars[index..=close].iter().collect::<String>());
458                index = close + 1;
459                after = index;
460                continue;
461            }
462            index += 1;
463        }
464        if symbols.is_empty() {
465            return (Vec::new(), src.to_string());
466        }
467        (symbols, chars[after..].iter().collect())
468    }
469
470    /// music21's `getPitchName`: the pitch as music21 names one, or nothing
471    /// for a rest, and whether its accidental is shown.
472    fn pitch_name(
473        &self,
474        src: &str,
475        forced_key: Option<&KeySignature>,
476    ) -> Result<(Option<String>, Option<bool>)> {
477        let chars: Vec<char> = src.chars().collect();
478        let mut text: String = if chars.len() > 1 && matches!(chars[0], 'u' | 'T') {
479            chars[1..].iter().collect()
480        } else {
481            src.to_string()
482        };
483        text = text.replace('T', "");
484        let name = text
485            .chars()
486            .find(|c| matches!(c, 'a'..='g' | 'A'..='G' | 'z'))
487            .ok_or_else(|| abc_error(format!("cannot find any pitch information in: {text:?}")))?;
488        if name == 'z' {
489            return Ok((None, None));
490        }
491        let key = forced_key.or(self.key.as_ref());
492        let count = |wanted: char| text.chars().filter(|c| *c == wanted).count();
493        let mut octave: i32 = if name.is_lowercase() { 5 } else { 4 };
494        octave -= count(',') as i32;
495        octave += count('\'') as i32;
496        let marks = |source: &str| -> String {
497            let count = |wanted: char| source.chars().filter(|c| *c == wanted).count();
498            format!(
499                "{}{}{}",
500                "-".repeat(count('_')),
501                "#".repeat(count('^')),
502                "n".repeat(count('='))
503            )
504        };
505        let written = marks(&text);
506        let carried = marks(&self.carried_accidental);
507        if !carried.is_empty() && !written.is_empty() {
508            return Err(abc_error("Carried accidentals not rendered moot."));
509        }
510        let mut name = name.to_uppercase().to_string();
511        let display = if !carried.is_empty() {
512            None
513        } else if !written.is_empty() {
514            Some(true)
515        } else {
516            match key {
517                None => None,
518                Some(key) => {
519                    // The signature's own spelling of the note, not shown.
520                    if let Ok(altered) = key.altered_pitches()
521                        && let Some(pitch) = altered
522                            .iter()
523                            .find(|pitch| pitch.step().as_char().to_string() == name)
524                    {
525                        name = pitch.name();
526                    }
527                    Some(false)
528                }
529            }
530        };
531        let accidental = if carried.is_empty() { written } else { carried };
532        Ok((Some(format!("{name}{accidental}{octave}")), display))
533    }
534
535    /// music21's `getQuarterLength`.
536    fn read_quarter_length(
537        &self,
538        src: &str,
539        forced_default: Option<FloatType>,
540    ) -> Result<FloatType> {
541        let default = forced_default
542            .or(self.default_quarter_length)
543            .ok_or_else(|| {
544                abc_error("cannot calculate quarter length without a default quarter length")
545            })?;
546        let number: String = src
547            .chars()
548            .filter(|c| c.is_ascii_digit() || *c == '/')
549            .collect();
550        let whole = |text: &str| -> Result<FloatType> {
551            text.trim()
552                .parse::<FloatType>()
553                .map_err(|_| abc_error(format!("cannot read the length in {src:?}")))
554        };
555        let mut length = match number.as_str() {
556            "" => default,
557            "/" => default * 0.5,
558            "//" => default * 0.25,
559            "///" => default * 0.125,
560            text if text.starts_with('/') => {
561                op_frac(default / whole(text.split('/').nth(1).unwrap_or(""))?)
562            }
563            text if text.ends_with('/') => {
564                default * whole(text.split('/').next().unwrap_or(""))? / 2.0
565            }
566            text if text.matches('/').count() == 2 => 1.0,
567            text if text.contains('/') => {
568                let (numerator, denominator) = text.split_once('/').unwrap_or(("1", "1"));
569                op_frac(default * whole(numerator)? / whole(denominator)?)
570            }
571            text => default * whole(text)?,
572        };
573        if let Some((symbol, left)) = &self.broken_rhythm {
574            let (first, second) = match symbol.as_str() {
575                ">" => (1.5, 0.5),
576                "<" => (0.5, 1.5),
577                ">>" => (1.75, 0.25),
578                "<<" => (0.25, 1.75),
579                ">>>" => (1.875, 0.125),
580                "<<<" => (0.125, 1.875),
581                _ => (1.0, 1.0),
582            };
583            length *= if *left { first } else { second };
584        }
585        Ok(length)
586    }
587
588    /// music21's `ABCNote.parse` and `ABCChord.parse`.
589    fn parse(
590        &mut self,
591        forced_default: Option<FloatType>,
592        forced_key: Option<&KeySignature>,
593    ) -> Result<()> {
594        let (symbols, rest) = Self::split_chord_symbols(&self.src);
595        self.chord_symbols = symbols;
596        if self.is_chord {
597            let chars: Vec<char> = rest.chars().collect();
598            let close = chars.iter().position(|c| *c == ']').ok_or_else(|| {
599                abc_error(format!(
600                    "Bad chord indicator: {}: no closing bracket found.",
601                    self.src
602                ))
603            })?;
604            let outer: String = chars[close + 1..].iter().collect();
605            let inner: String = chars[1..close].iter().collect();
606            let outer_length = self.read_quarter_length(&outer, Some(1.0))?;
607            let key = forced_key.cloned().or_else(|| self.key.clone());
608            let mut handler = Handler::new(DEFAULT_VERSION);
609            handler.tokenize(&inner)?;
610            let mut inner_length = 0.0;
611            for token in handler.tokens {
612                let Token::Note(mut note) = token else {
613                    continue;
614                };
615                note.parse(self.default_quarter_length, key.as_ref())?;
616                if note.is_rest {
617                    continue;
618                }
619                if inner_length == 0.0 {
620                    inner_length = note.quarter_length;
621                }
622                self.sub_tokens.push(*note);
623            }
624            self.quarter_length = outer_length * inner_length;
625            return Ok(());
626        }
627        // A note music21 can find no pitch in is read as a C.
628        let (name, display) = match self.pitch_name(&rest, forced_key) {
629            Ok(read) => read,
630            Err(Error::Abc(message)) if message.starts_with("cannot find any pitch") => {
631                (Some("C".to_string()), Some(false))
632            }
633            Err(error) => return Err(error),
634        };
635        self.is_rest = name.is_none();
636        self.pitch_name = name;
637        self.accidental_display = display;
638        self.quarter_length = self.read_quarter_length(&rest, forced_default)?;
639        Ok(())
640    }
641}
642
643// ----------------------------------------------------------------- handler
644
645/// A spanner as the handler makes one: what kind, and the notes it joins.
646#[derive(Clone, Debug)]
647struct Spanning {
648    kind: SpannerKind,
649    uids: Vec<usize>,
650}
651
652/// music21's `ABCHandler`.
653#[derive(Clone, Debug)]
654struct Handler {
655    version: (u32, u32, u32),
656    directives: Vec<(String, String)>,
657    tokens: Vec<Token>,
658}
659
660impl Handler {
661    fn new(version: (u32, u32, u32)) -> Self {
662        Self {
663            version,
664            directives: Vec::new(),
665            tokens: Vec::new(),
666        }
667    }
668
669    /// music21's `_accidentalPropagation`.
670    fn accidental_propagation(&self) -> &str {
671        if self.version < (2, 0, 0) {
672            return "not";
673        }
674        self.directives
675            .iter()
676            .rev()
677            .find(|(key, _)| key == "propagate-accidentals")
678            .map_or("pitch", |(_, value)| value.as_str())
679    }
680
681    /// music21's `parseHeaderForVersionInformation`: `%abc-2.1` in the first
682    /// hundred characters.
683    fn read_version(&mut self, text: &str) {
684        let head: String = text.chars().take(100).collect();
685        let Some(at) = head.find("%abc-") else {
686            return;
687        };
688        let rest = &head[at + 5..];
689        let mut numbers = rest
690            .split(|c: char| !c.is_ascii_digit())
691            .take(3)
692            .map(|piece| piece.parse::<u32>().ok());
693        // `major.minor` at the least.
694        let (Some(Some(major)), Some(Some(minor))) = (numbers.next(), numbers.next()) else {
695            return;
696        };
697        if !rest[major.to_string().len()..].starts_with('.') {
698            return;
699        }
700        let patch = numbers.next().flatten().unwrap_or(0);
701        self.version = (major, minor, patch);
702    }
703
704    /// music21's `barlineTokenFilter`: a bar written as two in one.
705    fn bar_tokens(text: &str) -> Vec<Bar> {
706        let pair = match text {
707            "::" => Some((":|", "|:")),
708            "|1" => Some(("|", "[1")),
709            "|2" => Some(("|", "[2")),
710            ":|1" => Some((":|", "[1")),
711            ":|2" => Some((":|", "[2")),
712            _ => None,
713        };
714        match pair {
715            Some((first, second)) => vec![Bar::new(first), Bar::new(second)],
716            None => vec![Bar::new(text)],
717        }
718    }
719
720    /// music21's `tokenize`.
721    fn tokenize(&mut self, source: &str) -> Result<()> {
722        let src: Vec<char> = source.chars().collect();
723        let len = src.len();
724        let at = |index: usize| src.get(index).copied();
725        let slice =
726            |from: usize, to: usize| -> String { src[from.min(len)..to.min(len)].iter().collect() };
727        let next_line_break =
728            |from: usize| -> usize { (from + 1..len).find(|j| src[*j] == '\n').unwrap_or(len) };
729        const DECORATIONS: &str = ".~^=_HLMOPSTuv";
730        const ACCIDENTALS: &str = "^=_";
731
732        let mut active_chord_symbol = String::new();
733        let mut accidentalized: Vec<(String, String)> = Vec::new();
734        let mut accidental = String::new();
735        let mut abc_pitch = String::new();
736        let mut pos = 0usize;
737        while pos < len {
738            let c = src[pos];
739            let next = at(pos + 1);
740            let next_next = at(pos + 2);
741            // What is taken past this character.
742            let mut skip = 0usize;
743
744            if c == '%' {
745                let end = next_line_break(pos);
746                let line = slice(pos, end);
747                if let Some(directive) = line.strip_prefix("%%") {
748                    let key: String = directive
749                        .chars()
750                        .take_while(|c| c.is_ascii_lowercase() || *c == '-')
751                        .collect();
752                    let after = &directive[key.len()..];
753                    if !key.is_empty()
754                        && after.starts_with(char::is_whitespace)
755                        && let Some(value) = after.split_whitespace().next()
756                    {
757                        self.directives.push((key, value.to_string()));
758                    }
759                }
760                pos = end;
761                continue;
762            }
763
764            let starts_metadata = next == Some(':')
765                && next_next.is_some()
766                && next_next != Some('|')
767                && (c == 'w' || (c.is_alphabetic() && c.is_uppercase()));
768            if starts_metadata {
769                let end = next_line_break(pos);
770                self.tokens.push(metadata_token(slice(pos, end).trim()));
771                pos = end;
772                continue;
773            }
774
775            if !c.is_whitespace() && !c.is_alphanumeric() && c != '~' && c != '(' {
776                let mut matched = None;
777                for (text, _) in BARS {
778                    let wanted: Vec<char> = text.chars().collect();
779                    let fits = match wanted.len() {
780                        3 => next.is_some() && next_next.is_some() && slice(pos, pos + 3) == text,
781                        2 => next.is_some() && slice(pos, pos + 2) == text,
782                        _ => c == wanted[0],
783                    };
784                    if fits {
785                        matched = Some(wanted.len());
786                        break;
787                    }
788                }
789                if let Some(length) = matched {
790                    accidentalized.clear();
791                    accidental.clear();
792                    for bar in Self::bar_tokens(&slice(pos, pos + length)) {
793                        self.tokens.push(Token::Bar(bar));
794                    }
795                    pos += length;
796                    continue;
797                }
798            }
799
800            if c == '(' && next.is_some_and(|c| c.is_ascii_digit()) {
801                let mut j = pos + 2;
802                if j >= len {
803                    return Err(abc_error(format!(
804                        "bad index value {j}, max is {}",
805                        len - 1
806                    )));
807                }
808                if at(j) == Some(':') {
809                    j += 1;
810                    if at(j).is_some_and(|c| c.is_ascii_digit()) {
811                        j += 1;
812                    }
813                    if at(j) == Some(':') {
814                        j += 1;
815                        if at(j).is_some_and(|c| c.is_ascii_digit()) {
816                            j += 1;
817                        }
818                    }
819                }
820                self.tokens.push(Token::Tuplet { src: slice(pos, j) });
821                pos = j;
822                continue;
823            }
824
825            if c == '<' || c == '>' {
826                let mut j = pos + 1;
827                while j + 1 < len && matches!(src[j], '<' | '>') {
828                    j += 1;
829                }
830                self.tokens
831                    .push(Token::BrokenRhythm(slice(pos, j).trim().to_string()));
832                pos = j;
833                continue;
834            }
835
836            if c == '!' {
837                let mut j = pos + 1;
838                while j < pos + 20 && j < len {
839                    if src[j] == '!' {
840                        match slice(pos, j + 1).as_str() {
841                            "!crescendo(!" => self
842                                .tokens
843                                .push(Token::SpannerStart(SpannerKind::Crescendo, None)),
844                            "!diminuendo(!" => self
845                                .tokens
846                                .push(Token::SpannerStart(SpannerKind::Diminuendo, None)),
847                            "!crescendo)!" | "!diminuendo)!" => self.tokens.push(Token::ParenStop),
848                            _ => {}
849                        }
850                        skip = j - pos;
851                        break;
852                    }
853                    j += 1;
854                }
855                pos += skip + 1;
856                continue;
857            }
858
859            if c == '(' && next.is_some() {
860                self.tokens
861                    .push(Token::SpannerStart(SpannerKind::Slur, None));
862                pos += 1;
863                continue;
864            }
865            let simple = match c {
866                ')' => Some(Token::ParenStop),
867                '-' => Some(Token::Tie),
868                _ => None,
869            };
870            if let Some(token) = simple {
871                self.tokens.push(token);
872                pos += 1;
873                continue;
874            }
875
876            if c == '"' {
877                let mut j = pos + 1;
878                while j + 1 < len && src[j] != '"' {
879                    j += 1;
880                }
881                j += 1;
882                active_chord_symbol.push_str(&slice(pos, j));
883                pos = j.max(pos + 1);
884                continue;
885            }
886
887            if c == '[' {
888                let mut j = pos + 1;
889                while j + 1 < len && src[j] != ']' {
890                    j += 1;
891                }
892                j += 1;
893                while j < len && (src[j].is_ascii_digit() || src[j] == '/') {
894                    j += 1;
895                }
896                let collected = format!("{}{}", active_chord_symbol, slice(pos, j));
897                active_chord_symbol.clear();
898                self.tokens
899                    .push(Token::Note(Box::new(AbcNote::new(&collected, "", true))));
900                pos = j.max(pos + 1);
901                continue;
902            }
903
904            let mark = match c {
905                '.' => Some(Token::Staccato),
906                'u' => Some(Token::Upbow),
907                '{' => Some(Token::GraceStart),
908                '}' => Some(Token::GraceStop),
909                'v' => Some(Token::Downbow),
910                'K' => Some(Token::Accent),
911                'k' => Some(Token::Straccent),
912                'M' => Some(Token::Tenuto),
913                _ => None,
914            };
915            if let Some(token) = mark {
916                self.tokens.push(token);
917                pos += 1;
918                continue;
919            }
920
921            if c.is_alphabetic() || "~^=_".contains(c) {
922                let mut found = c.is_alphabetic() && !DECORATIONS.contains(c);
923                if found {
924                    abc_pitch = c.to_string();
925                }
926                if ACCIDENTALS.contains(c) {
927                    accidental = c.to_string();
928                }
929                let mut j = pos + 1;
930                while j < len {
931                    let here = src[j];
932                    if !found && DECORATIONS.contains(here) {
933                        j += 1;
934                        // music21 looks at the character after the one it
935                        // has just passed.
936                        match at(j) {
937                            Some(after) if ACCIDENTALS.contains(after) => accidental.push(after),
938                            Some(_) => {}
939                            None => {
940                                return Err(abc_error("a decoration ends the text"));
941                            }
942                        }
943                    } else if !found && here.is_alphabetic() && !"~wuvhHLTSN".contains(here) {
944                        found = true;
945                        abc_pitch = here.to_string();
946                        j += 1;
947                    } else if here.is_ascii_digit() || ",/'".contains(here) {
948                        if here == ',' || here == '\'' {
949                            abc_pitch.push(here);
950                        }
951                        j += 1;
952                    } else {
953                        break;
954                    }
955                }
956                let collected = format!("{}{}", active_chord_symbol, slice(pos, j));
957                active_chord_symbol.clear();
958
959                const PASSED: [&str; 38] = [
960                    "w", "u", "v", "v.", "h", "H", "vk", "uk", "U", "~", ".", "=", "V", "v.", "S",
961                    "s", "i", "I", "ui", "u.", "Q", "Hy", "Hx", "r", "m", "M", "n", "N", "o", "O",
962                    "P", "l", "L", "R", "y", "T", "t", "x",
963                ];
964                let chars: Vec<char> = collected.chars().collect();
965                let last = chars.last().copied().unwrap_or(' ');
966                let passed = PASSED.contains(&collected.as_str())
967                    || collected == "Z"
968                    || (collected.starts_with('"')
969                        && ("uvkKQ.yTwhx".contains(last) || collected.ends_with("v.")))
970                    || collected.starts_with('x')
971                    || collected.starts_with('H')
972                    || collected.starts_with('Z')
973                    || (chars.len() > 1 && chars[0] == '=' && chars[1].is_ascii_digit());
974                if !passed {
975                    let mut carried = String::new();
976                    if !abc_pitch.is_empty() {
977                        let class: String = abc_pitch
978                            .chars()
979                            .take(1)
980                            .flat_map(char::to_uppercase)
981                            .collect();
982                        let key = match self.accidental_propagation() {
983                            "octave" => Some(abc_pitch.clone()),
984                            "pitch" => Some(class),
985                            _ => None,
986                        };
987                        if !accidental.is_empty() {
988                            if let Some(key) = key {
989                                accidentalized.retain(|(known, _)| *known != key);
990                                accidentalized.push((key, accidental.clone()));
991                            }
992                            accidental.clear();
993                        } else if let Some(key) = key
994                            && let Some((_, held)) =
995                                accidentalized.iter().find(|(known, _)| *known == key)
996                        {
997                            carried = held.clone();
998                        }
999                    }
1000                    self.tokens.push(Token::Note(Box::new(AbcNote::new(
1001                        &collected, &carried, false,
1002                    ))));
1003                }
1004                pos = j.max(pos + 1);
1005                continue;
1006            }
1007
1008            pos += 1;
1009        }
1010        Ok(())
1011    }
1012
1013    /// music21's `tokenProcess`: each token told what is in force where it
1014    /// stands, and then read. Hands back the spanners the tokens started.
1015    fn process(&mut self) -> Result<Vec<Spanning>> {
1016        let mut spanners: Vec<Spanning> = Vec::new();
1017        let mut active_spanners: Vec<usize> = Vec::new();
1018        let mut active_parens: Vec<&'static str> = Vec::new();
1019        let mut default_length: Option<FloatType> = None;
1020        let mut key: Option<KeySignature> = None;
1021        let mut meter: Option<TimeSignature> = None;
1022        // The tuplet in force and how many notes it still takes.
1023        let mut tuplet: Option<(Tuplet, i32)> = None;
1024        let mut tie_waiting = false;
1025        let mut marks: Vec<&'static str> = Vec::new();
1026        let mut in_grace = false;
1027        let mut last_note: Option<usize> = None;
1028
1029        for index in 0..self.tokens.len() {
1030            let previous_is_note = index > 0 && self.tokens[index - 1].is_note();
1031            let next_is_note = self.tokens.get(index + 1).is_some_and(Token::is_note);
1032            match self.tokens[index].clone() {
1033                Token::Metadata { tag, data } => {
1034                    if tag == "M" {
1035                        meter = meter_of(&data)?;
1036                    }
1037                    if tag == "L" || (tag == "M" && default_length.is_none()) {
1038                        default_length = Some(default_quarter_length(&tag, &data)?);
1039                    } else if tag == "K" {
1040                        let (sharps, _) = key_parameters(&data)?;
1041                        key = Some(KeySignature::new(sharps));
1042                    }
1043                    if tag == "X" {
1044                        active_parens.clear();
1045                        active_spanners.clear();
1046                    }
1047                }
1048                Token::BrokenRhythm(symbol) => {
1049                    if previous_is_note && next_is_note {
1050                        if let Token::Note(note) = &mut self.tokens[index - 1] {
1051                            note.broken_rhythm = Some((symbol.clone(), true));
1052                        }
1053                        if let Token::Note(note) = &mut self.tokens[index + 1] {
1054                            note.broken_rhythm = Some((symbol, false));
1055                        }
1056                    }
1057                }
1058                Token::Tuplet { src } => {
1059                    let (made, count) = tuplet_of(&src, meter.as_ref())?;
1060                    tuplet = Some((made, count));
1061                    active_parens.push("Tuplet");
1062                }
1063                Token::SpannerStart(kind, _) => {
1064                    spanners.push(Spanning {
1065                        kind,
1066                        uids: Vec::new(),
1067                    });
1068                    let made = spanners.len() - 1;
1069                    self.tokens[index] = Token::SpannerStart(kind, Some(made));
1070                    active_spanners.push(made);
1071                    active_parens.push(match kind {
1072                        SpannerKind::Crescendo => "Crescendo",
1073                        SpannerKind::Diminuendo => "Diminuendo",
1074                        _ => "Slur",
1075                    });
1076                }
1077                Token::ParenStop => {
1078                    if let Some(closed) = active_parens.pop()
1079                        && closed != "Tuplet"
1080                    {
1081                        active_spanners.pop();
1082                    }
1083                }
1084                Token::Tie => {
1085                    if let Some(last) = last_note
1086                        && let Token::Note(note) = &mut self.tokens[last]
1087                    {
1088                        note.tie = Some(if note.tie == Some(TieType::Stop) {
1089                            TieType::Continue
1090                        } else {
1091                            TieType::Start
1092                        });
1093                    }
1094                    tie_waiting = true;
1095                }
1096                Token::Staccato => marks.push("staccato"),
1097                Token::Upbow => marks.push("upbow"),
1098                Token::Downbow => marks.push("downbow"),
1099                Token::Accent => marks.push("accent"),
1100                Token::Straccent => marks.push("strongaccent"),
1101                Token::Tenuto => marks.push("tenuto"),
1102                Token::GraceStart => in_grace = true,
1103                Token::GraceStop => in_grace = false,
1104                Token::Bar(_) => {}
1105                Token::Note(_) => {
1106                    let Some(default_length) = default_length else {
1107                        return Err(abc_error(
1108                            "no active default note length provided for note processing.",
1109                        ));
1110                    };
1111                    let Token::Note(note) = &mut self.tokens[index] else {
1112                        continue;
1113                    };
1114                    note.default_quarter_length = Some(default_length);
1115                    note.key = key.clone();
1116                    note.spanners = active_spanners.clone();
1117                    if std::mem::take(&mut tie_waiting) {
1118                        note.tie = Some(TieType::Stop);
1119                    }
1120                    // Each kind of mark once, in music21's order.
1121                    for mark in [
1122                        "staccato",
1123                        "upbow",
1124                        "downbow",
1125                        "accent",
1126                        "strongaccent",
1127                        "tenuto",
1128                    ] {
1129                        if marks.contains(&mark) {
1130                            note.articulations.push(mark);
1131                        }
1132                    }
1133                    marks.clear();
1134                    if in_grace {
1135                        note.in_grace = true;
1136                    }
1137                    match &mut tuplet {
1138                        None => {}
1139                        Some((_, 0)) => tuplet = None,
1140                        Some((made, count)) => {
1141                            *count -= 1;
1142                            note.tuplet = Some(*made);
1143                        }
1144                    }
1145                    last_note = Some(index);
1146                }
1147            }
1148        }
1149        for token in &mut self.tokens {
1150            if let Token::Note(note) = token {
1151                note.parse(None, None)?;
1152            }
1153        }
1154        Ok(spanners)
1155    }
1156
1157    /// music21's `definesReferenceNumbers`: more than one `X:`.
1158    fn defines_reference_numbers(&self) -> bool {
1159        self.tokens
1160            .iter()
1161            .filter(|token| token.metadata().is_some_and(|(tag, _)| tag == "X"))
1162            .count()
1163            > 1
1164    }
1165
1166    /// music21's `splitByReferenceNumber`, in order of the numbers.
1167    fn split_by_reference_number(&self) -> Vec<(IntegerType, Handler)> {
1168        let mut before: Vec<Token> = Vec::new();
1169        let mut tunes: Vec<(IntegerType, Vec<Token>)> = Vec::new();
1170        for token in &self.tokens {
1171            if let Some(("X", data)) = token.metadata() {
1172                let number = data.trim().parse::<IntegerType>().unwrap_or(0);
1173                tunes.retain(|(known, _)| *known != number);
1174                tunes.push((number, Vec::new()));
1175            }
1176            match tunes.last_mut() {
1177                Some((_, tokens)) => tokens.push(token.clone()),
1178                None => before.push(token.clone()),
1179            }
1180        }
1181        tunes.sort_by_key(|(number, _)| *number);
1182        tunes
1183            .into_iter()
1184            .map(|(number, tokens)| {
1185                let mut handler = Handler::new(self.version);
1186                handler.tokens = before.iter().cloned().chain(tokens).collect();
1187                (number, handler)
1188            })
1189            .collect()
1190    }
1191
1192    /// music21's `definesMeasures`: two plain barlines or more.
1193    fn defines_measures(&self) -> bool {
1194        self.tokens
1195            .iter()
1196            .filter(|token| matches!(token, Token::Bar(bar) if bar.is_regular()))
1197            .count()
1198            >= 2
1199    }
1200
1201    fn has_notes(tokens: &[Token]) -> bool {
1202        tokens.iter().any(Token::is_note)
1203    }
1204
1205    /// music21's `splitByVoice`: the header, and the tokens of each voice
1206    /// whose `V:` line starts with a digit.
1207    fn split_by_voice(&self) -> Vec<Vec<Token>> {
1208        let positions: Vec<usize> = self
1209            .tokens
1210            .iter()
1211            .enumerate()
1212            .filter(|(_, token)| {
1213                token.metadata().is_some_and(|(tag, data)| {
1214                    tag == "V" && data.chars().next().is_some_and(|c| c.is_ascii_digit())
1215                })
1216            })
1217            .map(|(index, _)| index)
1218            .collect();
1219        if positions.len() <= 1 {
1220            return vec![self.tokens.clone()];
1221        }
1222        let mut pieces = vec![self.tokens[..positions[0]].to_vec()];
1223        for pair in positions.windows(2) {
1224            pieces.push(self.tokens[pair[0]..pair[1]].to_vec());
1225        }
1226        pieces.push(self.tokens[positions[positions.len() - 1]..].to_vec());
1227        pieces
1228    }
1229}
1230
1231/// music21's `ABCTuplet.updateRatio` and `updateNoteCount`: the tuplet and
1232/// how many notes it takes.
1233fn tuplet_of(src: &str, meter: Option<&TimeSignature>) -> Result<(Tuplet, i32)> {
1234    let normal_switch = match meter {
1235        Some(meter) if meter.beat_division_count() == 3 => 3,
1236        _ => 2,
1237    };
1238    let pieces: Vec<&str> = src.trim().split(':').collect();
1239    let (actual, normal) = match pieces[0] {
1240        "(1" => (1, 1),
1241        "(2" => (2, 3),
1242        "(3" => (3, 2),
1243        "(4" => (4, 3),
1244        "(5" => (5, normal_switch),
1245        "(6" => (6, 2),
1246        "(7" => (7, normal_switch),
1247        "(8" => (8, 3),
1248        "(9" => (9, normal_switch),
1249        other => {
1250            return Err(abc_error(format!(
1251                "cannot handle tuplet of form: {other:?}"
1252            )));
1253        }
1254    };
1255    let read = |piece: Option<&&str>| piece.and_then(|piece| piece.parse::<u32>().ok());
1256    let normal = read(pieces.get(1)).unwrap_or(normal);
1257    let count = read(pieces.get(2)).unwrap_or(actual);
1258    Ok((Tuplet::ratio(actual, normal), count as i32))
1259}
1260
1261/// A bar's worth of tokens with the barlines either side: music21's
1262/// `ABCHandlerBar`.
1263#[derive(Clone, Debug, Default)]
1264struct BarHandler {
1265    tokens: Vec<Token>,
1266    left: Option<Bar>,
1267    right: Option<Bar>,
1268}
1269
1270impl BarHandler {
1271    /// music21's `ABCHandlerBar.__add__`.
1272    fn joined(&self, other: &BarHandler) -> BarHandler {
1273        BarHandler {
1274            tokens: self
1275                .tokens
1276                .iter()
1277                .cloned()
1278                .chain(other.tokens.iter().cloned())
1279                .collect(),
1280            left: other.left.clone().or_else(|| self.left.clone()),
1281            right: other.right.clone().or_else(|| self.right.clone()),
1282        }
1283    }
1284}
1285
1286/// music21's `splitByMeasure`.
1287fn split_by_measure(tokens: &[Token]) -> Vec<BarHandler> {
1288    // Where a bar stands, or a line of metadata a note follows.
1289    let mut positions: Vec<usize> = Vec::new();
1290    for (index, token) in tokens.iter().enumerate() {
1291        let note_follows = tokens.get(index + 1).is_some_and(Token::is_note);
1292        if matches!(token, Token::Bar(_)) || (token.metadata().is_some() && note_follows) {
1293            positions.push(index);
1294        }
1295    }
1296    if positions.is_empty() || tokens.is_empty() {
1297        return Vec::new();
1298    }
1299    let last_valid = tokens.len() - 1;
1300    let mut pairs: Vec<(usize, usize)> = vec![(0, positions[0])];
1301    let mut start = positions[0];
1302    for end in positions.iter().skip(1).copied() {
1303        // A span of one is passed over.
1304        if end == start + 1 {
1305            start = end;
1306            continue;
1307        }
1308        pairs.push((start, end));
1309        start = end;
1310    }
1311    if start != last_valid {
1312        pairs.push((start, last_valid));
1313    }
1314
1315    let mut handlers = Vec::new();
1316    for (x, y) in pairs {
1317        let mut handler = BarHandler::default();
1318        let mut from = x;
1319        let mut to = y;
1320        match &tokens[x] {
1321            Token::Bar(bar) => {
1322                // A repeat's end belongs to the measure before.
1323                if !(bar.repeat && bar.form == "end") {
1324                    handler.left = Some(bar.clone());
1325                }
1326                from = x + 1;
1327            }
1328            Token::Metadata { .. } if x != 0 => from = x + 1,
1329            _ => {}
1330        }
1331        match &tokens[y] {
1332            Token::Bar(bar) => {
1333                if !(bar.repeat && bar.form == "start") {
1334                    handler.right = Some(bar.clone());
1335                }
1336                to = y.wrapping_sub(1);
1337            }
1338            Token::Metadata { .. } => {}
1339            token => {
1340                if !(token.is_note() && y == tokens.len() - 1) {
1341                    to = y.wrapping_sub(1);
1342                }
1343            }
1344        }
1345        if to == usize::MAX || from > to {
1346            continue;
1347        }
1348        handler.tokens = tokens[from..=to].to_vec();
1349        if handler.tokens.is_empty() {
1350            continue;
1351        }
1352        handlers.push(handler);
1353    }
1354    handlers
1355}
1356
1357/// music21's `mergeLeadingMetaData`: a handler of nothing but metadata is
1358/// joined to the one after it, and a tune of one measure is one handler.
1359fn merge_leading_metadata(handlers: Vec<BarHandler>) -> Vec<BarHandler> {
1360    let sounding = handlers
1361        .iter()
1362        .filter(|handler| Handler::has_notes(&handler.tokens))
1363        .count();
1364    if sounding <= 1 {
1365        let mut whole = BarHandler::default();
1366        for handler in &handlers {
1367            whole = whole.joined(handler);
1368        }
1369        return vec![whole];
1370    }
1371    let mut merged = Vec::new();
1372    let mut index = 0;
1373    while index < handlers.len() {
1374        let silent = !Handler::has_notes(&handlers[index].tokens);
1375        if silent && index != handlers.len() - 1 {
1376            merged.push(handlers[index].joined(&handlers[index + 1]));
1377            index += 2;
1378        } else {
1379            merged.push(handlers[index].clone());
1380            index += 1;
1381        }
1382    }
1383    merged
1384}
1385
1386// --------------------------------------------------------------- translate
1387
1388/// One element with where it stands and the order it was put in.
1389#[derive(Clone, Debug)]
1390struct Item {
1391    offset: FloatType,
1392    seq: usize,
1393    uid: Option<usize>,
1394    element: StreamElement,
1395}
1396
1397/// A measure or a part while it is being filled: what it holds, and where
1398/// the next thing appended goes.
1399#[derive(Clone, Debug, Default)]
1400struct Line {
1401    items: Vec<Item>,
1402    end: FloatType,
1403    seq: usize,
1404}
1405
1406impl Line {
1407    /// music21's `coreAppend`.
1408    fn append(&mut self, element: impl Into<StreamElement>, uid: Option<usize>) {
1409        let element = element.into();
1410        let length = element.quarter_length();
1411        self.items.push(Item {
1412            offset: self.end,
1413            seq: self.seq,
1414            uid,
1415            element,
1416        });
1417        self.seq += 1;
1418        self.end = op_frac(self.end + length);
1419    }
1420
1421    /// A signature or a clef put at the start in place of the one there,
1422    /// as music21's `measure.timeSignature = ...` does.
1423    fn set_at_start(&mut self, element: StreamElement) {
1424        let same = |held: &StreamElement| {
1425            matches!(
1426                (held, &element),
1427                (
1428                    StreamElement::TimeSignature(_),
1429                    StreamElement::TimeSignature(_)
1430                ) | (StreamElement::Clef(_), StreamElement::Clef(_))
1431                    | (
1432                        StreamElement::KeySignature(_) | StreamElement::Key(_),
1433                        StreamElement::KeySignature(_) | StreamElement::Key(_)
1434                    )
1435            )
1436        };
1437        self.items.retain(|item| !same(&item.element));
1438        self.items.push(Item {
1439            offset: 0.0,
1440            seq: self.seq,
1441            uid: None,
1442            element,
1443        });
1444        self.seq += 1;
1445    }
1446
1447    fn meter(&self) -> Option<&TimeSignature> {
1448        self.items.iter().find_map(|item| match &item.element {
1449            StreamElement::TimeSignature(meter) => Some(meter),
1450            _ => None,
1451        })
1452    }
1453
1454    /// The elements in the order music21 sorts a stream into.
1455    fn sorted(&self) -> Vec<&Item> {
1456        let mut sorted: Vec<&Item> = self.items.iter().collect();
1457        sorted.sort_by(|left, right| {
1458            let grace = |item: &Item| item.element.duration().is_some_and(Duration::is_grace);
1459            left.offset
1460                .total_cmp(&right.offset)
1461                .then(class_sort_order(&left.element).cmp(&class_sort_order(&right.element)))
1462                .then(grace(right).cmp(&grace(left)))
1463                .then(left.seq.cmp(&right.seq))
1464        });
1465        sorted
1466    }
1467}
1468
1469/// music21's `classSortOrder`.
1470pub(super) fn class_sort_order(element: &StreamElement) -> i32 {
1471    match element {
1472        StreamElement::TextExpression(_) => -30,
1473        StreamElement::Instrument(_) => -25,
1474        StreamElement::Stream(_) => -20,
1475        StreamElement::Clef(_) => 0,
1476        StreamElement::MetronomeMark(_) | StreamElement::TempoText(_) => 1,
1477        StreamElement::KeySignature(_) | StreamElement::Key(_) => 2,
1478        StreamElement::TimeSignature(_) => 4,
1479        StreamElement::Dynamic(_) => 10,
1480        StreamElement::ChordSymbol(_) => 19,
1481        _ => 20,
1482    }
1483}
1484
1485#[derive(Clone, Debug, Default)]
1486struct MeasureIr {
1487    line: Line,
1488    number: IntegerType,
1489    left: Option<Barline>,
1490    right: Option<Barline>,
1491    padding_left: FloatType,
1492}
1493
1494/// An ending while its measures are being met.
1495#[derive(Clone, Debug)]
1496struct Bracket {
1497    number: u32,
1498    measures: Vec<usize>,
1499    complete: bool,
1500}
1501
1502/// What reading one voice keeps between its measures.
1503struct PartReader {
1504    spanners: Vec<Spanning>,
1505    next_uid: usize,
1506    /// The notes a line of words is sung to, by measure and place.
1507    lyric_targets: Vec<(Option<usize>, usize)>,
1508    post_transposition: IntegerType,
1509}
1510
1511impl PartReader {
1512    fn uid(&mut self) -> usize {
1513        self.next_uid += 1;
1514        self.next_uid
1515    }
1516}
1517
1518/// music21's `addABCLyrics`: the words of a `w:` line, shared out among the
1519/// notes since the line before.
1520fn add_lyrics(data: &str, targets: &mut [&mut StreamElement]) -> Result<()> {
1521    let mut at = 0usize;
1522    for word in data.split_whitespace() {
1523        if word == "*" || word == "-" {
1524            at += 1;
1525            continue;
1526        }
1527        let syllables: Vec<&str> = word.split('-').collect();
1528        for (index, syllable) in syllables.iter().enumerate() {
1529            if syllable.is_empty() {
1530                at += 1;
1531                continue;
1532            }
1533            let Some(target) = targets.get_mut(at) else {
1534                return Ok(());
1535            };
1536            let text = format!(
1537                "{}{syllable}{}",
1538                if index > 0 { "-" } else { "" },
1539                if index + 1 < syllables.len() { "-" } else { "" }
1540            );
1541            match target {
1542                StreamElement::Note(note) => note.add_lyric(&text, None, false)?,
1543                StreamElement::Chord(chord) => chord.add_lyric(&text, None, false)?,
1544                _ => {}
1545            }
1546            at += 1;
1547        }
1548    }
1549    Ok(())
1550}
1551
1552/// An element and the number spanners know it by.
1553type Placed = (StreamElement, Option<usize>);
1554
1555/// music21's `parseABCNote`: the note, chord or rest a token stands for,
1556/// after the chord symbol written over it.
1557fn note_elements(
1558    token: &AbcNote,
1559    reader: &mut PartReader,
1560) -> Result<(Option<ChordSymbol>, Option<Placed>)> {
1561    let mut symbol = None;
1562    if let Some(first) = token.chord_symbols.first() {
1563        let mut name: String = first.replace('"', "").trim().to_string();
1564        name = name.replace(['(', ')'], "");
1565        // A flat written `b` after a note letter is music21's `-`.
1566        let chars: Vec<char> = name.chars().collect();
1567        let mut cleaned = String::new();
1568        for (index, character) in chars.iter().enumerate() {
1569            let after_letter = index > 0 && matches!(chars[index - 1], 'A'..='G' | 'a'..='g');
1570            cleaned.push(if *character == 'b' && after_letter {
1571                '-'
1572            } else {
1573                *character
1574            });
1575        }
1576        if matches!(cleaned.as_str(), "NC" | "N.C." | "No Chord" | "None") {
1577            symbol = Some(ChordSymbol::no_chord(Some(cleaned)));
1578        } else if cleaned.starts_with('>') {
1579            return Ok((None, None));
1580        } else if let Ok(read) = ChordSymbol::parse_music21(cleaned) {
1581            symbol = Some(read);
1582        }
1583    }
1584
1585    let with_tuplet = |duration: &mut Duration, tuplet: Option<Tuplet>| {
1586        if let Some(mut tuplet) = tuplet {
1587            if tuplet.duration_normal().is_none()
1588                && let Some((kind, dots)) = duration.type_and_dots()
1589            {
1590                tuplet.set_duration_type(kind, dots);
1591            }
1592            duration.append_tuplet(tuplet);
1593        }
1594    };
1595
1596    if token.is_chord {
1597        if token.sub_tokens.is_empty() {
1598            return Ok((symbol, None));
1599        }
1600        let mut members = Vec::new();
1601        for sub in &token.sub_tokens {
1602            let Some(name) = &sub.pitch_name else {
1603                continue;
1604            };
1605            let mut pitch = Pitch::from_name(name)?;
1606            if let Some(accidental) = pitch.written_accidental_mut() {
1607                accidental.set_display_status(sub.accidental_display);
1608            }
1609            members.push(Note::from_pitch(pitch));
1610        }
1611        let mut duration = Duration::new(token.quarter_length)?;
1612        with_tuplet(&mut duration, token.tuplet);
1613        let chord = Chord::new(members)?.with_duration(duration);
1614        let uid = reader.uid();
1615        return Ok((symbol, Some((chord.into(), Some(uid)))));
1616    }
1617
1618    let mut duration = Duration::new(token.quarter_length)?;
1619    with_tuplet(&mut duration, token.tuplet);
1620    if token.is_rest {
1621        let uid = reader.uid();
1622        for spanner in &token.spanners {
1623            reader.spanners[*spanner].uids.push(uid);
1624        }
1625        let duration = if token.in_grace {
1626            grace_of(&duration)
1627        } else {
1628            duration
1629        };
1630        // A grace rest is a copy made after the spanners took the first.
1631        let placed = if token.in_grace { reader.uid() } else { uid };
1632        let mut rest = Rest::new(duration);
1633        rest.set_tie(tie_of(token.tie));
1634        *rest.articulations_mut() = articulations_of(&token.articulations);
1635        return Ok((symbol, Some((rest.into(), Some(placed)))));
1636    }
1637    let name = token
1638        .pitch_name
1639        .as_deref()
1640        .ok_or_else(|| abc_error("a note with no pitch"))?;
1641    let mut pitch = Pitch::from_name(name)?;
1642    if let Some(accidental) = pitch.written_accidental_mut() {
1643        accidental.set_display_status(token.accidental_display);
1644    }
1645    let mut note = Note::from_pitch(pitch);
1646    note.set_tie(tie_of(token.tie));
1647    let uid = reader.uid();
1648    for spanner in &token.spanners {
1649        if !reader.spanners[*spanner].uids.contains(&uid) {
1650            reader.spanners[*spanner].uids.push(uid);
1651        }
1652    }
1653    // A grace note is a copy made after the spanners took the note itself,
1654    // which no stream then holds.
1655    let placed = if token.in_grace {
1656        duration = grace_of(&duration);
1657        reader.uid()
1658    } else {
1659        uid
1660    };
1661    note.set_duration(duration);
1662    *note.articulations_mut() = articulations_of(&token.articulations);
1663    Ok((symbol, Some((note.into(), Some(placed)))))
1664}
1665
1666/// The tie a token asks for, on a note or a rest alike.
1667fn tie_of(tie: Option<TieType>) -> Option<Tie> {
1668    match tie? {
1669        tie_type @ (TieType::Start | TieType::Continue) => {
1670            let mut tie = Tie::new(tie_type);
1671            tie.set_style(TieStyle::Normal);
1672            Some(tie)
1673        }
1674        tie_type => Some(Tie::new(tie_type)),
1675    }
1676}
1677
1678/// The marks a token carries, last written first: music21 pops them off
1679/// the end of its list.
1680fn articulations_of(marks: &[&'static str]) -> Vec<Articulation> {
1681    marks
1682        .iter()
1683        .rev()
1684        .filter_map(|mark| {
1685            let class = match *mark {
1686                "staccato" => "Staccato",
1687                "upbow" => "UpBow",
1688                "downbow" => "DownBow",
1689                "accent" => "Accent",
1690                "strongaccent" => "StrongAccent",
1691                "tenuto" => "Tenuto",
1692                _ => return None,
1693            };
1694            ArticulationKind::from_class_name(class).map(Articulation::of_kind)
1695        })
1696        .collect()
1697}
1698
1699/// A length as a grace note's: the written value, lasting nothing and in no
1700/// tuplet, whatever bracket the note was written inside.
1701fn grace_of(duration: &Duration) -> Duration {
1702    duration.grace_duration()
1703}
1704
1705/// music21's `abcToStreamPart`: one voice as a part, with the spanners it
1706/// holds, each naming its notes by the numbers the part's leaves carry.
1707fn part_of(
1708    tokens: &[Token],
1709    spanners: &[Spanning],
1710) -> Result<(Stream, Vec<Option<usize>>, Vec<Spanning>)> {
1711    let handler = Handler {
1712        version: DEFAULT_VERSION,
1713        directives: Vec::new(),
1714        tokens: tokens.to_vec(),
1715    };
1716    let merged: Vec<BarHandler> = if handler.defines_measures() {
1717        merge_leading_metadata(split_by_measure(tokens))
1718    } else {
1719        vec![BarHandler {
1720            tokens: tokens.to_vec(),
1721            ..BarHandler::default()
1722        }]
1723    };
1724    let use_measures = merged.len() > 1;
1725
1726    let mut reader = PartReader {
1727        spanners: spanners.to_vec(),
1728        next_uid: 0,
1729        lyric_targets: Vec::new(),
1730        post_transposition: 0,
1731    };
1732    // Which of the handler's spanners this voice starts, in order.
1733    let mut started: Vec<usize> = Vec::new();
1734    let mut part = Line::default();
1735    let mut measures: Vec<MeasureIr> = Vec::new();
1736    let mut brackets: Vec<Bracket> = Vec::new();
1737    let mut bar_count = 0;
1738    let mut measure_number = 1;
1739
1740    for handler in &merged {
1741        let in_measure = use_measures && Handler::has_notes(&handler.tokens);
1742        let mut measure = MeasureIr::default();
1743        if in_measure {
1744            let index = measures.len();
1745            if let Some(left) = &handler.left {
1746                measure.left = left.barline();
1747                if let Some(number) = left.repeat_bracket() {
1748                    match brackets.iter_mut().find(|bracket| !bracket.complete) {
1749                        None => brackets.push(Bracket {
1750                            number,
1751                            measures: vec![index],
1752                            complete: number == 2,
1753                        }),
1754                        Some(open) => {
1755                            if !open.measures.contains(&index) {
1756                                open.measures.push(index);
1757                            }
1758                            open.complete = true;
1759                        }
1760                    }
1761                }
1762            }
1763            if let Some(right) = &handler.right {
1764                // A repeat closing a measure ends the passage.
1765                measure.right = right.barline().map(|barline| {
1766                    if barline.repeat_direction() == Some(RepeatDirection::Start) {
1767                        Barline::repeat(RepeatDirection::End, None)
1768                    } else {
1769                        barline
1770                    }
1771                });
1772                if right.repeat
1773                    && let Some(open) = brackets.iter_mut().find(|bracket| !bracket.complete)
1774                {
1775                    if !open.measures.contains(&index) {
1776                        open.measures.push(index);
1777                    }
1778                    open.complete = true;
1779                }
1780            }
1781            bar_count += 1;
1782        }
1783
1784        // music21's `parseTokens`.
1785        reader.post_transposition = 0;
1786        let place = in_measure.then_some(measures.len());
1787        {
1788            let line = if in_measure {
1789                &mut measure.line
1790            } else {
1791                &mut part
1792            };
1793            for token in &handler.tokens {
1794                match token {
1795                    Token::Metadata { tag, data } => {
1796                        if tag == "w" {
1797                            let wanted = std::mem::take(&mut reader.lyric_targets);
1798                            let mut targets: Vec<&mut StreamElement> = Vec::new();
1799                            // Notes of this line only; those of measures
1800                            // already closed are reached below.
1801                            let mut here: Vec<usize> = wanted
1802                                .iter()
1803                                .filter(|(held, _)| *held == place)
1804                                .map(|(_, index)| *index)
1805                                .collect();
1806                            here.sort_unstable();
1807                            let outside = wanted.iter().any(|(held, _)| *held != place);
1808                            if !outside {
1809                                let mut rest: &mut [Item] = &mut line.items;
1810                                let mut passed = 0;
1811                                for index in here {
1812                                    let (_, tail) = rest.split_at_mut(index - passed);
1813                                    let (item, tail) = tail
1814                                        .split_first_mut()
1815                                        .ok_or_else(|| abc_error("a lyric's note is missing"))?;
1816                                    targets.push(&mut item.element);
1817                                    rest = tail;
1818                                    passed = index + 1;
1819                                }
1820                                add_lyrics(data, &mut targets)?;
1821                            } else {
1822                                add_lyrics_across(data, &wanted, &mut measures, line, place)?;
1823                            }
1824                        }
1825                        match tag.as_str() {
1826                            "M" => {
1827                                if let Some(meter) = meter_of(data)? {
1828                                    if use_measures {
1829                                        line.set_at_start(meter.into());
1830                                    } else {
1831                                        line.append(meter, None);
1832                                    }
1833                                }
1834                            }
1835                            "K" => {
1836                                let key = key_of(data)?;
1837                                if use_measures {
1838                                    line.set_at_start(key);
1839                                } else {
1840                                    line.append(key, None);
1841                                }
1842                                if let Some((clef, transposition)) = clef_of(data) {
1843                                    if use_measures {
1844                                        line.set_at_start(clef.into());
1845                                    } else {
1846                                        line.append(clef, None);
1847                                    }
1848                                    reader.post_transposition = transposition;
1849                                }
1850                            }
1851                            "Q" => line.append(tempo_of(data)?, None),
1852                            _ => {}
1853                        }
1854                    }
1855                    Token::Note(note) => {
1856                        let (symbol, made) = note_elements(note, &mut reader)?;
1857                        if let Some(symbol) = symbol {
1858                            line.append(symbol, None);
1859                        }
1860                        if let Some((element, uid)) = made {
1861                            let sung = !matches!(element, StreamElement::Rest(_)) && !note.in_grace;
1862                            line.append(element, uid);
1863                            if sung {
1864                                reader.lyric_targets.push((place, line.items.len() - 1));
1865                            }
1866                        }
1867                    }
1868                    Token::SpannerStart(_, Some(index)) => started.push(*index),
1869                    _ => {}
1870                }
1871            }
1872        }
1873
1874        if in_measure {
1875            if bar_count == 1
1876                && let Some(meter) = measure.line.meter()
1877            {
1878                // A short first measure is a pickup, numbered nought.
1879                let bar = meter.bar_quarter_length();
1880                let highest = measure_stream(&measure.line).end_offset();
1881                if highest < bar {
1882                    measure.padding_left = bar - highest;
1883                }
1884                measure.number = 0;
1885            } else {
1886                measure.number = measure_number;
1887                measure_number += 1;
1888            }
1889            // Lyric targets name a measure by its place among them.
1890            measures.push(measure);
1891        }
1892    }
1893
1894    re_bar(&mut measures, &mut brackets);
1895
1896    // Endings, from the brackets over the measures.
1897    let mut endings: Vec<Option<Ending>> = vec![None; measures.len()];
1898    // An ending never closed is left out, as music21 leaves it.
1899    for bracket in brackets.iter().filter(|bracket| bracket.complete) {
1900        for (place, index) in bracket.measures.iter().enumerate() {
1901            if let Some(slot) = endings.get_mut(*index)
1902                && slot.is_none()
1903            {
1904                *slot = Some(Ending::new(
1905                    vec![bracket.number],
1906                    place == 0,
1907                    place + 1 == bracket.measures.len(),
1908                ));
1909            }
1910        }
1911    }
1912
1913    // A part with no clef takes the one that fits its notes best.
1914    let has_clef = measures
1915        .iter()
1916        .flat_map(|measure| &measure.line.items)
1917        .chain(&part.items)
1918        .any(|item| matches!(item.element, StreamElement::Clef(_)));
1919    if !has_clef {
1920        let mut pitches: Vec<Pitch> = Vec::new();
1921        for item in measures
1922            .iter()
1923            .flat_map(|measure| measure.line.sorted())
1924            .chain(part.sorted())
1925        {
1926            match &item.element {
1927                StreamElement::Note(note) => pitches.push(note.pitch().clone()),
1928                StreamElement::Chord(chord) => pitches.extend(chord.pitches()),
1929                StreamElement::ChordSymbol(symbol) => {
1930                    pitches.extend(symbol.pitches().unwrap_or_default());
1931                }
1932                _ => {}
1933            }
1934        }
1935        let clef = Clef::best_for(&pitches, false);
1936        match measures.first_mut() {
1937            Some(first) if use_measures => first.line.set_at_start(clef.into()),
1938            _ => {
1939                part.items.push(Item {
1940                    offset: 0.0,
1941                    seq: part.seq,
1942                    uid: None,
1943                    element: clef.into(),
1944                });
1945                part.seq += 1;
1946            }
1947        }
1948    }
1949
1950    if reader.post_transposition != 0 {
1951        // music21 transposes by a count of semitones, which spells each
1952        // note afresh from where it lands and decides nothing about how its
1953        // accidental is shown.
1954        let interval = Interval::from_semitones(reader.post_transposition)?;
1955        for item in measures
1956            .iter_mut()
1957            .flat_map(|measure| &mut measure.line.items)
1958            .chain(&mut part.items)
1959        {
1960            if item.element.is_note_or_chord() {
1961                item.element = item.element.transpose(&interval)?;
1962            }
1963        }
1964    }
1965
1966    // Put together: the measures one after another, or the part's own line.
1967    let mut uids: Vec<Option<usize>> = Vec::new();
1968    let mut events = Vec::new();
1969    let mut offset = 0.0;
1970    let has_meter = part.meter().is_some()
1971        || measures
1972            .iter()
1973            .any(|measure| measure.line.meter().is_some());
1974    for (index, measure) in measures.into_iter().enumerate() {
1975        let mut inner = Vec::new();
1976        for item in measure.line.sorted() {
1977            uids.push(item.uid);
1978            inner.push(StreamEvent::new(item.offset, item.element.clone()));
1979        }
1980        let mut stream = Stream::from_events(inner);
1981        stream.set_kind(StreamKind::Measure);
1982        stream.set_number(measure.number);
1983        stream.set_left_barline(measure.left);
1984        stream.set_right_barline(measure.right);
1985        stream.set_ending(endings[index].clone());
1986        stream.set_padding_left(measure.padding_left);
1987        let length = measure.line.end;
1988        events.push(StreamEvent::new(offset, stream));
1989        offset = op_frac(offset + length);
1990    }
1991    for item in part.sorted() {
1992        uids.push(item.uid);
1993        events.push(StreamEvent::new(item.offset, item.element.clone()));
1994    }
1995    let mut stream = Stream::from_events(events);
1996    stream.set_kind(StreamKind::Part);
1997
1998    if use_measures && has_meter {
1999        // music21 warns and carries on where a measure cannot be beamed.
2000        let _ = crate::makenotation::make_beams(&mut stream);
2001    }
2002
2003    let held: Vec<Spanning> = started
2004        .into_iter()
2005        .map(|index| reader.spanners[index].clone())
2006        .collect();
2007    Ok((stream, uids, held))
2008}
2009
2010/// Words sung to notes of measures already closed as well as this one.
2011fn add_lyrics_across(
2012    data: &str,
2013    wanted: &[(Option<usize>, usize)],
2014    measures: &mut [MeasureIr],
2015    line: &mut Line,
2016    place: Option<usize>,
2017) -> Result<()> {
2018    // One mutable borrow per note: each is reached in turn by where it is.
2019    let mut elements: Vec<StreamElement> = Vec::new();
2020    for (held, index) in wanted {
2021        let item = if *held == place {
2022            line.items.get(*index)
2023        } else {
2024            held.and_then(|measure| measures.get(measure))
2025                .and_then(|measure| measure.line.items.get(*index))
2026        };
2027        elements.push(
2028            item.map(|item| item.element.clone())
2029                .ok_or_else(|| abc_error("a lyric's note is missing"))?,
2030        );
2031    }
2032    {
2033        let mut targets: Vec<&mut StreamElement> = elements.iter_mut().collect();
2034        add_lyrics(data, &mut targets)?;
2035    }
2036    for ((held, index), element) in wanted.iter().zip(elements) {
2037        let slot = if *held == place {
2038            line.items.get_mut(*index)
2039        } else {
2040            held.and_then(|measure| measures.get_mut(measure))
2041                .and_then(|measure| measure.line.items.get_mut(*index))
2042        };
2043        if let Some(slot) = slot {
2044            slot.element = element;
2045        }
2046    }
2047    Ok(())
2048}
2049
2050/// A line as the measure it will be, for the questions asked of a stream.
2051fn measure_stream(line: &Line) -> Stream {
2052    let mut stream = Stream::from_events(
2053        line.sorted()
2054            .into_iter()
2055            .map(|item| StreamEvent::new(item.offset, item.element.clone())),
2056    );
2057    stream.set_kind(StreamKind::Measure);
2058    stream
2059}
2060
2061/// music21's `reBar`: a measure holding more than its bar is cut in two, the
2062/// second taking the meter that fits it where it is not a whole bar, and
2063/// every later measure is numbered one further on.
2064///
2065/// An overflow no meter fits is kept as a measure stating none. music21
2066/// gives up where it stands on a measure with no meter in force, or one it
2067/// cannot cut, keeping what it had done.
2068fn re_bar(measures: &mut Vec<MeasureIr>, brackets: &mut [Bracket]) {
2069    let mut meter: Option<TimeSignature> = None;
2070    let mut shift = 0;
2071    // Where each measure read stands once the cut ones are in.
2072    let mut places: Vec<usize> = (0..measures.len()).collect();
2073    let mut index = 0;
2074    let mut original = 0;
2075    let count = measures.len();
2076    'measures: while original < count {
2077        if let Some(own) = measures[index].line.meter() {
2078            meter = Some(own.clone());
2079        }
2080        let Some(current) = meter.clone() else {
2081            break;
2082        };
2083        places[original] = index;
2084        let bar = op_frac(current.bar_quarter_length());
2085        let end = measures[index].line.end;
2086        measures[index].number += shift;
2087        if end > bar + 1e-9 {
2088            let mut second = Line::default();
2089            let mut kept: Vec<Item> = Vec::new();
2090            let mut moved: Vec<Item> = Vec::new();
2091            let items = std::mem::take(&mut measures[index].line.items);
2092            let mut broken = false;
2093            for item in items {
2094                let length = item.element.quarter_length();
2095                if (item.offset - bar).abs() <= 1e-9 && length == 0.0 {
2096                    // Something with no length standing on the barline ends
2097                    // where the new measure starts, and stays behind.
2098                    kept.push(item);
2099                } else if item.offset >= bar - 1e-9 {
2100                    moved.push(item);
2101                } else if item.offset + length > bar + 1e-9 {
2102                    match split_element(&item.element, op_frac(bar - item.offset)) {
2103                        Ok((first, remain)) => {
2104                            second.items.push(Item {
2105                                offset: 0.0,
2106                                seq: second.seq,
2107                                uid: None,
2108                                element: remain,
2109                            });
2110                            second.seq += 1;
2111                            kept.push(Item {
2112                                element: first,
2113                                ..item
2114                            });
2115                        }
2116                        Err(_) => {
2117                            broken = true;
2118                            kept.push(item);
2119                        }
2120                    }
2121                } else {
2122                    kept.push(item);
2123                }
2124            }
2125            measures[index].line.items = kept;
2126            measures[index].line.end = bar;
2127            if broken {
2128                break 'measures;
2129            }
2130            for item in moved {
2131                second.items.push(Item {
2132                    offset: op_frac(item.offset - bar),
2133                    seq: second.seq,
2134                    ..item
2135                });
2136                second.seq += 1;
2137            }
2138            second.end = op_frac(end - bar);
2139            if (bar - second.end).abs() > 1e-9
2140                && let Ok(best) = crate::meter::best_time_signature(&measure_stream(&second))
2141            {
2142                second.set_at_start(best.into());
2143                if original + 1 < count && measures[index + 1].line.meter().is_none() {
2144                    // music21 puts the very meter object back, so it stands
2145                    // in two measures at once.
2146                    let mut again = current.clone();
2147                    again.set_restated(true);
2148                    measures[index + 1].line.set_at_start(again.into());
2149                }
2150            }
2151            let number = measures[index].number + 1;
2152            shift += 1;
2153            // The barline closing the measure closes the new one.
2154            let right = measures[index].right.take();
2155            measures.insert(
2156                index + 1,
2157                MeasureIr {
2158                    line: second,
2159                    number,
2160                    left: None,
2161                    right,
2162                    padding_left: 0.0,
2163                },
2164            );
2165            index += 1;
2166        }
2167        index += 1;
2168        original += 1;
2169    }
2170    for (passed, place) in places.iter_mut().skip(original).enumerate() {
2171        *place = index + passed;
2172    }
2173    for bracket in brackets {
2174        for measure in &mut bracket.measures {
2175            *measure = places[*measure];
2176        }
2177    }
2178}
2179
2180/// music21's `abcToStreamScore`.
2181fn score_of(handler: &Handler, spanners: &[Spanning]) -> Result<Stream> {
2182    let mut metadata = Metadata::new();
2183    let mut titles = 0;
2184    for token in &handler.tokens {
2185        let Some((tag, data)) = token.metadata() else {
2186            continue;
2187        };
2188        match tag {
2189            "T" => {
2190                metadata.add_text(
2191                    if titles == 0 {
2192                        "title"
2193                    } else {
2194                        "alternativeTitle"
2195                    },
2196                    data,
2197                );
2198                titles += 1;
2199            }
2200            "C" => metadata.add_contributor("composer", data),
2201            "O" => metadata.add_text("localeOfComposition", data),
2202            "X" => {
2203                let number = data.trim().parse::<IntegerType>().map_err(|_| {
2204                    abc_error(format!("the reference number {data:?} is no number"))
2205                })?;
2206                metadata.add_text("number", number.to_string());
2207            }
2208            _ => {}
2209        }
2210    }
2211
2212    let voices = handler.split_by_voice();
2213    let parts: Vec<Vec<Token>> = if voices.len() == 1 {
2214        voices
2215    } else {
2216        // The header goes in front of each voice.
2217        voices[1..]
2218            .iter()
2219            .map(|voice| {
2220                voices[0]
2221                    .iter()
2222                    .cloned()
2223                    .chain(voice.iter().cloned())
2224                    .collect()
2225            })
2226            .collect()
2227    };
2228
2229    let mut events = Vec::new();
2230    let mut uids: Vec<Option<(usize, usize)>> = Vec::new();
2231    let mut held: Vec<(usize, Spanning)> = Vec::new();
2232    for (index, tokens) in parts.iter().enumerate() {
2233        let (part, part_uids, part_spanners) = part_of(tokens, spanners)?;
2234        uids.extend(part_uids.into_iter().map(|uid| uid.map(|uid| (index, uid))));
2235        held.extend(part_spanners.into_iter().map(|spanner| (index, spanner)));
2236        events.push(StreamEvent::new(0.0, part));
2237    }
2238    let mut score = Stream::from_events(events);
2239    score.set_kind(StreamKind::Score);
2240    score.set_metadata(Some(metadata));
2241    for (part, spanner) in held {
2242        let positions: Vec<Option<usize>> = spanner
2243            .uids
2244            .iter()
2245            .map(|uid| uids.iter().position(|held| *held == Some((part, *uid))))
2246            .collect();
2247        let made = match spanner.kind {
2248            SpannerKind::Crescendo | SpannerKind::Diminuendo => {
2249                let template = Spanner::wedge(spanner.kind, Vec::new());
2250                let mut wedge = Spanner::with_unplaced(spanner.kind, positions);
2251                wedge.set_placement(template.placement());
2252                wedge.set_spread(template.spread());
2253                wedge
2254            }
2255            kind => Spanner::with_unplaced(kind, positions),
2256        };
2257        score.add_spanner(made);
2258    }
2259    Ok(score)
2260}
2261
2262/// music21's `extractReferenceNumber`: the lines of one tune.
2263fn extract_reference_number(text: &str, number: IntegerType) -> Result<String> {
2264    let mut collected = Vec::new();
2265    let mut gathering = false;
2266    for line in text.split('\n') {
2267        let starts = line.trim().starts_with("X:");
2268        if starts && !gathering {
2269            let named = line.replace(' ', "");
2270            let named = named.trim_end().trim_start_matches("X:");
2271            if named.parse::<IntegerType>() == Ok(number) {
2272                gathering = true;
2273            }
2274        } else if starts && gathering {
2275            break;
2276        }
2277        if gathering {
2278            collected.push(line);
2279        }
2280    }
2281    if collected.is_empty() {
2282        return Err(abc_error(format!(
2283            "cannot find requested reference number in source file: {number}"
2284        )));
2285    }
2286    Ok(collected.join("\n"))
2287}
2288
2289fn handler_of(text: &str) -> Result<(Handler, Vec<Spanning>)> {
2290    let mut handler = Handler::new(DEFAULT_VERSION);
2291    handler.read_version(text);
2292    handler.tokenize(text)?;
2293    let spanners = handler.process()?;
2294    Ok((handler, spanners))
2295}
2296
2297/// Reads ABC text into a score: music21's `converter.parse` for the format.
2298///
2299/// A file holding one tune comes back as a score, with a part for each of
2300/// its voices. A file holding several tunes, each under its own `X:`
2301/// reference number, comes back as an opus of scores in the order of their
2302/// numbers.
2303///
2304/// ```
2305/// use music21_rs::abc::from_abc;
2306///
2307/// let score = from_abc("X:1\nT:Scale\nM:4/4\nL:1/4\nK:G\nG A B c | d e f g |\n")?;
2308/// let part = score.parts()[0];
2309/// assert_eq!(part.measures().len(), 2);
2310/// // The key's F sharp is read into the note.
2311/// assert_eq!(part.measures()[1].pitches()[2].name_with_octave(), "F#5");
2312/// # Ok::<(), music21_rs::Error>(())
2313/// ```
2314pub fn from_abc(text: &str) -> Result<Stream> {
2315    let (handler, spanners) = handler_of(text)?;
2316    if handler.defines_reference_numbers() {
2317        let mut events = Vec::new();
2318        let mut offset = 0.0;
2319        for (_, tune) in handler.split_by_reference_number() {
2320            let score = score_of(&tune, &spanners)?;
2321            let length = score.end_offset();
2322            events.push(StreamEvent::new(offset, score));
2323            offset += length;
2324        }
2325        let mut opus = Stream::from_events(events);
2326        opus.set_kind(StreamKind::Opus);
2327        return Ok(opus);
2328    }
2329    score_of(&handler, &spanners)
2330}
2331
2332/// Reads one tune out of ABC text holding several, by its `X:` reference
2333/// number: music21's `converter.parse(..., number=n)`.
2334pub fn from_abc_number(text: &str, number: IntegerType) -> Result<Stream> {
2335    let (handler, spanners) = handler_of(&extract_reference_number(text, number)?)?;
2336    score_of(&handler, &spanners)
2337}
2338
2339#[cfg(test)]
2340mod tests {
2341    use super::*;
2342
2343    fn tokens_of(text: &str) -> Vec<Token> {
2344        let mut handler = Handler::new(DEFAULT_VERSION);
2345        handler.tokenize(text).unwrap();
2346        handler.tokens
2347    }
2348
2349    #[test]
2350    fn a_bar_says_what_it_is() {
2351        // music21's `ABCBar.parse` docstring.
2352        let bar = Bar::new("|");
2353        assert!(bar.is_regular() && !bar.repeat);
2354        let end = Bar::new(":|");
2355        assert!(end.repeat && end.form == "end" && end.style == "light-heavy");
2356        let first = Bar::new("[1");
2357        assert_eq!(first.repeat_bracket(), Some(1));
2358        assert_eq!(
2359            Bar::new("||").barline().unwrap().bar_type(),
2360            BarlineType::Double
2361        );
2362    }
2363
2364    #[test]
2365    fn text_is_cut_into_tokens_as_music21_cuts_it() {
2366        let tokens = tokens_of("M:6/8\nL:1/8\nK:G\nB3 A3 | (3GAB c2 :|\n");
2367        let kinds: Vec<&str> = tokens
2368            .iter()
2369            .map(|token| match token {
2370                Token::Metadata { .. } => "meta",
2371                Token::Bar(_) => "bar",
2372                Token::Tuplet { .. } => "tuplet",
2373                Token::Note(_) => "note",
2374                _ => "other",
2375            })
2376            .collect();
2377        assert_eq!(
2378            kinds,
2379            [
2380                "meta", "meta", "meta", "note", "note", "bar", "tuplet", "note", "note", "note",
2381                "note", "bar"
2382            ]
2383        );
2384    }
2385
2386    #[test]
2387    fn a_key_line_gives_its_sharps_and_mode() {
2388        // music21's `getKeySignatureParameters` docstring.
2389        assert_eq!(key_parameters("Eb").unwrap(), (-3, Some("major")));
2390        assert_eq!(
2391            key_parameters("A mixolydian").unwrap(),
2392            (2, Some("mixolydian"))
2393        );
2394        assert_eq!(key_parameters("F#m").unwrap(), (3, Some("minor")));
2395        assert_eq!(key_parameters("HP").unwrap(), (0, None));
2396        assert_eq!(key_parameters("Hp").unwrap(), (2, None));
2397    }
2398
2399    #[test]
2400    fn a_length_is_read_against_the_default() {
2401        // music21's `getQuarterLength` docstring.
2402        let mut note = AbcNote::new("", "", false);
2403        note.default_quarter_length = Some(0.5);
2404        assert_eq!(note.read_quarter_length("f", None).unwrap(), 0.5);
2405        assert_eq!(note.read_quarter_length("f2", None).unwrap(), 1.0);
2406        assert_eq!(note.read_quarter_length("f/", None).unwrap(), 0.25);
2407        assert_eq!(note.read_quarter_length("f3/2", None).unwrap(), 0.75);
2408        note.broken_rhythm = Some((">".to_string(), true));
2409        assert_eq!(note.read_quarter_length("A", None).unwrap(), 0.75);
2410    }
2411
2412    #[test]
2413    fn a_pitch_takes_its_accidental_from_the_key() {
2414        let mut note = AbcNote::new("f", "", false);
2415        note.key = Some(KeySignature::new(1));
2416        assert_eq!(
2417            note.pitch_name("f", None).unwrap(),
2418            (Some("F#5".to_string()), Some(false))
2419        );
2420        assert_eq!(
2421            note.pitch_name("=f", None).unwrap(),
2422            (Some("Fn5".to_string()), Some(true))
2423        );
2424        assert_eq!(note.pitch_name("z", None).unwrap(), (None, None));
2425        assert_eq!(
2426            note.pitch_name("C,,", None).unwrap(),
2427            (Some("C2".to_string()), Some(false))
2428        );
2429    }
2430
2431    #[test]
2432    fn a_tune_is_a_score_of_measures() {
2433        let score =
2434            from_abc("X:1\nT:Tune\nC:Anon\nM:3/4\nL:1/4\nK:D\nD E F | G A B | c d2 |]\n").unwrap();
2435        assert_eq!(score.kind(), StreamKind::Score);
2436        let metadata = score.metadata().unwrap();
2437        assert_eq!(metadata.first_text("title"), Some("Tune"));
2438        let part = score.parts()[0];
2439        let measures = part.measures();
2440        assert_eq!(measures.len(), 3);
2441        let names: Vec<String> = measures[0]
2442            .pitches()
2443            .iter()
2444            .map(|pitch| pitch.name_with_octave())
2445            .collect();
2446        assert_eq!(names, ["D4", "E4", "F#4"]);
2447        assert_eq!(
2448            measures[2].right_barline().unwrap().bar_type(),
2449            BarlineType::Final
2450        );
2451    }
2452
2453    #[test]
2454    fn several_tunes_are_an_opus_and_one_can_be_asked_for() {
2455        let text = "X:1\nT:One\nM:2/4\nL:1/4\nK:C\nC D | E F |]\n\nX:2\nT:Two\nM:2/4\nL:1/4\nK:C\nG A | B c |]\n";
2456        let opus = from_abc(text).unwrap();
2457        assert_eq!(opus.kind(), StreamKind::Opus);
2458        assert_eq!(opus.events().len(), 2);
2459        let second = from_abc_number(text, 2).unwrap();
2460        assert_eq!(second.metadata().unwrap().first_text("title"), Some("Two"));
2461        assert!(from_abc_number(text, 3).is_err());
2462    }
2463
2464    #[test]
2465    fn a_measure_holding_more_than_its_bar_is_cut_in_two() {
2466        // Six quarters between barlines in 4/4: a whole bar, then a 2/4 bar
2467        // holding the tied remainder of the long note, and the meter put
2468        // back on the measure after.
2469        let score = from_abc(
2470            "X:1
2471M:4/4
2472L:1/4
2473K:C
2474CDEF|GAB4|CDEF|
2475",
2476        )
2477        .unwrap();
2478        let part = score.events()[0].element().as_stream().unwrap();
2479        let measures = part.measures();
2480        let numbers: Vec<_> = measures.iter().map(|measure| measure.number()).collect();
2481        assert_eq!(numbers, [0, 1, 2, 3]);
2482        let meter = |measure: &Stream| {
2483            measure
2484                .events()
2485                .iter()
2486                .find_map(|event| match event.element() {
2487                    StreamElement::TimeSignature(meter) => Some(meter.ratio_string()),
2488                    _ => None,
2489                })
2490        };
2491        assert_eq!(meter(measures[1]), None);
2492        assert_eq!(meter(measures[2]).as_deref(), Some("2/4"));
2493        assert_eq!(meter(measures[3]).as_deref(), Some("4/4"));
2494        let ties: Vec<_> = measures[1..3]
2495            .iter()
2496            .flat_map(|measure| measure.events())
2497            .filter_map(|event| match event.element() {
2498                StreamElement::Note(note) if note.pitch().name() == "B" => Some((
2499                    event.element().quarter_length(),
2500                    note.tie().map(Tie::tie_type),
2501                )),
2502                _ => None,
2503            })
2504            .collect();
2505        assert_eq!(
2506            ties,
2507            [(2.0, Some(TieType::Start)), (2.0, Some(TieType::Stop))]
2508        );
2509    }
2510}