sim_lib_music_serial/
allowance.rs1use std::collections::BTreeSet;
4
5use sim_lib_pitch_core::PitchClass;
6
7use crate::OrdinalRef;
8
9#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct ReferentialSubsetAllowance {
12 pub id: String,
14 pub pitch_classes: BTreeSet<PitchClass>,
16}
17
18impl ReferentialSubsetAllowance {
19 pub fn new(
21 id: impl Into<String>,
22 pitch_classes: impl IntoIterator<Item = PitchClass>,
23 ) -> Result<Self, String> {
24 let id = id.into();
25 if id.trim().is_empty() {
26 return Err("referential subset id cannot be empty".to_owned());
27 }
28 let pitch_classes = pitch_classes.into_iter().collect::<BTreeSet<_>>();
29 if pitch_classes.is_empty() {
30 return Err("referential subset pitch classes cannot be empty".to_owned());
31 }
32 Ok(Self { id, pitch_classes })
33 }
34}
35
36#[derive(Clone, Debug, PartialEq, Eq)]
38pub enum SerialAllowanceKind {
39 CurrentPartition,
41 StatedPitchClasses,
43 AggregateRemainder,
45 ReferentialSubset {
47 id: String,
49 },
50 ModalProjection,
52 DerivedReservoir,
54 ExplicitForeignMaterial,
56}
57
58impl SerialAllowanceKind {
59 pub(crate) fn label(&self) -> String {
60 match self {
61 Self::CurrentPartition => "current-partition".to_owned(),
62 Self::StatedPitchClasses => "stated-pitch-classes".to_owned(),
63 Self::AggregateRemainder => "aggregate-remainder".to_owned(),
64 Self::ReferentialSubset { id } => format!("referential-subset/{id}"),
65 Self::ModalProjection => "modal-projection".to_owned(),
66 Self::DerivedReservoir => "derived-reservoir".to_owned(),
67 Self::ExplicitForeignMaterial => "explicit-foreign-material".to_owned(),
68 }
69 }
70}
71
72#[derive(Clone, Debug, PartialEq, Eq)]
74pub struct SerialAllowanceMatch {
75 pub kind: SerialAllowanceKind,
77 pub ordinals: Vec<OrdinalRef>,
79}
80
81#[derive(Clone, Debug, PartialEq, Eq)]
83pub struct SerialCompletionAllowances {
84 pub current_partition: bool,
86 pub stated_pitch_classes: bool,
88 pub aggregate_remainder: bool,
90 pub referential_subsets: Vec<ReferentialSubsetAllowance>,
92 pub modal_projection: bool,
94 pub derived_reservoir: bool,
96 pub explicitly_foreign_material: bool,
98}
99
100impl Default for SerialCompletionAllowances {
101 fn default() -> Self {
102 Self {
103 current_partition: true,
104 stated_pitch_classes: true,
105 aggregate_remainder: false,
106 referential_subsets: Vec::new(),
107 modal_projection: false,
108 derived_reservoir: false,
109 explicitly_foreign_material: false,
110 }
111 }
112}