Skip to main content

music21/stream/
repeats.rs

1//! Repeats played out: music21's `repeat.Expander` and `expandRepeats`.
2
3use super::{Stream, StreamElement, StreamEvent, StreamKind};
4use crate::bar::{Barline, BarlineType, RepeatDirection};
5use crate::defaults::{FloatType, IntegerType};
6use crate::error::{Error, Result};
7use crate::repeat::RepeatExpressionKind;
8
9impl Stream {
10    /// This stream with its repeats played out, as music21's
11    /// `expandRepeats` plays them: every passage between repeat barlines
12    /// written out as many times as its end says (twice where it says
13    /// nothing), each first and second ending in its turn, and a *da capo*
14    /// or *dal segno* jump taken -- to the *fine* or through the *coda*
15    /// where it says so.
16    ///
17    /// A score has each part played out and keeps everything else it holds;
18    /// a part keeps what stands outside its measures where it stood. A
19    /// measure written out again is numbered as it was, with `a`, `b` and
20    /// on after its number the second time and later; one played after a
21    /// jump is renumbered on from the first. The repeat barlines become
22    /// double ones and the jumps and markers are taken out. A spanner joins
23    /// what it joined the first time through. A part with no repeats comes
24    /// back as it is.
25    ///
26    /// ```
27    /// use music21::bar::{Barline, RepeatDirection};
28    /// use music21::{Note, Stream, StreamKind};
29    ///
30    /// let mut part = Stream::with_kind(StreamKind::Part);
31    /// for (index, name) in ["C4", "D4"].into_iter().enumerate() {
32    ///     let mut measure = Stream::with_kind(StreamKind::Measure);
33    ///     measure.set_number(index as i32 + 1);
34    ///     measure.push(Note::from_name(name)?.with_duration(music21::Duration::whole()));
35    ///     if index == 0 {
36    ///         measure.set_right_barline(Some(Barline::repeat(RepeatDirection::End, None)));
37    ///     }
38    ///     part.insert(index as f64 * 4.0, measure);
39    /// }
40    /// let played = part.expand_repeats()?;
41    /// let numbers: Vec<String> = played
42    ///     .measures()
43    ///     .iter()
44    ///     .map(|measure| measure.number_with_suffix())
45    ///     .collect();
46    /// assert_eq!(numbers, ["1", "1a", "2"]);
47    /// # Ok::<(), music21::Error>(())
48    /// ```
49    ///
50    /// # Errors
51    ///
52    /// A stream holding no measures, and repeats music21 cannot make sense
53    /// of: barlines that do not pair up, endings that are not numbered one
54    /// on from another or not closed by a repeat, and more than one jump.
55    pub fn expand_repeats(&self) -> Result<Stream> {
56        if self.kind == StreamKind::Score || self.kind == StreamKind::Opus {
57            let mut expanded = Vec::new();
58            // Where each leaf of the score first sounds in what is played.
59            let mut moved: Vec<Option<usize>> = Vec::new();
60            let mut new_count = 0;
61            for event in &self.events {
62                match &event.element {
63                    StreamElement::Stream(part)
64                        if matches!(part.kind, StreamKind::Part | StreamKind::PartStaff) =>
65                    {
66                        let (played, part_moved) = part.expand_part()?;
67                        let first = new_count;
68                        moved.extend(
69                            part_moved
70                                .into_iter()
71                                .map(|place| place.map(|place| place + first)),
72                        );
73                        new_count += played.leaves().len();
74                        expanded.push(StreamEvent::new(
75                            event.offset,
76                            StreamElement::Stream(Box::new(played)),
77                        ));
78                    }
79                    element => {
80                        let count = match element {
81                            StreamElement::Stream(inner) => inner.leaves().len(),
82                            _ => 1,
83                        };
84                        moved.extend((new_count..new_count + count).map(Some));
85                        new_count += count;
86                        expanded.push(StreamEvent::new(event.offset, element.clone()));
87                    }
88                }
89            }
90            let mut score = self.with_events(expanded);
91            score.labels.spanners = self.labels.spanners.clone();
92            for spanner in &mut score.labels.spanners {
93                spanner.move_places(&moved);
94            }
95            return Ok(score);
96        }
97        self.expand_part().map(|(played, _)| played)
98    }
99
100    /// music21's `Stream.expandRepeats`, for one part, with where each of
101    /// its leaves first sounds in what is played.
102    fn expand_part(&self) -> Result<(Stream, Vec<Option<usize>>)> {
103        let measures: Vec<(FloatType, &Stream)> = self
104            .events
105            .iter()
106            .filter_map(|event| match &event.element {
107                StreamElement::Stream(inner) if inner.kind == StreamKind::Measure => {
108                    Some((event.offset, inner.as_ref()))
109                }
110                _ => None,
111            })
112            .collect();
113        if measures.is_empty() {
114            return Err(Error::Stream(
115                "cannot process repeats on Stream that does not contain measures".to_string(),
116            ));
117        }
118        let expander = Expander::from_measures(measures.iter().map(|(_, measure)| *measure));
119        // Nothing to play out leaves every measure where it stood.
120        let Some(played) = expander.process()? else {
121            return Ok((self.clone(), (0..self.leaves().len()).map(Some).collect()));
122        };
123
124        // Where each measure's leaves start among the part's, and what
125        // stands outside the measures, with where it stood.
126        let mut first_leaf: Vec<usize> = Vec::new();
127        let mut loose: Vec<(StreamEvent, usize)> = Vec::new();
128        let mut seen = 0;
129        for event in &self.events {
130            match &event.element {
131                StreamElement::Stream(inner) => {
132                    if inner.kind == StreamKind::Measure {
133                        first_leaf.push(seen);
134                    } else {
135                        loose.push((event.clone(), seen));
136                    }
137                    seen += inner.leaves().len();
138                }
139                _ => {
140                    loose.push((event.clone(), seen));
141                    seen += 1;
142                }
143            }
144        }
145
146        // The measures appended as music21 appends them, each where the
147        // furthest-reaching so far ends, then what stood outside them where
148        // it stood, sorted in among them.
149        let mut held: Vec<(StreamEvent, Origin)> = Vec::new();
150        let mut end: FloatType = 0.0;
151        for working in played {
152            let length = working
153                .appended_length
154                .unwrap_or_else(|| working.measure.end_offset());
155            let at = end;
156            let origin = Origin::Measure {
157                source: working.source,
158                stripped: working.stripped,
159            };
160            held.push((
161                StreamEvent::new(at, StreamElement::Stream(Box::new(working.measure))),
162                origin,
163            ));
164            end = end.max(crate::makenotation::op_frac(at + length));
165        }
166        held.extend(
167            loose
168                .into_iter()
169                .map(|(event, place)| (event, Origin::Loose(place))),
170        );
171        held.sort_by(|left, right| crate::makenotation::event_order(&left.0, &right.0));
172
173        let mut moved: Vec<Option<usize>> = vec![None; seen];
174        let mut placed = 0;
175        for (event, origin) in &held {
176            match origin {
177                Origin::Loose(place) => {
178                    let count = match event.element() {
179                        StreamElement::Stream(inner) => inner.leaves().len(),
180                        _ => 1,
181                    };
182                    for leaf in 0..count {
183                        moved[place + leaf] = Some(placed + leaf);
184                    }
185                    placed += count;
186                }
187                Origin::Measure { source, stripped } => {
188                    let source_measure = measures[*source].1;
189                    for (index, (top, _, element)) in
190                        source_measure.leaves_under_top().into_iter().enumerate()
191                    {
192                        // music21 takes out the jumps and markers standing in
193                        // the measure itself.
194                        let gone = *stripped
195                            && matches!(element, StreamElement::RepeatExpression(_))
196                            && !matches!(
197                                source_measure.events[top].element,
198                                StreamElement::Stream(_)
199                            );
200                        if gone {
201                            continue;
202                        }
203                        let old = first_leaf[*source] + index;
204                        if moved[old].is_none() {
205                            moved[old] = Some(placed);
206                        }
207                        placed += 1;
208                    }
209                }
210            }
211        }
212        let mut part =
213            self.with_events(held.into_iter().map(|(event, _)| event).collect::<Vec<_>>());
214        part.labels.spanners = self.labels.spanners.clone();
215        for spanner in &mut part.labels.spanners {
216            spanner.move_places(&moved);
217        }
218        Ok((part, moved))
219    }
220}
221
222/// Where an element of what is played came from.
223enum Origin {
224    Measure { source: usize, stripped: bool },
225    Loose(usize),
226}
227
228/// A measure being played out, with which measure of the part it is where
229/// it is still that very measure rather than a copy of it: music21 tells
230/// a measure from a copy by identity, and its endings name measures so.
231#[derive(Clone, Debug)]
232struct Working {
233    measure: Stream,
234    original: Option<usize>,
235    /// The measure of the part it plays, copy or not.
236    source: usize,
237    /// Whether its jumps and markers were taken out.
238    stripped: bool,
239    /// How long it was when music21 appended it, where something has been
240    /// taken out of it since: a jump standing past the barline still
241    /// counts there.
242    appended_length: Option<FloatType>,
243}
244
245impl Working {
246    /// The measure at `index` of the part, as it stands there.
247    fn of(measure: &Stream, index: usize) -> Self {
248        Self {
249            measure: measure.clone(),
250            original: Some(index),
251            source: index,
252            stripped: false,
253            appended_length: None,
254        }
255    }
256
257    /// A copy, which no ending names.
258    fn copy(&self) -> Self {
259        Self {
260            original: None,
261            ..self.clone()
262        }
263    }
264
265    fn left_repeat(&self) -> Option<RepeatDirection> {
266        self.measure
267            .left_barline()
268            .and_then(Barline::repeat_direction)
269    }
270
271    fn right_repeat(&self) -> Option<RepeatDirection> {
272        self.measure
273            .right_barline()
274            .and_then(Barline::repeat_direction)
275    }
276
277    /// music21's `_stripRepeatBarlines`: a repeat barline made a double one.
278    fn strip_repeat_barlines(&mut self) {
279        if self.left_repeat().is_some() {
280            self.measure
281                .set_left_barline(Some(Barline::new(BarlineType::Double)));
282        }
283        if self.right_repeat().is_some() {
284            self.measure
285                .set_right_barline(Some(Barline::new(BarlineType::Double)));
286        }
287    }
288
289    /// music21's `_stripRepeatExpressions`, on one measure.
290    fn strip_repeat_expressions(&mut self) {
291        let events: Vec<StreamEvent> = self
292            .measure
293            .events
294            .iter()
295            .filter(|event| !matches!(event.element, StreamElement::RepeatExpression(_)))
296            .cloned()
297            .collect();
298        let spanners = self.measure.labels.spanners.clone();
299        self.measure = self.measure.with_events(events);
300        self.measure.labels.spanners = spanners;
301        self.stripped = true;
302    }
303
304    /// The kinds of the jumps and markers standing in the measure itself.
305    fn expressions(&self) -> Vec<RepeatExpressionKind> {
306        self.measure
307            .events
308            .iter()
309            .filter_map(|event| match &event.element {
310                StreamElement::RepeatExpression(expression) => Some(expression.kind()),
311                _ => None,
312            })
313            .collect()
314    }
315}
316
317/// A first, second or later ending, by the measures of the part it spans.
318#[derive(Clone, Debug)]
319struct Bracket {
320    numbers: Vec<u32>,
321    measures: Vec<usize>,
322}
323
324impl Bracket {
325    fn is_first(&self, working: &Working) -> bool {
326        working.original.is_some() && working.original == self.measures.first().copied()
327    }
328
329    fn is_last(&self, working: &Working) -> bool {
330        working.original.is_some() && working.original == self.measures.last().copied()
331    }
332
333    fn spans(&self, working: &Working) -> bool {
334        working
335            .original
336            .is_some_and(|original| self.measures.contains(&original))
337    }
338}
339
340/// A group of endings played in turn after one passage, with the places of
341/// the measures from the first ending's start to each ending's end.
342#[derive(Clone, Debug, Default)]
343struct Group {
344    brackets: Vec<usize>,
345    indices: Vec<usize>,
346}
347
348/// music21's `repeat.Expander`: a part's repeats read once, to be played
349/// out whole -- which is [`Stream::expand_repeats`] -- or a step at a time.
350///
351/// The steps work on a stream of measures given them and hand back a new
352/// one; where music21 strips the repeat barline off a measure of the
353/// stream it was given, the crate leaves that stream as it was.
354///
355/// ```
356/// use music21::bar::{Barline, RepeatDirection};
357/// use music21::repeat::Expander;
358/// use music21::{Duration, Note, Stream, StreamKind};
359///
360/// let mut part = Stream::with_kind(StreamKind::Part);
361/// for number in 1..=3 {
362///     let mut measure = Stream::with_kind(StreamKind::Measure);
363///     measure.set_number(number);
364///     measure.push(Note::from_name("C4")?.with_duration(Duration::whole()));
365///     if number == 2 {
366///         measure.set_left_barline(Some(Barline::repeat(RepeatDirection::Start, None)));
367///         measure.set_right_barline(Some(Barline::repeat(RepeatDirection::End, Some(3))));
368///     }
369///     part.insert(f64::from(number - 1) * 4.0, measure);
370/// }
371/// let expander = Expander::new(&part)?;
372/// assert!(expander.repeat_bars_are_coherent()?);
373/// assert_eq!(expander.measure_map()?, [0, 1, 1, 1, 2]);
374/// assert_eq!(expander.measure_map_numbers()?, ["1", "2", "2a", "2b", "3"]);
375/// # Ok::<(), music21::Error>(())
376/// ```
377#[derive(Clone, Debug)]
378pub struct Expander {
379    source: Vec<Working>,
380    brackets: Vec<Bracket>,
381    counts: std::collections::HashMap<RepeatExpressionKind, usize>,
382}
383
384/// music21's `_daCapoOrSegno`.
385#[derive(Clone, Copy, Debug, PartialEq, Eq)]
386enum Jump {
387    DaCapo,
388    Segno,
389}
390
391impl Expander {
392    /// The repeats of `part`'s measures, read: music21's `Expander(part)`,
393    /// which is refused where the part has no measures.
394    pub fn new(part: &Stream) -> Result<Self> {
395        let measures = part.measures();
396        if measures.is_empty() {
397            return Err(Error::Stream(
398                "no measures found in the source stream to be expanded".to_string(),
399            ));
400        }
401        Ok(Self::from_measures(measures))
402    }
403
404    fn from_measures<'a>(measures: impl IntoIterator<Item = &'a Stream>) -> Self {
405        let source: Vec<Working> = measures
406            .into_iter()
407            .enumerate()
408            .map(|(index, measure)| Working::of(measure, index))
409            .collect();
410        // A bracket opens on a measure whose ending starts and closes on one
411        // whose ending stops; music21's spanner spans those measures, and
412        // only those, as the reader marks them.
413        let mut brackets: Vec<Bracket> = Vec::new();
414        let mut open = false;
415        for (index, working) in source.iter().enumerate() {
416            let Some(ending) = working.measure.ending() else {
417                continue;
418            };
419            match brackets.last_mut() {
420                Some(bracket) if open && !ending.starts() => bracket.measures.push(index),
421                _ => brackets.push(Bracket {
422                    numbers: ending.numbers().to_vec(),
423                    measures: vec![index],
424                }),
425            }
426            open = !ending.stops();
427        }
428        let mut counts = std::collections::HashMap::new();
429        for working in &source {
430            for (_, element) in working.measure.leaves() {
431                if let StreamElement::RepeatExpression(expression) = element {
432                    *counts.entry(expression.kind()).or_insert(0) += 1;
433                }
434            }
435        }
436        Self {
437            source,
438            brackets,
439            counts,
440        }
441    }
442
443    fn count(&self, kind: RepeatExpressionKind) -> usize {
444        self.counts.get(&kind).copied().unwrap_or(0)
445    }
446
447    /// music21's `process`: the measures played out, or `None` where there
448    /// is nothing to play out.
449    fn process(&self) -> Result<Option<Vec<Working>>> {
450        match self.is_expandable()? {
451            Some(false) => Err(Error::Stream(
452                "cannot expand Stream: badly formed repeats or repeat expressions".to_string(),
453            )),
454            None => Ok(None),
455            Some(true) => match self.da_capo_or_segno() {
456                None => self
457                    .process_recursive_repeat_bars(self.source.clone())
458                    .map(Some),
459                Some(jump) => self
460                    .process_repeat_expression_and_repeats(self.source.clone(), jump)
461                    .map(Some),
462            },
463        }
464    }
465
466    /// The measures played, as `process` leaves them: the source measures
467    /// themselves where there is nothing to play out.
468    fn played_measures(&self) -> Result<Vec<Working>> {
469        Ok(self.process()?.unwrap_or_else(|| self.source.clone()))
470    }
471
472    /// For each measure played, which measure of the part it plays, by its
473    /// place among them: music21's `measureMap`.
474    ///
475    /// A measure is found by its number and suffix, and by its number
476    /// alone where no measure of the part has both, as music21 finds it;
477    /// one renumbered after a jump past the part's last number has neither,
478    /// and is refused.
479    pub fn measure_map(&self) -> Result<Vec<usize>> {
480        let mut with_suffix = std::collections::HashMap::new();
481        let mut without = std::collections::HashMap::new();
482        for (index, working) in self.source.iter().enumerate() {
483            with_suffix.insert(working.measure.number_with_suffix(), index);
484            without.insert(working.measure.number(), index);
485        }
486        self.played_measures()?
487            .iter()
488            .map(|working| {
489                let measure = &working.measure;
490                with_suffix
491                    .get(&measure.number_with_suffix())
492                    .or_else(|| without.get(&measure.number()))
493                    .copied()
494                    .ok_or_else(|| {
495                        Error::Stream(format!(
496                            "no measure {} in the source stream",
497                            measure.number()
498                        ))
499                    })
500            })
501            .collect()
502    }
503
504    /// The number and suffix of each measure played: music21's
505    /// `measureMap(returnType='measureNumber')`.
506    pub fn measure_map_numbers(&self) -> Result<Vec<String>> {
507        Ok(self
508            .played_measures()?
509            .iter()
510            .map(|working| working.measure.number_with_suffix())
511            .collect())
512    }
513
514    /// The places among `measures`' measures of the first passage closed
515    /// by a repeat barline, from the last start before it, or from the
516    /// first measure where there is none: music21's
517    /// `findInnermostRepeatIndices`. Empty where no repeat closes.
518    pub fn find_innermost_repeat_indices(measures: &Stream) -> Vec<usize> {
519        Self::innermost_of(&Self::measures_of(measures))
520    }
521
522    /// `measures` with its innermost repeated passage played out, every
523    /// other measure kept as it stands: music21's
524    /// `processInnermostRepeatBars`. Called again on what it gives, it
525    /// plays out the next passage.
526    ///
527    /// `repeat_indices` plays out exactly those measures instead, and
528    /// `repeat_times` plays them that many times rather than as often as
529    /// the closing barline says; `expansion_only` hands back the measures
530    /// played out and nothing else. The measures are laid end to end in a
531    /// stream of `measures`' own kind; one played again is numbered with
532    /// `a`, `b` and on.
533    pub fn process_innermost_repeat_bars(
534        measures: &Stream,
535        repeat_indices: Option<&[usize]>,
536        repeat_times: Option<u32>,
537        expansion_only: bool,
538    ) -> Result<Stream> {
539        let mut source = Self::measures_of(measures);
540        let played =
541            Self::play_innermost(&mut source, repeat_indices, repeat_times, expansion_only)?;
542
543        let mut out = Stream::with_kind(measures.kind());
544        let mut end: FloatType = 0.0;
545        for working in played {
546            let length = working.measure.end_offset();
547            out.insert(end, working.measure);
548            end = crate::makenotation::op_frac(end + length);
549        }
550        Ok(out)
551    }
552
553    /// The places among `measures`' measures of those holding a mark of
554    /// `kind`, once for each such mark: music21's `getRepeatExpressionIndex`
555    /// asked for one class of mark. Empty where there is none.
556    pub fn repeat_expression_index(measures: &Stream, kind: RepeatExpressionKind) -> Vec<usize> {
557        Self::measures_of(measures)
558            .iter()
559            .enumerate()
560            .flat_map(|(index, working)| {
561                working
562                    .expressions()
563                    .into_iter()
564                    .filter(move |found| *found == kind)
565                    .map(move |_| index)
566            })
567            .collect()
568    }
569
570    /// The measures of a stream, each as itself.
571    fn measures_of(measures: &Stream) -> Vec<Working> {
572        measures
573            .measures()
574            .into_iter()
575            .enumerate()
576            .map(|(index, measure)| Working::of(measure, index))
577            .collect()
578    }
579
580    fn da_capo_or_segno(&self) -> Option<Jump> {
581        use RepeatExpressionKind::*;
582        let da_capo = self.count(DaCapo) + self.count(DaCapoAlFine) + self.count(DaCapoAlCoda);
583        let segno = self.count(DalSegno)
584            + self.count(DalSegnoAlCoda)
585            + self.count(DalSegnoAlFine)
586            + self.count(AlSegno);
587        match (da_capo, segno) {
588            (1, 0) => Some(Jump::DaCapo),
589            (0, 1) => Some(Jump::Segno),
590            _ => None,
591        }
592    }
593
594    /// Whether the repeats can be played out: music21's `isExpandable`,
595    /// which is `None` where there is nothing to play out, and `false`
596    /// where the repeat barlines do not pair up, the endings do not follow
597    /// on from each other, or a *da capo* or *dal segno* lacks the *fine*,
598    /// coda or segno it names.
599    pub fn is_expandable(&self) -> Result<Option<bool>> {
600        let jump = self.da_capo_or_segno();
601        if jump.is_none() && !has_repeat(&self.source) {
602            return Ok(None);
603        }
604        if !self.repeat_bars_are_coherent()? || !self.repeat_brackets_are_coherent() {
605            return Ok(Some(false));
606        }
607        Ok(Some(match jump {
608            Some(Jump::DaCapo) => self.da_capo_is_coherent(),
609            Some(Jump::Segno) => self.dal_segno_is_coherent(),
610            None => true,
611        }))
612    }
613
614    /// Whether every repeat barline pairs up with another: music21's
615    /// `repeatBarsAreCoherent`. An end with no start before it is taken to
616    /// go back to the beginning; a right barline marking a start is
617    /// refused.
618    pub fn repeat_bars_are_coherent(&self) -> Result<bool> {
619        let (mut starts, mut ends, mut balance) = (0, 0, 0);
620        for working in &self.source {
621            match working.left_repeat() {
622                Some(RepeatDirection::Start) => {
623                    starts += 1;
624                    balance += 1;
625                }
626                Some(RepeatDirection::End) => {
627                    if balance == 0 {
628                        starts += 1;
629                        balance += 1;
630                    }
631                    ends += 1;
632                    balance -= 1;
633                }
634                None => {}
635            }
636            match working.right_repeat() {
637                Some(RepeatDirection::End) => {
638                    if balance == 0 {
639                        starts += 1;
640                        balance += 1;
641                    }
642                    ends += 1;
643                    balance -= 1;
644                }
645                Some(RepeatDirection::Start) => {
646                    return Err(Error::Stream(format!(
647                        "a right barline is found that cannot be processed: measure {}",
648                        working.measure.number_with_suffix()
649                    )));
650                }
651                None => {}
652            }
653        }
654        Ok(matches!(balance, 0 | 1) && (starts == ends || starts + 1 == ends))
655    }
656
657    fn da_capo_is_coherent(&self) -> bool {
658        use RepeatExpressionKind::*;
659        let total = self.count(DaCapo) + self.count(DaCapoAlFine) + self.count(DaCapoAlCoda);
660        if total > 1 {
661            return false;
662        }
663        (self.count(DaCapo) == 1 && self.count(Coda) == 0)
664            || (self.count(DaCapoAlFine) == 1 && self.count(Fine) == 1)
665            || (self.count(DaCapoAlCoda) == 1 && self.count(Coda) == 2)
666    }
667
668    fn dal_segno_is_coherent(&self) -> bool {
669        use RepeatExpressionKind::*;
670        let total = self.count(AlSegno)
671            + self.count(DalSegno)
672            + self.count(DalSegnoAlCoda)
673            + self.count(DalSegnoAlFine);
674        if total > 1 {
675            return false;
676        }
677        let (segnos, codas, fines) = (self.count(Segno), self.count(Coda), self.count(Fine));
678        (self.count(AlSegno) == 1 && segnos == 1 && codas == 0)
679            || (self.count(DalSegno) == 1 && segnos == 1 && codas == 0)
680            || (self.count(DalSegnoAlFine) == 1 && codas == 0 && segnos == 1 && fines == 1)
681            || (self.count(DalSegnoAlCoda) == 1 && codas == 2 && segnos == 1 && fines == 0)
682    }
683
684    /// music21's `_groupRepeatBracketIndices`.
685    fn group_bracket_indices(&self, measures: &[Working]) -> Vec<Group> {
686        let mut groups = Vec::new();
687        let mut found_numbers: Vec<u32> = Vec::new();
688        let mut group = Group::default();
689        for (index, working) in measures.iter().enumerate() {
690            for (bracket_index, bracket) in self.brackets.iter().enumerate() {
691                if !bracket.is_first(working) {
692                    continue;
693                }
694                if bracket
695                    .numbers
696                    .first()
697                    .is_some_and(|first| found_numbers.contains(first))
698                {
699                    groups.push(std::mem::take(&mut group));
700                    found_numbers.clear();
701                }
702                found_numbers.extend(&bracket.numbers);
703                group.brackets.push(bracket_index);
704                for (sub, candidate) in measures.iter().enumerate() {
705                    if bracket.is_last(candidate) {
706                        group.indices.push(sub);
707                        break;
708                    }
709                    if sub >= index {
710                        group.indices.push(sub);
711                    }
712                }
713            }
714        }
715        // music21 keeps the group it was building whatever it holds.
716        groups.push(group);
717        groups
718    }
719
720    fn repeat_brackets_are_coherent(&self) -> bool {
721        for group in self.group_bracket_indices(&self.source) {
722            if group.brackets.is_empty() {
723                return true;
724            }
725            if group.brackets.len() > 1 {
726                let numbers: Vec<u32> = group
727                    .brackets
728                    .iter()
729                    .flat_map(|index| self.brackets[*index].numbers.clone())
730                    .collect();
731                let highest = numbers.iter().copied().max().unwrap_or(0);
732                if numbers != (1..=highest).collect::<Vec<_>>() {
733                    return false;
734                }
735            }
736            let mut spanned: Vec<usize> = Vec::new();
737            for (count, index) in group.brackets.iter().enumerate() {
738                let bracket = &self.brackets[*index];
739                for measure in &bracket.measures {
740                    if spanned.contains(measure) {
741                        return false;
742                    }
743                    spanned.push(*measure);
744                }
745                let last =
746                    &self.source[*bracket.measures.last().expect("an ending spans a measure")];
747                if last.right_repeat().is_none()
748                    && (group.brackets.len() == 1 || count + 1 < group.brackets.len())
749                {
750                    return false;
751                }
752            }
753        }
754        true
755    }
756
757    /// music21's `findInnermostRepeatIndices`.
758    fn innermost_of(measures: &[Working]) -> Vec<usize> {
759        let mut starts: Vec<usize> = Vec::new();
760        for (index, working) in measures.iter().enumerate() {
761            match working.left_repeat() {
762                Some(RepeatDirection::Start) => starts.push(index),
763                Some(RepeatDirection::End) => {
764                    return (starts.last().copied().unwrap_or(0)..index).collect();
765                }
766                None => {}
767            }
768            if working.right_repeat() == Some(RepeatDirection::End) {
769                return (starts.last().copied().unwrap_or(0)..=index).collect();
770            }
771        }
772        Vec::new()
773    }
774
775    /// music21's `_getEndRepeatBar`: whether the measure closing the repeat
776    /// is the last one repeated, and how many times it is played.
777    fn end_repeat_bar(measures: &[Working], index: usize) -> Result<(bool, u32)> {
778        let last = &measures[index];
779        if last.right_repeat() == Some(RepeatDirection::End) {
780            let times = last.measure.right_barline().and_then(Barline::repeat_times);
781            return Ok((true, times.unwrap_or(2)));
782        }
783        let Some(after) = measures.get(index + 1) else {
784            return Err(Error::Stream(format!(
785                "cannot find an end Repeat bar after the given end: {index}"
786            )));
787        };
788        if after.left_repeat() == Some(RepeatDirection::End) {
789            let times = after.measure.left_barline().and_then(Barline::repeat_times);
790            return Ok((false, times.unwrap_or(2)));
791        }
792        Err(Error::Stream(
793            "cannot find an end Repeat bar in the expected position".to_string(),
794        ))
795    }
796
797    /// music21's `processInnermostRepeatBars`.
798    fn play_innermost(
799        measures: &mut [Working],
800        forced: Option<&[usize]>,
801        times: Option<u32>,
802        expansion_only: bool,
803    ) -> Result<Vec<Working>> {
804        let indices: Vec<usize> = match forced {
805            Some(indices) => indices.to_vec(),
806            None => Self::innermost_of(measures),
807        };
808        if indices.iter().any(|index| *index >= measures.len()) {
809            return Err(Error::Stream(format!(
810                "a repeat index is past the last of {} measures",
811                measures.len()
812            )));
813        }
814        let mut out = Vec::new();
815        let mut strip_next = false;
816        let mut times_given = times;
817        let mut index = 0;
818        while index < measures.len() {
819            let (Some(&first), Some(&last)) = (indices.first(), indices.last()) else {
820                break;
821            };
822            if index == first {
823                let (closes_itself, times_found) = match Self::end_repeat_bar(measures, last) {
824                    Ok(found) => found,
825                    Err(error) if forced.is_none() => return Err(error),
826                    // A forced run with no repeat bar at its end: music21
827                    // leaves its last and its end-barline measure as `None`,
828                    // which counts as the same measure, and finds it played
829                    // no times.
830                    Err(_) => (true, 0),
831                };
832                let times = *times_given.get_or_insert(times_found);
833                for time in 0..times {
834                    for &place in &indices {
835                        let mut copy = measures[place].copy();
836                        if place == first || place == last {
837                            copy.strip_repeat_barlines();
838                        }
839                        if times >= 2 && time < times - 1 {
840                            copy.strip_repeat_expressions();
841                        }
842                        if time != 0 {
843                            let letter = char::from(b'a' + ((time - 1) % 26) as u8);
844                            copy.measure.set_number_suffix(Some(letter.to_string()));
845                        }
846                        out.push(copy);
847                    }
848                }
849                if !closes_itself {
850                    strip_next = true;
851                }
852                index = last + 1;
853            } else {
854                if !expansion_only {
855                    if strip_next {
856                        measures[index].strip_repeat_barlines();
857                        strip_next = false;
858                    }
859                    out.push(measures[index].clone());
860                }
861                index += 1;
862            }
863        }
864        Ok(out)
865    }
866
867    /// music21's `_processInnermostRepeatsAndBrackets`.
868    fn process_innermost_repeats_and_brackets(
869        &self,
870        mut measures: Vec<Working>,
871        done: &mut Vec<usize>,
872    ) -> Result<Vec<Working>> {
873        let groups = self.group_bracket_indices(&measures);
874        let innermost = Self::innermost_of(&measures);
875        let mut focus: Option<Group> = None;
876        if let (Some(&first), Some(&last)) = (innermost.first(), innermost.last()) {
877            for group in &groups {
878                for &bracket in &group.brackets {
879                    if done.contains(&bracket) {
880                        break;
881                    }
882                    let spans = &self.brackets[bracket];
883                    if spans.spans(&measures[first]) || spans.spans(&measures[last]) {
884                        focus = Some(group.clone());
885                        break;
886                    }
887                }
888                if focus.is_some() {
889                    break;
890                }
891            }
892        }
893        let Some(focus) = focus else {
894            return Self::play_innermost(&mut measures, None, None, false);
895        };
896        let start = innermost[0];
897        let mut boundaries: Vec<(usize, Vec<usize>, Vec<usize>)> = Vec::new();
898        for &bracket_index in &focus.brackets {
899            done.push(bracket_index);
900            let bracket = &self.brackets[bracket_index];
901            let mut end = None;
902            let mut bracket_start = None;
903            for (index, working) in measures.iter().enumerate() {
904                if bracket.is_last(working) {
905                    end = Some(index);
906                }
907                if bracket.is_first(working) {
908                    bracket_start = Some(index);
909                }
910            }
911            let (Some(end), Some(bracket_start)) = (end, bracket_start) else {
912                return Err(Error::Stream(
913                    "failed to find start or end index of bracket expansion".to_string(),
914                ));
915            };
916            let mut indices: Vec<usize> = (start..=end).collect();
917            for (_, _, earlier) in &boundaries {
918                indices.retain(|index| !earlier.contains(index));
919            }
920            boundaries.push((bracket_index, indices, (bracket_start..=end).collect()));
921        }
922        let mut repeats: Vec<Vec<Working>> = Vec::new();
923        let mut highest = None;
924        for (bracket_index, indices, _) in &boundaries {
925            let times = self.brackets[*bracket_index].numbers.len() as u32;
926            repeats.push(Self::play_innermost(
927                &mut measures,
928                Some(indices),
929                Some(times),
930                true,
931            )?);
932            highest = indices.iter().copied().max();
933        }
934        let mut out: Vec<Working> = measures[..start].to_vec();
935        for sub in repeats {
936            for mut working in sub {
937                working.strip_repeat_barlines();
938                out.push(working);
939            }
940        }
941        if let Some(highest) = highest {
942            out.extend(measures[highest + 1..].iter().cloned());
943        }
944        Ok(out)
945    }
946
947    /// music21's `_processRecursiveRepeatBars`.
948    fn process_recursive_repeat_bars(&self, mut measures: Vec<Working>) -> Result<Vec<Working>> {
949        let mut done: Vec<usize> = Vec::new();
950        for _ in 0..100 {
951            measures = self.process_innermost_repeats_and_brackets(measures, &mut done)?;
952            if !has_repeat(&measures) {
953                break;
954            }
955        }
956        Ok(measures)
957    }
958
959    /// music21's `_processRepeatExpressionAndRepeats`: the passage up to the
960    /// jump, then from where it jumps to on to the fine, the end or the
961    /// first coda and on from the second.
962    fn process_repeat_expression_and_repeats(
963        &self,
964        measures: Vec<Working>,
965        jump: Jump,
966    ) -> Result<Vec<Working>> {
967        use RepeatExpressionKind::*;
968        let command = [
969            DaCapo,
970            DaCapoAlCoda,
971            DaCapoAlFine,
972            AlSegno,
973            DalSegno,
974            DalSegnoAlCoda,
975            DalSegnoAlFine,
976        ]
977        .into_iter()
978        .find(|kind| self.count(*kind) == 1)
979        .ok_or_else(|| Error::Stream("no repeat command found".to_string()))?;
980        let index_of = |kind: RepeatExpressionKind| -> Vec<usize> {
981            measures
982                .iter()
983                .enumerate()
984                .flat_map(|(index, working)| {
985                    working
986                        .expressions()
987                        .into_iter()
988                        .filter(move |found| *found == kind)
989                        .map(move |_| index)
990                })
991                .collect()
992        };
993        let missing =
994            || Error::Stream("a repeat expression is not where it is expected".to_string());
995        let jump_back = *index_of(command).first().ok_or_else(missing)?;
996        let start = match jump {
997            Jump::DaCapo => 0,
998            Jump::Segno => *index_of(Segno).first().ok_or_else(missing)?,
999        };
1000        let last = measures.len() - 1;
1001        let end = if matches!(command, DaCapoAlFine | DalSegnoAlFine) {
1002            *index_of(Fine).first().ok_or_else(missing)?
1003        } else {
1004            last
1005        };
1006        let mut segments = vec![(0, jump_back)];
1007        if matches!(command, DaCapoAlCoda | DalSegnoAlCoda) {
1008            let codas = index_of(Coda);
1009            let (Some(&jump_from), Some(&resume)) = (codas.first(), codas.get(1)) else {
1010                return Err(missing());
1011            };
1012            segments.push((start, jump_from));
1013            segments.push((resume, last));
1014        } else {
1015            segments.push((start, end));
1016        }
1017
1018        let mut number: IntegerType = measures[0].measure.number();
1019        let mut out = Vec::new();
1020        for (count, (from, to)) in segments.into_iter().enumerate() {
1021            let mut segment: Vec<Working> = Vec::new();
1022            for working in measures.iter().take(to + 1).skip(from) {
1023                let mut copy = working.copy();
1024                copy.measure.set_number(number);
1025                segment.push(copy);
1026                number += 1;
1027            }
1028            if has_repeat(&segment) {
1029                // music21 plays the repeats after the jump only where the
1030                // jump says to, and none of its jumps do.
1031                if count != 1 {
1032                    segment = self.process_recursive_repeat_bars(segment)?;
1033                    number = segment
1034                        .last()
1035                        .map_or(number, |last| last.measure.number() + 1);
1036                }
1037                for working in &mut segment {
1038                    working.strip_repeat_barlines();
1039                }
1040            }
1041            out.extend(segment);
1042        }
1043        for working in &mut out {
1044            working.appended_length = Some(working.measure.end_offset());
1045            working.strip_repeat_expressions();
1046        }
1047        Ok(out)
1048    }
1049}
1050
1051/// music21's `_hasRepeat`.
1052fn has_repeat(measures: &[Working]) -> bool {
1053    measures.iter().any(|working| {
1054        working.left_repeat().is_some() || working.right_repeat() == Some(RepeatDirection::End)
1055    })
1056}
1057
1058#[cfg(test)]
1059mod tests {
1060    use crate::bar::{Barline, Ending, RepeatDirection};
1061    use crate::repeat::{RepeatExpression, RepeatExpressionKind};
1062    use crate::stream::{Expander, Stream, StreamElement, StreamKind};
1063    use crate::{Duration, Note};
1064
1065    /// A part of whole-note measures numbered from one, each shaped by
1066    /// `shape` from its number.
1067    fn part(count: i32, shape: impl Fn(i32, &mut Stream)) -> Stream {
1068        let mut part = Stream::with_kind(StreamKind::Part);
1069        for number in 1..=count {
1070            let mut measure = Stream::with_kind(StreamKind::Measure);
1071            measure.set_number(number);
1072            measure.push(
1073                Note::from_name("C4")
1074                    .unwrap()
1075                    .with_duration(Duration::whole()),
1076            );
1077            shape(number, &mut measure);
1078            part.insert(f64::from(number - 1) * 4.0, measure);
1079        }
1080        part
1081    }
1082
1083    fn played(part: &Stream) -> Vec<String> {
1084        part.expand_repeats()
1085            .unwrap()
1086            .measures()
1087            .iter()
1088            .map(|measure| measure.number_with_suffix())
1089            .collect()
1090    }
1091
1092    #[test]
1093    fn a_passage_between_repeat_barlines_is_played_twice() {
1094        let part = part(4, |number, measure| match number {
1095            2 => measure.set_left_barline(Some(Barline::repeat(RepeatDirection::Start, None))),
1096            3 => measure.set_right_barline(Some(Barline::repeat(RepeatDirection::End, None))),
1097            _ => {}
1098        });
1099        assert_eq!(played(&part), ["1", "2", "3", "2a", "3a", "4"]);
1100        let expanded = part.expand_repeats().unwrap();
1101        // Laid end to end, and the repeat barlines made double ones.
1102        assert_eq!(expanded.end_offset(), 24.0);
1103        assert!(
1104            expanded.measures()[2]
1105                .right_barline()
1106                .unwrap()
1107                .repeat_direction()
1108                .is_none()
1109        );
1110    }
1111
1112    #[test]
1113    fn a_first_ending_is_played_then_the_second() {
1114        let part = part(4, |number, measure| match number {
1115            2 => {
1116                measure.set_ending(Some(Ending::new(vec![1], true, true)));
1117                measure.set_right_barline(Some(Barline::repeat(RepeatDirection::End, None)));
1118            }
1119            3 => measure.set_ending(Some(Ending::new(vec![2], true, true))),
1120            _ => {}
1121        });
1122        // Each ending's run is played once, so music21 numbers neither
1123        // time through with a suffix.
1124        assert_eq!(played(&part), ["1", "2", "1", "3", "4"]);
1125    }
1126
1127    #[test]
1128    fn da_capo_al_fine_goes_back_to_the_fine() {
1129        let part = part(3, |number, measure| {
1130            let mark = match number {
1131                1 => RepeatExpressionKind::Fine,
1132                3 => RepeatExpressionKind::DaCapoAlFine,
1133                _ => return,
1134            };
1135            measure.insert(
1136                0.0,
1137                StreamElement::RepeatExpression(RepeatExpression::new(mark)),
1138            );
1139        });
1140        // Renumbered on from the first, and the marks taken out.
1141        assert_eq!(played(&part), ["1", "2", "3", "4"]);
1142        let expanded = part.expand_repeats().unwrap();
1143        assert!(
1144            expanded
1145                .recurse()
1146                .iter()
1147                .all(|(_, element)| !matches!(element, StreamElement::RepeatExpression(_)))
1148        );
1149    }
1150
1151    #[test]
1152    fn repeats_that_do_not_pair_up_are_refused() {
1153        let part = part(3, |number, measure| {
1154            if number != 2 {
1155                measure.set_left_barline(Some(Barline::repeat(RepeatDirection::Start, None)));
1156            }
1157        });
1158        assert!(part.expand_repeats().is_err());
1159    }
1160
1161    /// music21's own example for the expander's steps: a passage of one
1162    /// measure played three times, then one played twice.
1163    fn two_passages() -> Stream {
1164        part(5, |number, measure| match number {
1165            2 => {
1166                measure.set_left_barline(Some(Barline::repeat(RepeatDirection::Start, None)));
1167                measure.set_right_barline(Some(Barline::repeat(RepeatDirection::End, Some(3))));
1168            }
1169            4 => {
1170                measure.set_left_barline(Some(Barline::repeat(RepeatDirection::Start, None)));
1171                measure.set_right_barline(Some(Barline::repeat(RepeatDirection::End, Some(2))));
1172            }
1173            _ => {}
1174        })
1175    }
1176
1177    fn numbers(stream: &Stream) -> Vec<String> {
1178        stream
1179            .measures()
1180            .iter()
1181            .map(|measure| measure.number_with_suffix())
1182            .collect()
1183    }
1184
1185    #[test]
1186    fn the_measure_map_names_the_measure_each_one_plays() {
1187        let expander = Expander::new(&two_passages()).unwrap();
1188        assert_eq!(expander.measure_map().unwrap(), [0, 1, 1, 1, 2, 3, 3, 4]);
1189        assert_eq!(
1190            expander.measure_map_numbers().unwrap(),
1191            ["1", "2", "2a", "2b", "3", "4", "4a", "5"]
1192        );
1193    }
1194
1195    #[test]
1196    fn a_part_with_nothing_to_play_out_maps_to_itself() {
1197        let expander = Expander::new(&part(3, |_, _| {})).unwrap();
1198        assert_eq!(expander.is_expandable().unwrap(), None);
1199        assert_eq!(expander.measure_map().unwrap(), [0, 1, 2]);
1200    }
1201
1202    #[test]
1203    fn repeats_that_do_not_pair_up_are_not_expandable() {
1204        let part = part(3, |number, measure| {
1205            if number != 2 {
1206                measure.set_left_barline(Some(Barline::repeat(RepeatDirection::Start, None)));
1207            }
1208        });
1209        let expander = Expander::new(&part).unwrap();
1210        assert!(!expander.repeat_bars_are_coherent().unwrap());
1211        assert_eq!(expander.is_expandable().unwrap(), Some(false));
1212        assert!(expander.measure_map().is_err());
1213        assert!(
1214            Expander::new(&two_passages())
1215                .unwrap()
1216                .repeat_bars_are_coherent()
1217                .unwrap()
1218        );
1219    }
1220
1221    #[test]
1222    fn a_right_barline_starting_a_repeat_is_refused() {
1223        let part = part(2, |number, measure| {
1224            if number == 1 {
1225                measure.set_right_barline(Some(Barline::repeat(RepeatDirection::Start, None)));
1226            }
1227        });
1228        assert!(
1229            Expander::new(&part)
1230                .unwrap()
1231                .repeat_bars_are_coherent()
1232                .is_err()
1233        );
1234    }
1235
1236    #[test]
1237    fn the_innermost_repeat_runs_from_the_last_start() {
1238        let mut written = two_passages();
1239        assert_eq!(Expander::find_innermost_repeat_indices(&written), [1]);
1240        let StreamElement::Stream(second) = written.events_mut()[1].element_mut() else {
1241            unreachable!()
1242        };
1243        second.set_right_barline(None);
1244        let StreamElement::Stream(fourth) = written.events_mut()[3].element_mut() else {
1245            unreachable!()
1246        };
1247        fourth.set_left_barline(None);
1248        assert_eq!(Expander::find_innermost_repeat_indices(&written), [1, 2, 3]);
1249        assert!(Expander::find_innermost_repeat_indices(&part(2, |_, _| {})).is_empty());
1250    }
1251
1252    #[test]
1253    fn the_innermost_repeat_is_played_out_one_at_a_time() {
1254        let part = two_passages();
1255        let once = Expander::process_innermost_repeat_bars(&part, None, None, false).unwrap();
1256        assert_eq!(numbers(&once), ["1", "2", "2a", "2b", "3", "4", "5"]);
1257        assert_eq!(once.kind(), StreamKind::Part);
1258        assert_eq!(once.events()[4].offset(), 16.0);
1259        // The next passage is still to be played.
1260        assert!(
1261            once.measures()[5]
1262                .left_barline()
1263                .unwrap()
1264                .repeat_direction()
1265                .is_some()
1266        );
1267
1268        let twice = Expander::process_innermost_repeat_bars(&once, None, None, false).unwrap();
1269        assert_eq!(numbers(&twice), ["1", "2", "2a", "2b", "3", "4", "4a", "5"]);
1270        assert_eq!(twice.end_offset(), 32.0);
1271        // The stream it was given is left as it was.
1272        assert_eq!(numbers(&part), ["1", "2", "3", "4", "5"]);
1273    }
1274
1275    #[test]
1276    fn an_end_with_no_start_repeats_from_the_beginning() {
1277        let part = part(5, |number, measure| {
1278            if number == 2 {
1279                measure.set_right_barline(Some(Barline::repeat(RepeatDirection::End, None)));
1280            }
1281        });
1282        let played = Expander::process_innermost_repeat_bars(&part, None, None, false).unwrap();
1283        assert_eq!(numbers(&played), ["1", "2", "1a", "2a", "3", "4", "5"]);
1284    }
1285
1286    #[test]
1287    fn given_measures_are_played_as_often_as_asked() {
1288        let part = part(3, |_, _| {});
1289        let played =
1290            Expander::process_innermost_repeat_bars(&part, Some(&[1]), Some(2), false).unwrap();
1291        assert_eq!(numbers(&played), ["1", "2", "2a", "3"]);
1292        let only =
1293            Expander::process_innermost_repeat_bars(&part, Some(&[1]), Some(2), true).unwrap();
1294        assert_eq!(numbers(&only), ["2", "2a"]);
1295        // With no repeat barline to say how often, music21 plays them none.
1296        let none = Expander::process_innermost_repeat_bars(&part, Some(&[1]), None, false).unwrap();
1297        assert_eq!(numbers(&none), ["1", "3"]);
1298        assert!(Expander::process_innermost_repeat_bars(&part, Some(&[7]), None, false).is_err());
1299    }
1300
1301    #[test]
1302    fn a_repeat_expression_is_found_by_its_measure() {
1303        let part = part(3, |number, measure| {
1304            if number == 3 {
1305                measure.push(StreamElement::RepeatExpression(RepeatExpression::new(
1306                    RepeatExpressionKind::Segno,
1307                )));
1308            }
1309        });
1310        assert_eq!(
1311            Expander::repeat_expression_index(&part, RepeatExpressionKind::Segno),
1312            [2]
1313        );
1314        assert!(Expander::repeat_expression_index(&part, RepeatExpressionKind::Coda).is_empty());
1315    }
1316
1317    #[test]
1318    fn an_expander_needs_measures() {
1319        assert!(Expander::new(&Stream::with_kind(StreamKind::Part)).is_err());
1320    }
1321
1322    #[test]
1323    fn a_stream_with_no_measures_is_refused() {
1324        assert!(
1325            Stream::with_kind(StreamKind::Part)
1326                .expand_repeats()
1327                .is_err()
1328        );
1329    }
1330}