1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
//! Typed construction and validation failures.
use crate::{AggregateRuleKind, AlphabetId, ProjectionId};
use sim_lib_discrete_rank::RankAdapterError;
use thiserror::Error;
/// Failure while defining an alphabet or registering its stable identity.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum AlphabetError {
/// An alphabet id was empty or did not use the stable portable syntax.
#[error("invalid alphabet id {value:?}: {reason}")]
InvalidId {
/// Rejected id text.
value: String,
/// Specific syntax violation.
reason: &'static str,
},
/// A finite musical alphabet contained no symbols.
#[error("alphabet {id} must contain at least one symbol")]
Empty {
/// Stable id of the empty alphabet.
id: AlphabetId,
},
/// The same symbol occupied two canonical alphabet positions.
#[error("alphabet {id} repeats positions {first} and {duplicate}")]
DuplicateSymbol {
/// Stable alphabet id.
id: AlphabetId,
/// First canonical position.
first: usize,
/// Repeated canonical position.
duplicate: usize,
},
/// A registry already contained the stable id being inserted.
#[error("duplicate alphabet id {0}")]
DuplicateId(AlphabetId),
}
/// Failure while compiling symbolic aggregate-rule data for one alphabet.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum AggregateRuleError {
/// The alphabet itself was invalid.
#[error(transparent)]
Alphabet(#[from] AlphabetError),
/// A declaration named a symbol outside the alphabet.
#[error("aggregate declaration contains a foreign symbol for alphabet {alphabet_id}")]
ForeignSymbol {
/// Stable alphabet id.
alphabet_id: AlphabetId,
},
/// The same symbol was declared more than once.
#[error("aggregate declaration repeats alphabet position {position}")]
DuplicateDeclaration {
/// Canonical alphabet position identified from the supplied symbol.
position: usize,
},
/// A multiplicity declaration omitted an alphabet symbol.
#[error("aggregate declaration is missing alphabet position {position}")]
MissingDeclaration {
/// Canonical alphabet position without a declaration.
position: usize,
},
/// A multiplicity was zero where the selected rule requires presence.
#[error("aggregate declaration gives zero multiplicity at alphabet position {position}")]
ZeroMultiplicity {
/// Canonical alphabet position with zero multiplicity.
position: usize,
},
/// An omission rule named no omitted symbols.
#[error("declared-omissions rule must omit at least one symbol")]
NoOmissions,
/// A rule omitted every symbol and could not admit a musical series.
#[error("aggregate rule omits every symbol in alphabet {0}")]
OmitsEverything(AlphabetId),
/// Projected class identity did not use the stable portable syntax.
#[error("invalid projection id {value:?}: {reason}")]
InvalidProjectionId {
/// Rejected projection id text.
value: String,
/// Specific syntax violation.
reason: &'static str,
},
/// Two projected classes reused the same stable id.
#[error("duplicate projected class id {0}")]
DuplicateProjectionId(ProjectionId),
/// A projected class had no source symbols.
#[error("projected class {0} must contain at least one symbol")]
EmptyProjectionClass(ProjectionId),
/// An alphabet symbol was assigned to more than one projected class.
#[error("alphabet position {position} belongs to multiple projected classes")]
DuplicateProjectionMember {
/// Canonical alphabet position assigned twice.
position: usize,
},
/// An alphabet symbol was not assigned to a projected class.
#[error("alphabet position {position} has no projected class")]
MissingProjectionMember {
/// Canonical alphabet position without a class.
position: usize,
},
/// Declared multiplicities overflowed the platform series length.
#[error("aggregate multiplicity total exceeds the supported series length")]
MultiplicityOverflow,
/// The rule's declarations were compiled for another alphabet identity.
#[error("aggregate rule belongs to {rule_id}, not {series_id}")]
AlphabetMismatch {
/// Alphabet id retained by the rule.
rule_id: AlphabetId,
/// Alphabet id supplied to series construction.
series_id: AlphabetId,
},
/// The rule's declarations were compiled for another alphabet cardinality.
#[error("aggregate rule expects alphabet size {expected}, got {found}")]
CardinalityMismatch {
/// Cardinality retained by the rule.
expected: usize,
/// Cardinality supplied to series construction.
found: usize,
},
}
/// Failure while validating or ranking a symbol-bearing series.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum SeriesError {
/// The supplied alphabet was invalid.
#[error(transparent)]
Alphabet(#[from] AlphabetError),
/// The aggregate rule was invalid for the supplied alphabet.
#[error(transparent)]
Rule(#[from] AggregateRuleError),
/// A series position contained a symbol outside the alphabet.
#[error("series position {position} is foreign to alphabet {alphabet_id}")]
ForeignSymbol {
/// Position in the supplied series order.
position: usize,
/// Stable alphabet id.
alphabet_id: AlphabetId,
},
/// A no-repeat rule encountered a repeated symbol.
#[error("series position {position} repeats position {first}")]
RepeatedSymbol {
/// Position of the repeated occurrence.
position: usize,
/// Position of the first occurrence.
first: usize,
},
/// Series length differed from the rule's declared total.
#[error("aggregate rule expects {expected} symbols, got {found}")]
WrongLength {
/// Required number of series positions.
expected: usize,
/// Supplied number of series positions.
found: usize,
},
/// An alphabet symbol occurred a different number of times than declared.
#[error("alphabet position {alphabet_position} occurs {found} times; expected {expected}")]
MultiplicityMismatch {
/// Canonical position of the affected symbol.
alphabet_position: usize,
/// Required number of occurrences.
expected: usize,
/// Observed number of occurrences.
found: usize,
},
/// A projected class occurred a different number of times than declared.
#[error("projected class {class_id} occurs {found} times; expected {expected}")]
ProjectionMismatch {
/// Stable projected class id.
class_id: ProjectionId,
/// Required number of occurrences.
expected: usize,
/// Observed number of occurrences.
found: usize,
},
/// The valid series is not an exactly-once permutation of its alphabet.
#[error("series is not an exactly-once permutation of alphabet {0}")]
NotPermutation(AlphabetId),
/// The shared discrete permutation-rank adapter rejected the request.
#[error(transparent)]
Rank(#[from] RankAdapterError),
}
/// Failure while validating or composing a finite ordinal map.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum OrdinalMapError {
/// An ordinal selected a position outside the finite domain.
#[error("ordinal map output {output} selects input {input} outside 0..{cardinality}")]
OutOfRange {
/// Output position containing the invalid ordinal.
output: usize,
/// Rejected input position.
input: usize,
/// Finite domain cardinality.
cardinality: usize,
},
/// Two output positions selected the same input position.
#[error("ordinal map selects input {input} at outputs {first_output} and {duplicate_output}")]
DuplicateInput {
/// Repeated input position.
input: usize,
/// First output selecting it.
first_output: usize,
/// Later output selecting it.
duplicate_output: usize,
},
/// A map was applied to a slice with another cardinality.
#[error("ordinal map expects cardinality {expected}, got {found}")]
CardinalityMismatch {
/// Validated map cardinality.
expected: usize,
/// Supplied slice cardinality.
found: usize,
},
/// Two maps over different domains cannot be composed.
#[error("cannot compose ordinal maps of cardinalities {first} and {second}")]
CompositionCardinalityMismatch {
/// First map cardinality.
first: usize,
/// Second map cardinality.
second: usize,
},
}
/// Failure while validating an ordered block partition.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum BlockPartitionError {
/// One declared block contained no positions.
#[error("block partition block {block} must not be empty")]
EmptyBlock {
/// Position of the empty block in declaration order.
block: usize,
},
/// Flattened blocks did not cover the declared finite domain.
#[error("block partition expects {expected} positions, got {found}")]
CardinalityMismatch {
/// Declared source cardinality.
expected: usize,
/// Number of declared positions.
found: usize,
},
/// Contiguous block lengths overflowed the platform cardinality.
#[error("block partition cardinality exceeds the supported series length")]
CardinalityOverflow,
/// The flattened block order was not a complete ordinal bijection.
#[error(transparent)]
OrdinalMap(#[from] OrdinalMapError),
}
/// Failure while validating a caller-supplied alphabet bijection.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum SymbolBijectionError {
/// A source or target alphabet was invalid.
#[error(transparent)]
Alphabet(#[from] AlphabetError),
/// Source and target alphabets had different cardinalities.
#[error(
"symbol bijection source cardinality {source_cardinality} differs from target {target_cardinality}"
)]
CardinalityMismatch {
/// Source alphabet cardinality.
source_cardinality: usize,
/// Target alphabet or map cardinality.
target_cardinality: usize,
},
/// A supplied source symbol was outside the source alphabet.
#[error("symbol bijection contains a foreign source symbol for alphabet {alphabet_id}")]
ForeignSourceSymbol {
/// Source alphabet identity.
alphabet_id: AlphabetId,
},
/// A supplied target symbol was outside the target alphabet.
#[error("symbol bijection contains a foreign target symbol for alphabet {alphabet_id}")]
ForeignTargetSymbol {
/// Target alphabet identity.
alphabet_id: AlphabetId,
},
/// One source position was declared more than once.
#[error("symbol bijection repeats source position {position}")]
DuplicateSource {
/// Repeated source position.
position: usize,
},
/// Two source symbols selected the same target position.
#[error("symbol bijection repeats target position {position}")]
DuplicateTarget {
/// Repeated target position.
position: usize,
},
/// A source position had no mapping.
#[error("symbol bijection is missing source position {position}")]
MissingSource {
/// Unmapped source position.
position: usize,
},
/// A target position had no preimage.
#[error("symbol bijection is missing target position {position}")]
MissingTarget {
/// Unmapped target position.
position: usize,
},
/// The internal ordinal spelling was not a bijection.
#[error(transparent)]
OrdinalMap(#[from] OrdinalMapError),
}
/// Failure while applying, inverting, or composing a series transform.
#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum SeriesTransformError {
/// A positional permutation was invalid for the series.
#[error(transparent)]
OrdinalMap(#[from] OrdinalMapError),
/// A symbolic relabeling was not a complete bijection.
#[error(transparent)]
Bijection(#[from] SymbolBijectionError),
/// Aggregate data could not be rebound to the target alphabet.
#[error(transparent)]
Rule(#[from] AggregateRuleError),
/// The transformed value did not satisfy its preserved aggregate rule.
#[error(transparent)]
Series(#[from] SeriesError),
/// An alphabet-bound relabeling was applied to another source alphabet.
#[error("transform expects source alphabet {expected}, got {found}")]
SourceAlphabetMismatch {
/// Alphabet bound into the relabeling.
expected: AlphabetId,
/// Alphabet retained by the supplied series.
found: AlphabetId,
},
/// Two alphabet relabelings did not meet at the same intermediate alphabet.
#[error("cannot compose relabeling to {first_target} with relabeling from {second_source}")]
CompositionAlphabetMismatch {
/// Target of the first relabeling.
first_target: AlphabetId,
/// Source of the second relabeling.
second_source: AlphabetId,
},
/// Private rule data disagreed with its public rule category.
#[error("aggregate rule data is missing for category {0:?}")]
RuleKindMismatch(AggregateRuleKind),
}