Skip to main content

music21_rs/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_rs::bar::{Barline, RepeatDirection};
28    /// use music21_rs::{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_rs::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_rs::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::new(&measures);
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    /// A copy, which no ending names.
247    fn copy(&self) -> Self {
248        Self {
249            original: None,
250            ..self.clone()
251        }
252    }
253
254    fn left_repeat(&self) -> Option<RepeatDirection> {
255        self.measure
256            .left_barline()
257            .and_then(Barline::repeat_direction)
258    }
259
260    fn right_repeat(&self) -> Option<RepeatDirection> {
261        self.measure
262            .right_barline()
263            .and_then(Barline::repeat_direction)
264    }
265
266    /// music21's `_stripRepeatBarlines`: a repeat barline made a double one.
267    fn strip_repeat_barlines(&mut self) {
268        if self.left_repeat().is_some() {
269            self.measure
270                .set_left_barline(Some(Barline::new(BarlineType::Double)));
271        }
272        if self.right_repeat().is_some() {
273            self.measure
274                .set_right_barline(Some(Barline::new(BarlineType::Double)));
275        }
276    }
277
278    /// music21's `_stripRepeatExpressions`, on one measure.
279    fn strip_repeat_expressions(&mut self) {
280        let events: Vec<StreamEvent> = self
281            .measure
282            .events
283            .iter()
284            .filter(|event| !matches!(event.element, StreamElement::RepeatExpression(_)))
285            .cloned()
286            .collect();
287        let spanners = self.measure.labels.spanners.clone();
288        self.measure = self.measure.with_events(events);
289        self.measure.labels.spanners = spanners;
290        self.stripped = true;
291    }
292
293    /// The kinds of the jumps and markers standing in the measure itself.
294    fn expressions(&self) -> Vec<RepeatExpressionKind> {
295        self.measure
296            .events
297            .iter()
298            .filter_map(|event| match &event.element {
299                StreamElement::RepeatExpression(expression) => Some(expression.kind()),
300                _ => None,
301            })
302            .collect()
303    }
304}
305
306/// A first, second or later ending, by the measures of the part it spans.
307#[derive(Clone, Debug)]
308struct Bracket {
309    numbers: Vec<u32>,
310    measures: Vec<usize>,
311}
312
313impl Bracket {
314    fn is_first(&self, working: &Working) -> bool {
315        working.original.is_some() && working.original == self.measures.first().copied()
316    }
317
318    fn is_last(&self, working: &Working) -> bool {
319        working.original.is_some() && working.original == self.measures.last().copied()
320    }
321
322    fn spans(&self, working: &Working) -> bool {
323        working
324            .original
325            .is_some_and(|original| self.measures.contains(&original))
326    }
327}
328
329/// A group of endings played in turn after one passage, with the places of
330/// the measures from the first ending's start to each ending's end.
331#[derive(Clone, Debug, Default)]
332struct Group {
333    brackets: Vec<usize>,
334    indices: Vec<usize>,
335}
336
337struct Expander {
338    source: Vec<Working>,
339    brackets: Vec<Bracket>,
340    counts: std::collections::HashMap<RepeatExpressionKind, usize>,
341}
342
343/// music21's `_daCapoOrSegno`.
344#[derive(Clone, Copy, Debug, PartialEq, Eq)]
345enum Jump {
346    DaCapo,
347    Segno,
348}
349
350impl Expander {
351    fn new(measures: &[(FloatType, &Stream)]) -> Self {
352        let source: Vec<Working> = measures
353            .iter()
354            .enumerate()
355            .map(|(index, (_, measure))| Working {
356                measure: (*measure).clone(),
357                original: Some(index),
358                source: index,
359                stripped: false,
360                appended_length: None,
361            })
362            .collect();
363        // A bracket opens on a measure whose ending starts and closes on one
364        // whose ending stops; music21's spanner spans those measures, and
365        // only those, as the reader marks them.
366        let mut brackets: Vec<Bracket> = Vec::new();
367        let mut open = false;
368        for (index, working) in source.iter().enumerate() {
369            let Some(ending) = working.measure.ending() else {
370                continue;
371            };
372            match brackets.last_mut() {
373                Some(bracket) if open && !ending.starts() => bracket.measures.push(index),
374                _ => brackets.push(Bracket {
375                    numbers: ending.numbers().to_vec(),
376                    measures: vec![index],
377                }),
378            }
379            open = !ending.stops();
380        }
381        let mut counts = std::collections::HashMap::new();
382        for working in &source {
383            for (_, element) in working.measure.leaves() {
384                if let StreamElement::RepeatExpression(expression) = element {
385                    *counts.entry(expression.kind()).or_insert(0) += 1;
386                }
387            }
388        }
389        Self {
390            source,
391            brackets,
392            counts,
393        }
394    }
395
396    fn count(&self, kind: RepeatExpressionKind) -> usize {
397        self.counts.get(&kind).copied().unwrap_or(0)
398    }
399
400    /// music21's `process`: the measures played out, or `None` where there
401    /// is nothing to play out.
402    fn process(&self) -> Result<Option<Vec<Working>>> {
403        match self.is_expandable()? {
404            Some(false) => Err(Error::Stream(
405                "cannot expand Stream: badly formed repeats or repeat expressions".to_string(),
406            )),
407            None => Ok(None),
408            Some(true) => match self.da_capo_or_segno() {
409                None => self
410                    .process_recursive_repeat_bars(self.source.clone())
411                    .map(Some),
412                Some(jump) => self
413                    .process_repeat_expression_and_repeats(self.source.clone(), jump)
414                    .map(Some),
415            },
416        }
417    }
418
419    fn da_capo_or_segno(&self) -> Option<Jump> {
420        use RepeatExpressionKind::*;
421        let da_capo = self.count(DaCapo) + self.count(DaCapoAlFine) + self.count(DaCapoAlCoda);
422        let segno = self.count(DalSegno)
423            + self.count(DalSegnoAlCoda)
424            + self.count(DalSegnoAlFine)
425            + self.count(AlSegno);
426        match (da_capo, segno) {
427            (1, 0) => Some(Jump::DaCapo),
428            (0, 1) => Some(Jump::Segno),
429            _ => None,
430        }
431    }
432
433    /// music21's `isExpandable`: `None` where there is nothing to play out.
434    fn is_expandable(&self) -> Result<Option<bool>> {
435        let jump = self.da_capo_or_segno();
436        if jump.is_none() && !has_repeat(&self.source) {
437            return Ok(None);
438        }
439        if !self.repeat_bars_are_coherent()? || !self.repeat_brackets_are_coherent() {
440            return Ok(Some(false));
441        }
442        Ok(Some(match jump {
443            Some(Jump::DaCapo) => self.da_capo_is_coherent(),
444            Some(Jump::Segno) => self.dal_segno_is_coherent(),
445            None => true,
446        }))
447    }
448
449    fn repeat_bars_are_coherent(&self) -> Result<bool> {
450        let (mut starts, mut ends, mut balance) = (0, 0, 0);
451        for working in &self.source {
452            match working.left_repeat() {
453                Some(RepeatDirection::Start) => {
454                    starts += 1;
455                    balance += 1;
456                }
457                Some(RepeatDirection::End) => {
458                    if balance == 0 {
459                        starts += 1;
460                        balance += 1;
461                    }
462                    ends += 1;
463                    balance -= 1;
464                }
465                None => {}
466            }
467            match working.right_repeat() {
468                Some(RepeatDirection::End) => {
469                    if balance == 0 {
470                        starts += 1;
471                        balance += 1;
472                    }
473                    ends += 1;
474                    balance -= 1;
475                }
476                Some(RepeatDirection::Start) => {
477                    return Err(Error::Stream(format!(
478                        "a right barline is found that cannot be processed: measure {}",
479                        working.measure.number_with_suffix()
480                    )));
481                }
482                None => {}
483            }
484        }
485        Ok(matches!(balance, 0 | 1) && (starts == ends || starts + 1 == ends))
486    }
487
488    fn da_capo_is_coherent(&self) -> bool {
489        use RepeatExpressionKind::*;
490        let total = self.count(DaCapo) + self.count(DaCapoAlFine) + self.count(DaCapoAlCoda);
491        if total > 1 {
492            return false;
493        }
494        (self.count(DaCapo) == 1 && self.count(Coda) == 0)
495            || (self.count(DaCapoAlFine) == 1 && self.count(Fine) == 1)
496            || (self.count(DaCapoAlCoda) == 1 && self.count(Coda) == 2)
497    }
498
499    fn dal_segno_is_coherent(&self) -> bool {
500        use RepeatExpressionKind::*;
501        let total = self.count(AlSegno)
502            + self.count(DalSegno)
503            + self.count(DalSegnoAlCoda)
504            + self.count(DalSegnoAlFine);
505        if total > 1 {
506            return false;
507        }
508        let (segnos, codas, fines) = (self.count(Segno), self.count(Coda), self.count(Fine));
509        (self.count(AlSegno) == 1 && segnos == 1 && codas == 0)
510            || (self.count(DalSegno) == 1 && segnos == 1 && codas == 0)
511            || (self.count(DalSegnoAlFine) == 1 && codas == 0 && segnos == 1 && fines == 1)
512            || (self.count(DalSegnoAlCoda) == 1 && codas == 2 && segnos == 1 && fines == 0)
513    }
514
515    /// music21's `_groupRepeatBracketIndices`.
516    fn group_bracket_indices(&self, measures: &[Working]) -> Vec<Group> {
517        let mut groups = Vec::new();
518        let mut found_numbers: Vec<u32> = Vec::new();
519        let mut group = Group::default();
520        for (index, working) in measures.iter().enumerate() {
521            for (bracket_index, bracket) in self.brackets.iter().enumerate() {
522                if !bracket.is_first(working) {
523                    continue;
524                }
525                if bracket
526                    .numbers
527                    .first()
528                    .is_some_and(|first| found_numbers.contains(first))
529                {
530                    groups.push(std::mem::take(&mut group));
531                    found_numbers.clear();
532                }
533                found_numbers.extend(&bracket.numbers);
534                group.brackets.push(bracket_index);
535                for (sub, candidate) in measures.iter().enumerate() {
536                    if bracket.is_last(candidate) {
537                        group.indices.push(sub);
538                        break;
539                    }
540                    if sub >= index {
541                        group.indices.push(sub);
542                    }
543                }
544            }
545        }
546        // music21 keeps the group it was building whatever it holds.
547        groups.push(group);
548        groups
549    }
550
551    fn repeat_brackets_are_coherent(&self) -> bool {
552        for group in self.group_bracket_indices(&self.source) {
553            if group.brackets.is_empty() {
554                return true;
555            }
556            if group.brackets.len() > 1 {
557                let numbers: Vec<u32> = group
558                    .brackets
559                    .iter()
560                    .flat_map(|index| self.brackets[*index].numbers.clone())
561                    .collect();
562                let highest = numbers.iter().copied().max().unwrap_or(0);
563                if numbers != (1..=highest).collect::<Vec<_>>() {
564                    return false;
565                }
566            }
567            let mut spanned: Vec<usize> = Vec::new();
568            for (count, index) in group.brackets.iter().enumerate() {
569                let bracket = &self.brackets[*index];
570                for measure in &bracket.measures {
571                    if spanned.contains(measure) {
572                        return false;
573                    }
574                    spanned.push(*measure);
575                }
576                let last =
577                    &self.source[*bracket.measures.last().expect("an ending spans a measure")];
578                if last.right_repeat().is_none()
579                    && (group.brackets.len() == 1 || count + 1 < group.brackets.len())
580                {
581                    return false;
582                }
583            }
584        }
585        true
586    }
587
588    /// music21's `findInnermostRepeatIndices`.
589    fn innermost_repeat_indices(measures: &[Working]) -> Vec<usize> {
590        let mut starts: Vec<usize> = Vec::new();
591        for (index, working) in measures.iter().enumerate() {
592            match working.left_repeat() {
593                Some(RepeatDirection::Start) => starts.push(index),
594                Some(RepeatDirection::End) => {
595                    return (starts.last().copied().unwrap_or(0)..index).collect();
596                }
597                None => {}
598            }
599            if working.right_repeat() == Some(RepeatDirection::End) {
600                return (starts.last().copied().unwrap_or(0)..=index).collect();
601            }
602        }
603        Vec::new()
604    }
605
606    /// music21's `_getEndRepeatBar`: whether the measure closing the repeat
607    /// is the last one repeated, and how many times it is played.
608    fn end_repeat_bar(measures: &[Working], index: usize) -> Result<(bool, u32)> {
609        let last = &measures[index];
610        if last.right_repeat() == Some(RepeatDirection::End) {
611            let times = last.measure.right_barline().and_then(Barline::repeat_times);
612            return Ok((true, times.unwrap_or(2)));
613        }
614        let Some(after) = measures.get(index + 1) else {
615            return Err(Error::Stream(format!(
616                "cannot find an end Repeat bar after the given end: {index}"
617            )));
618        };
619        if after.left_repeat() == Some(RepeatDirection::End) {
620            let times = after.measure.left_barline().and_then(Barline::repeat_times);
621            return Ok((false, times.unwrap_or(2)));
622        }
623        Err(Error::Stream(
624            "cannot find an end Repeat bar in the expected position".to_string(),
625        ))
626    }
627
628    /// music21's `processInnermostRepeatBars`.
629    fn process_innermost_repeat_bars(
630        measures: &mut [Working],
631        forced: Option<(&[usize], u32)>,
632        expansion_only: bool,
633    ) -> Result<Vec<Working>> {
634        let indices: Vec<usize> = match forced {
635            Some((indices, _)) => indices.to_vec(),
636            None => Self::innermost_repeat_indices(measures),
637        };
638        let mut out = Vec::new();
639        let mut strip_next = false;
640        let mut times_given = forced.map(|(_, times)| times);
641        let mut index = 0;
642        while index < measures.len() {
643            let (Some(&first), Some(&last)) = (indices.first(), indices.last()) else {
644                break;
645            };
646            if index == first {
647                let (closes_itself, times_found) = match Self::end_repeat_bar(measures, last) {
648                    Ok(found) => found,
649                    Err(error) if forced.is_none() => return Err(error),
650                    // A forced run with no repeat bar at its end: music21
651                    // leaves its last and its end-barline measure as `None`,
652                    // which counts as the same measure.
653                    Err(_) => (true, 2),
654                };
655                let times = *times_given.get_or_insert(times_found);
656                for time in 0..times {
657                    for &place in &indices {
658                        let mut copy = measures[place].copy();
659                        if place == first || place == last {
660                            copy.strip_repeat_barlines();
661                        }
662                        if times >= 2 && time < times - 1 {
663                            copy.strip_repeat_expressions();
664                        }
665                        if time != 0 {
666                            let letter = char::from(b'a' + ((time - 1) % 26) as u8);
667                            copy.measure.set_number_suffix(Some(letter.to_string()));
668                        }
669                        out.push(copy);
670                    }
671                }
672                if !closes_itself {
673                    strip_next = true;
674                }
675                index = last + 1;
676            } else {
677                if !expansion_only {
678                    if strip_next {
679                        measures[index].strip_repeat_barlines();
680                        strip_next = false;
681                    }
682                    out.push(measures[index].clone());
683                }
684                index += 1;
685            }
686        }
687        Ok(out)
688    }
689
690    /// music21's `_processInnermostRepeatsAndBrackets`.
691    fn process_innermost_repeats_and_brackets(
692        &self,
693        mut measures: Vec<Working>,
694        done: &mut Vec<usize>,
695    ) -> Result<Vec<Working>> {
696        let groups = self.group_bracket_indices(&measures);
697        let innermost = Self::innermost_repeat_indices(&measures);
698        let mut focus: Option<Group> = None;
699        if let (Some(&first), Some(&last)) = (innermost.first(), innermost.last()) {
700            for group in &groups {
701                for &bracket in &group.brackets {
702                    if done.contains(&bracket) {
703                        break;
704                    }
705                    let spans = &self.brackets[bracket];
706                    if spans.spans(&measures[first]) || spans.spans(&measures[last]) {
707                        focus = Some(group.clone());
708                        break;
709                    }
710                }
711                if focus.is_some() {
712                    break;
713                }
714            }
715        }
716        let Some(focus) = focus else {
717            return Self::process_innermost_repeat_bars(&mut measures, None, false);
718        };
719        let start = innermost[0];
720        let mut boundaries: Vec<(usize, Vec<usize>, Vec<usize>)> = Vec::new();
721        for &bracket_index in &focus.brackets {
722            done.push(bracket_index);
723            let bracket = &self.brackets[bracket_index];
724            let mut end = None;
725            let mut bracket_start = None;
726            for (index, working) in measures.iter().enumerate() {
727                if bracket.is_last(working) {
728                    end = Some(index);
729                }
730                if bracket.is_first(working) {
731                    bracket_start = Some(index);
732                }
733            }
734            let (Some(end), Some(bracket_start)) = (end, bracket_start) else {
735                return Err(Error::Stream(
736                    "failed to find start or end index of bracket expansion".to_string(),
737                ));
738            };
739            let mut indices: Vec<usize> = (start..=end).collect();
740            for (_, _, earlier) in &boundaries {
741                indices.retain(|index| !earlier.contains(index));
742            }
743            boundaries.push((bracket_index, indices, (bracket_start..=end).collect()));
744        }
745        let mut repeats: Vec<Vec<Working>> = Vec::new();
746        let mut highest = None;
747        for (bracket_index, indices, _) in &boundaries {
748            let times = self.brackets[*bracket_index].numbers.len() as u32;
749            repeats.push(Self::process_innermost_repeat_bars(
750                &mut measures,
751                Some((indices, times)),
752                true,
753            )?);
754            highest = indices.iter().copied().max();
755        }
756        let mut out: Vec<Working> = measures[..start].to_vec();
757        for sub in repeats {
758            for mut working in sub {
759                working.strip_repeat_barlines();
760                out.push(working);
761            }
762        }
763        if let Some(highest) = highest {
764            out.extend(measures[highest + 1..].iter().cloned());
765        }
766        Ok(out)
767    }
768
769    /// music21's `_processRecursiveRepeatBars`.
770    fn process_recursive_repeat_bars(&self, mut measures: Vec<Working>) -> Result<Vec<Working>> {
771        let mut done: Vec<usize> = Vec::new();
772        for _ in 0..100 {
773            measures = self.process_innermost_repeats_and_brackets(measures, &mut done)?;
774            if !has_repeat(&measures) {
775                break;
776            }
777        }
778        Ok(measures)
779    }
780
781    /// music21's `_processRepeatExpressionAndRepeats`: the passage up to the
782    /// jump, then from where it jumps to on to the fine, the end or the
783    /// first coda and on from the second.
784    fn process_repeat_expression_and_repeats(
785        &self,
786        measures: Vec<Working>,
787        jump: Jump,
788    ) -> Result<Vec<Working>> {
789        use RepeatExpressionKind::*;
790        let command = [
791            DaCapo,
792            DaCapoAlCoda,
793            DaCapoAlFine,
794            AlSegno,
795            DalSegno,
796            DalSegnoAlCoda,
797            DalSegnoAlFine,
798        ]
799        .into_iter()
800        .find(|kind| self.count(*kind) == 1)
801        .ok_or_else(|| Error::Stream("no repeat command found".to_string()))?;
802        let index_of = |kind: RepeatExpressionKind| -> Vec<usize> {
803            measures
804                .iter()
805                .enumerate()
806                .flat_map(|(index, working)| {
807                    working
808                        .expressions()
809                        .into_iter()
810                        .filter(move |found| *found == kind)
811                        .map(move |_| index)
812                })
813                .collect()
814        };
815        let missing =
816            || Error::Stream("a repeat expression is not where it is expected".to_string());
817        let jump_back = *index_of(command).first().ok_or_else(missing)?;
818        let start = match jump {
819            Jump::DaCapo => 0,
820            Jump::Segno => *index_of(Segno).first().ok_or_else(missing)?,
821        };
822        let last = measures.len() - 1;
823        let end = if matches!(command, DaCapoAlFine | DalSegnoAlFine) {
824            *index_of(Fine).first().ok_or_else(missing)?
825        } else {
826            last
827        };
828        let mut segments = vec![(0, jump_back)];
829        if matches!(command, DaCapoAlCoda | DalSegnoAlCoda) {
830            let codas = index_of(Coda);
831            let (Some(&jump_from), Some(&resume)) = (codas.first(), codas.get(1)) else {
832                return Err(missing());
833            };
834            segments.push((start, jump_from));
835            segments.push((resume, last));
836        } else {
837            segments.push((start, end));
838        }
839
840        let mut number: IntegerType = measures[0].measure.number();
841        let mut out = Vec::new();
842        for (count, (from, to)) in segments.into_iter().enumerate() {
843            let mut segment: Vec<Working> = Vec::new();
844            for working in measures.iter().take(to + 1).skip(from) {
845                let mut copy = working.copy();
846                copy.measure.set_number(number);
847                segment.push(copy);
848                number += 1;
849            }
850            if has_repeat(&segment) {
851                // music21 plays the repeats after the jump only where the
852                // jump says to, and none of its jumps do.
853                if count != 1 {
854                    segment = self.process_recursive_repeat_bars(segment)?;
855                    number = segment
856                        .last()
857                        .map_or(number, |last| last.measure.number() + 1);
858                }
859                for working in &mut segment {
860                    working.strip_repeat_barlines();
861                }
862            }
863            out.extend(segment);
864        }
865        for working in &mut out {
866            working.appended_length = Some(working.measure.end_offset());
867            working.strip_repeat_expressions();
868        }
869        Ok(out)
870    }
871}
872
873/// music21's `_hasRepeat`.
874fn has_repeat(measures: &[Working]) -> bool {
875    measures.iter().any(|working| {
876        working.left_repeat().is_some() || working.right_repeat() == Some(RepeatDirection::End)
877    })
878}
879
880#[cfg(test)]
881mod tests {
882    use crate::bar::{Barline, Ending, RepeatDirection};
883    use crate::repeat::{RepeatExpression, RepeatExpressionKind};
884    use crate::stream::{Stream, StreamElement, StreamKind};
885    use crate::{Duration, Note};
886
887    /// A part of whole-note measures numbered from one, each shaped by
888    /// `shape` from its number.
889    fn part(count: i32, shape: impl Fn(i32, &mut Stream)) -> Stream {
890        let mut part = Stream::with_kind(StreamKind::Part);
891        for number in 1..=count {
892            let mut measure = Stream::with_kind(StreamKind::Measure);
893            measure.set_number(number);
894            measure.push(
895                Note::from_name("C4")
896                    .unwrap()
897                    .with_duration(Duration::whole()),
898            );
899            shape(number, &mut measure);
900            part.insert(f64::from(number - 1) * 4.0, measure);
901        }
902        part
903    }
904
905    fn played(part: &Stream) -> Vec<String> {
906        part.expand_repeats()
907            .unwrap()
908            .measures()
909            .iter()
910            .map(|measure| measure.number_with_suffix())
911            .collect()
912    }
913
914    #[test]
915    fn a_passage_between_repeat_barlines_is_played_twice() {
916        let part = part(4, |number, measure| match number {
917            2 => measure.set_left_barline(Some(Barline::repeat(RepeatDirection::Start, None))),
918            3 => measure.set_right_barline(Some(Barline::repeat(RepeatDirection::End, None))),
919            _ => {}
920        });
921        assert_eq!(played(&part), ["1", "2", "3", "2a", "3a", "4"]);
922        let expanded = part.expand_repeats().unwrap();
923        // Laid end to end, and the repeat barlines made double ones.
924        assert_eq!(expanded.end_offset(), 24.0);
925        assert!(
926            expanded.measures()[2]
927                .right_barline()
928                .unwrap()
929                .repeat_direction()
930                .is_none()
931        );
932    }
933
934    #[test]
935    fn a_first_ending_is_played_then_the_second() {
936        let part = part(4, |number, measure| match number {
937            2 => {
938                measure.set_ending(Some(Ending::new(vec![1], true, true)));
939                measure.set_right_barline(Some(Barline::repeat(RepeatDirection::End, None)));
940            }
941            3 => measure.set_ending(Some(Ending::new(vec![2], true, true))),
942            _ => {}
943        });
944        // Each ending's run is played once, so music21 numbers neither
945        // time through with a suffix.
946        assert_eq!(played(&part), ["1", "2", "1", "3", "4"]);
947    }
948
949    #[test]
950    fn da_capo_al_fine_goes_back_to_the_fine() {
951        let part = part(3, |number, measure| {
952            let mark = match number {
953                1 => RepeatExpressionKind::Fine,
954                3 => RepeatExpressionKind::DaCapoAlFine,
955                _ => return,
956            };
957            measure.insert(
958                0.0,
959                StreamElement::RepeatExpression(RepeatExpression::new(mark)),
960            );
961        });
962        // Renumbered on from the first, and the marks taken out.
963        assert_eq!(played(&part), ["1", "2", "3", "4"]);
964        let expanded = part.expand_repeats().unwrap();
965        assert!(
966            expanded
967                .recurse()
968                .iter()
969                .all(|(_, element)| !matches!(element, StreamElement::RepeatExpression(_)))
970        );
971    }
972
973    #[test]
974    fn repeats_that_do_not_pair_up_are_refused() {
975        let part = part(3, |number, measure| {
976            if number != 2 {
977                measure.set_left_barline(Some(Barline::repeat(RepeatDirection::Start, None)));
978            }
979        });
980        assert!(part.expand_repeats().is_err());
981    }
982
983    #[test]
984    fn a_stream_with_no_measures_is_refused() {
985        assert!(
986            Stream::with_kind(StreamKind::Part)
987                .expand_repeats()
988                .is_err()
989        );
990    }
991}