sim_lib_pitch_serial/error.rs
1//! Typed tone-row construction failures.
2
3use sim_lib_serial_core::{AlphabetError, OrdinalMapError, SeriesError};
4use thiserror::Error;
5
6/// Failure while constructing the canonical alphabet or a strict tone row.
7#[derive(Clone, Debug, PartialEq, Eq, Error)]
8pub enum RowError {
9 /// The canonical pitch-class alphabet could not be constructed.
10 #[error(transparent)]
11 Alphabet(#[from] AlphabetError),
12 /// The supplied row failed canonical membership or exactly-once validation.
13 #[error(transparent)]
14 Aggregate(#[from] SeriesError),
15 /// A caller-supplied ordinal permutation was not a complete bijection.
16 #[error(transparent)]
17 OrdinalMap(#[from] OrdinalMapError),
18 /// A contiguous row segment reached outside the twelve row positions.
19 #[error("segment start {start} with length {len} is out of bounds for a twelve-tone row")]
20 SegmentOutOfBounds {
21 /// Zero-based start ordinal requested by the caller.
22 start: usize,
23 /// Number of row positions requested from `start`.
24 len: usize,
25 },
26 /// A wrapped row segment exceeded the row length.
27 #[error("wrapped segment length {len} exceeds the row length")]
28 WrappedSegmentTooLong {
29 /// Number of row positions requested for the wrapped segment.
30 len: usize,
31 },
32 /// An indexed segment referenced an invalid row ordinal.
33 #[error("row ordinal {ordinal} is out of bounds for a twelve-tone row")]
34 InvalidOrdinal {
35 /// Zero-based row ordinal that fell outside `0..12`.
36 ordinal: usize,
37 },
38 /// A requested partition block contained no row ordinals.
39 #[error("partition block {block_index} is empty")]
40 EmptyPartitionBlock {
41 /// Zero-based block index in caller order.
42 block_index: usize,
43 },
44 /// A requested partition assigned one row ordinal to more than one block.
45 #[error(
46 "row ordinal {ordinal} appears in multiple partition blocks ({first_block_index} and {second_block_index})"
47 )]
48 DuplicatePartitionOrdinal {
49 /// Zero-based row ordinal that appeared more than once.
50 ordinal: u8,
51 /// First block index that claimed the ordinal.
52 first_block_index: usize,
53 /// Later block index that duplicated the ordinal.
54 second_block_index: usize,
55 },
56 /// A requested partition failed to cover the full row exactly once.
57 #[error("partition coverage is incomplete; missing row ordinals {missing:?}")]
58 PartitionCoverageMismatch {
59 /// Zero-based row ordinals that were not assigned to any block.
60 missing: Vec<u8>,
61 },
62 /// A derivation or combinatoriality partition size was unsupported.
63 #[error("partition size {size} is invalid; expected one of 2, 3, 4, or 6")]
64 InvalidPartitionSize {
65 /// The invalid partition size requested by the caller.
66 size: usize,
67 },
68}