sim_lib_pitch_serial/
render.rs1use std::fmt::Write;
4
5use crate::{
6 MatrixCoordinate, ROW_MATRIX_SIZE, RowLabelConvention, RowMatrix, RowMatrixCell,
7 RowMatrixEdgeLabels, RowOperation, ToneRow,
8};
9
10#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct RowMatrixData {
17 source: ToneRow,
18 convention: RowLabelConvention,
19 cells: Vec<RowMatrixCell>,
20 row_operations: [RowOperation; ROW_MATRIX_SIZE],
21 column_operations: [RowOperation; ROW_MATRIX_SIZE],
22 edge_labels: RowMatrixEdgeLabels,
23}
24
25impl RowMatrixData {
26 pub const fn source(&self) -> &ToneRow {
28 &self.source
29 }
30
31 pub const fn convention(&self) -> RowLabelConvention {
33 self.convention
34 }
35
36 pub fn cells(&self) -> &[RowMatrixCell] {
38 &self.cells
39 }
40
41 pub fn cell(&self, coordinate: MatrixCoordinate) -> &RowMatrixCell {
43 &self.cells[coordinate.row() * ROW_MATRIX_SIZE + coordinate.column()]
44 }
45
46 pub const fn row_operations(&self) -> &[RowOperation; ROW_MATRIX_SIZE] {
48 &self.row_operations
49 }
50
51 pub const fn column_operations(&self) -> &[RowOperation; ROW_MATRIX_SIZE] {
53 &self.column_operations
54 }
55
56 pub const fn edge_labels(&self) -> &RowMatrixEdgeLabels {
58 &self.edge_labels
59 }
60}
61
62impl RowMatrix {
63 pub fn render_data(&self) -> RowMatrixData {
65 let cells = (0..ROW_MATRIX_SIZE)
66 .flat_map(|row| {
67 (0..ROW_MATRIX_SIZE).map(move |column| {
68 let coordinate = MatrixCoordinate::new(row, column)
69 .expect("fixed matrix iteration always yields a valid coordinate");
70 self.cell(coordinate)
71 })
72 })
73 .collect();
74 let row_operations = std::array::from_fn(|row| {
75 self.row_operation(row)
76 .expect("fixed matrix iteration always yields a row operation")
77 });
78 let column_operations = std::array::from_fn(|column| {
79 self.column_operation(column)
80 .expect("fixed matrix iteration always yields a column operation")
81 });
82
83 RowMatrixData {
84 source: self.source().clone(),
85 convention: self.convention(),
86 cells,
87 row_operations,
88 column_operations,
89 edge_labels: *self.edge_labels(),
90 }
91 }
92
93 pub fn render_ascii(&self) -> String {
95 let data = self.render_data();
96 let mut output = String::new();
97 writeln!(output, "label-convention: {}", data.convention().as_str())
98 .expect("writing to a String cannot fail");
99 write!(output, "source:").expect("writing to a String cannot fail");
100 for class in data.source().classes() {
101 write!(output, " {:>2}", class.value()).expect("writing to a String cannot fail");
102 }
103 output.push('\n');
104
105 output.push_str(" ");
106 for label in data.edge_labels().top() {
107 write!(output, " {:>4}", label).expect("writing to a String cannot fail");
108 }
109 output.push('\n');
110
111 for row in 0..ROW_MATRIX_SIZE {
112 write!(output, "{:>4} |", data.edge_labels().left()[row])
113 .expect("writing to a String cannot fail");
114 for column in 0..ROW_MATRIX_SIZE {
115 let coordinate = MatrixCoordinate::new(row, column)
116 .expect("fixed matrix iteration always yields a valid coordinate");
117 write!(output, " {:>4}", data.cell(coordinate).class().value())
118 .expect("writing to a String cannot fail");
119 }
120 writeln!(output, " | {:<4}", data.edge_labels().right()[row])
121 .expect("writing to a String cannot fail");
122 }
123
124 output.push_str(" ");
125 for label in data.edge_labels().bottom() {
126 write!(output, " {:>4}", label).expect("writing to a String cannot fail");
127 }
128 output.push('\n');
129 output
130 }
131}