1use 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 pub fn expand_repeats(&self) -> Result<Stream> {
56 if self.kind == StreamKind::Score || self.kind == StreamKind::Opus {
57 let mut expanded = Vec::new();
58 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 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 let Some(played) = expander.process()? else {
121 return Ok((self.clone(), (0..self.leaves().len()).map(Some).collect()));
122 };
123
124 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 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 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
222enum Origin {
224 Measure { source: usize, stripped: bool },
225 Loose(usize),
226}
227
228#[derive(Clone, Debug)]
232struct Working {
233 measure: Stream,
234 original: Option<usize>,
235 source: usize,
237 stripped: bool,
239 appended_length: Option<FloatType>,
243}
244
245impl Working {
246 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 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 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 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#[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#[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#[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 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 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 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 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 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 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 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 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 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 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 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 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 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
873fn 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 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 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 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 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}