tau_term_screen/
cell_row.rs1#[cfg(debug_assertions)]
2use std::cell::Cell as Counter;
3use std::ops::Deref;
4use std::sync::Arc;
5
6use crate::Cell;
7
8#[cfg(debug_assertions)]
9thread_local! {
10 static METRICS: Counter<CellRowMetrics> = const { Counter::new(CellRowMetrics::ZERO) };
11}
12
13#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
19pub struct CellRowMetrics {
20 pub allocations: usize,
22 pub pointer_clones: usize,
24 pub cell_copies: usize,
26}
27
28impl CellRowMetrics {
29 #[cfg(debug_assertions)]
30 const ZERO: Self = Self {
31 allocations: 0,
32 pointer_clones: 0,
33 cell_copies: 0,
34 };
35}
36
37#[derive(Debug, PartialEq, Eq)]
39pub struct CellRow {
40 cells: CellRowStorage,
42}
43
44#[derive(Debug, PartialEq, Eq)]
46enum CellRowStorage {
47 Empty,
49 Cells(Arc<Vec<Cell>>),
51}
52
53impl CellRow {
54 pub fn new(mut cells: Vec<Cell>) -> Self {
56 if cells.is_empty() {
57 return Self {
58 cells: CellRowStorage::Empty,
59 };
60 }
61 let needs_normalization = cells
62 .iter()
63 .any(|cell| Cell::sanitized_char(cell.ch) != cell.ch);
64 if needs_normalization {
65 let copied = cells.len();
66 cells = cells.iter().map(Cell::normalized).collect();
67 record_cell_copies(copied);
68 }
69 record_allocation();
70 Self {
71 cells: CellRowStorage::Cells(Arc::new(cells)),
72 }
73 }
74
75 pub fn metrics() -> Option<CellRowMetrics> {
80 metrics()
81 }
82
83 pub fn reset_metrics() {
87 reset_metrics();
88 }
89
90 pub fn shares_buffer_with(&self, other: &Self) -> bool {
94 match (&self.cells, &other.cells) {
95 (CellRowStorage::Empty, CellRowStorage::Empty) => true,
96 (CellRowStorage::Cells(left), CellRowStorage::Cells(right)) => Arc::ptr_eq(left, right),
97 _ => false,
98 }
99 }
100}
101
102impl Clone for CellRow {
103 fn clone(&self) -> Self {
104 if matches!(self.cells, CellRowStorage::Cells(_)) {
105 record_pointer_clone();
106 }
107 Self {
108 cells: match &self.cells {
109 CellRowStorage::Empty => CellRowStorage::Empty,
110 CellRowStorage::Cells(cells) => CellRowStorage::Cells(Arc::clone(cells)),
111 },
112 }
113 }
114}
115
116impl Deref for CellRow {
117 type Target = [Cell];
118
119 fn deref(&self) -> &Self::Target {
120 match &self.cells {
121 CellRowStorage::Empty => &[],
122 CellRowStorage::Cells(cells) => cells.as_slice(),
123 }
124 }
125}
126
127impl AsRef<[Cell]> for CellRow {
128 fn as_ref(&self) -> &[Cell] {
129 self
130 }
131}
132
133impl From<Vec<Cell>> for CellRow {
134 fn from(cells: Vec<Cell>) -> Self {
135 Self::new(cells)
136 }
137}
138
139impl PartialEq<Vec<Cell>> for CellRow {
140 fn eq(&self, other: &Vec<Cell>) -> bool {
141 self.as_ref() == other.as_slice()
142 }
143}
144
145impl CellRowMetrics {
146 #[cfg(debug_assertions)]
147 fn with_allocation(mut self) -> Self {
148 self.allocations += 1;
149 self
150 }
151
152 #[cfg(debug_assertions)]
153 fn with_pointer_clone(mut self) -> Self {
154 self.pointer_clones += 1;
155 self
156 }
157
158 #[cfg(debug_assertions)]
159 fn with_cell_copies(mut self, count: usize) -> Self {
160 self.cell_copies += count;
161 self
162 }
163}
164
165#[cfg(debug_assertions)]
166fn record_allocation() {
167 METRICS.set(METRICS.get().with_allocation());
168}
169
170#[cfg(not(debug_assertions))]
171fn record_allocation() {}
172
173#[cfg(debug_assertions)]
174fn record_pointer_clone() {
175 METRICS.set(METRICS.get().with_pointer_clone());
176}
177
178#[cfg(not(debug_assertions))]
179fn record_pointer_clone() {}
180
181#[cfg(debug_assertions)]
182fn record_cell_copies(count: usize) {
183 METRICS.set(METRICS.get().with_cell_copies(count));
184}
185
186#[cfg(not(debug_assertions))]
187fn record_cell_copies(_count: usize) {}
188
189#[cfg(debug_assertions)]
190fn metrics() -> Option<CellRowMetrics> {
191 Some(METRICS.get())
192}
193
194#[cfg(not(debug_assertions))]
195fn metrics() -> Option<CellRowMetrics> {
196 None
197}
198
199#[cfg(debug_assertions)]
200fn reset_metrics() {
201 METRICS.set(CellRowMetrics::ZERO);
202}
203
204#[cfg(not(debug_assertions))]
205fn reset_metrics() {}