ironcalc_base/sheet_data/
chunks.rs1use std::borrow::Cow;
5
6use bitcode::{Decode, Encode};
7
8use super::row::Row;
9use crate::constants::LAST_ROW;
10use crate::types::Cell;
11
12const CHUNK_BITS: u32 = 10;
13const CHUNK_ROWS: usize = 1 << CHUNK_BITS;
14const CHUNK_MASK: usize = CHUNK_ROWS - 1;
15
16#[derive(Encode, Decode, Debug, Clone, Default)]
27pub struct SheetData {
28 chunks: Vec<Option<Box<Chunk>>>,
30 row_count: usize,
32}
33
34#[derive(Encode, Decode, Debug, Clone)]
35struct Chunk {
36 rows: Vec<Option<Row>>,
38 used: usize,
40}
41
42impl Chunk {
43 fn new() -> Self {
44 let mut rows = Vec::new();
45 rows.resize_with(CHUNK_ROWS, || None);
46 Chunk { rows, used: 0 }
47 }
48}
49
50#[inline]
52fn locate(row: i32) -> Option<(usize, usize)> {
53 if !(1..=LAST_ROW).contains(&row) {
54 return None;
55 }
56 let row = row as usize;
57 Some((row >> CHUNK_BITS, row & CHUNK_MASK))
58}
59
60impl SheetData {
61 pub fn new() -> Self {
62 Self::default()
63 }
64
65 #[inline]
66 pub(super) fn row(&self, row: i32) -> Option<&Row> {
67 let (chunk, index) = locate(row)?;
68 self.chunks.get(chunk)?.as_ref()?.rows[index].as_ref()
69 }
70
71 #[inline]
72 fn row_mut(&mut self, row: i32) -> Option<&mut Row> {
73 let (chunk, index) = locate(row)?;
74 self.chunks.get_mut(chunk)?.as_mut()?.rows[index].as_mut()
75 }
76
77 fn row_or_insert(&mut self, row: i32) -> Option<&mut Row> {
79 let (chunk, index) = locate(row)?;
80 if chunk >= self.chunks.len() {
81 self.chunks.resize_with(chunk + 1, || None);
82 }
83 let chunk = self.chunks[chunk].get_or_insert_with(|| Box::new(Chunk::new()));
84 if chunk.rows[index].is_none() {
85 chunk.rows[index] = Some(Row::default());
86 chunk.used += 1;
87 self.row_count += 1;
88 }
89 chunk.rows[index].as_mut()
90 }
91
92 fn rows_in_order(&self) -> impl Iterator<Item = (i32, &Row)> {
94 self.chunks
95 .iter()
96 .enumerate()
97 .filter_map(|(chunk_index, chunk)| Some((chunk_index, chunk.as_ref()?)))
98 .flat_map(|(chunk_index, chunk)| {
99 chunk
100 .rows
101 .iter()
102 .enumerate()
103 .filter_map(move |(index, row)| {
104 let number = (chunk_index << CHUNK_BITS) | index;
105 Some((number as i32, row.as_ref()?))
106 })
107 })
108 }
109
110 #[inline]
112 pub fn cell(&self, row: i32, column: i32) -> Option<Cow<'_, Cell>> {
113 self.row(row)?.get(column)
114 }
115
116 pub fn cell_mut(&mut self, row: i32, column: i32) -> Option<&mut Cell> {
118 self.row_mut(row)?.get_mut(column)
119 }
120
121 pub fn set_cell(&mut self, row: i32, column: i32, cell: Cell) -> Option<Cell> {
123 self.row_or_insert(row)?.insert(column, cell)
124 }
125
126 pub fn remove_cell(&mut self, row: i32, column: i32) -> Option<Cell> {
128 let row_data = self.row_mut(row)?;
129 let cell = row_data.remove(column)?;
130 if row_data.is_empty() {
131 self.remove_row(row);
132 }
133 Some(cell)
134 }
135
136 pub fn is_empty(&self) -> bool {
138 self.row_count == 0
139 }
140
141 pub fn cells(&self) -> impl Iterator<Item = (i32, i32, Cow<'_, Cell>)> {
144 self.rows_in_order().flat_map(|(row, row_data)| {
145 row_data
146 .iter()
147 .map(move |(column, cell)| (row, column, cell))
148 })
149 }
150
151 pub fn rows(&self) -> Vec<i32> {
153 self.rows_in_order().map(|(row, _)| row).collect()
154 }
155
156 pub fn columns_in_row(&self, row: i32) -> Vec<i32> {
158 match self.row(row) {
159 Some(row_data) => row_data.iter().map(|(column, _)| column).collect(),
160 None => Vec::new(),
161 }
162 }
163
164 pub fn cells_in_row(&self, row: i32) -> Vec<(i32, Cow<'_, Cell>)> {
166 match self.row(row) {
167 Some(row_data) => row_data.iter().collect(),
168 None => Vec::new(),
169 }
170 }
171
172 pub fn cells_in_row_between(
176 &self,
177 row: i32,
178 first_column: i32,
179 last_column: i32,
180 ) -> impl Iterator<Item = (i32, Cow<'_, Cell>)> {
181 self.row(row)
182 .map(|row_data| row_data.iter_from(first_column))
183 .into_iter()
184 .flatten()
185 .take_while(move |(column, _)| *column <= last_column)
186 }
187
188 #[inline]
192 pub fn numbers_in_row_between(
193 &self,
194 row: i32,
195 first_column: i32,
196 last_column: i32,
197 ) -> Option<&[f64]> {
198 match self.row(row)? {
199 Row::Numbers {
200 first_column: row_first_column,
201 values,
202 ..
203 } => {
204 let first = Row::offset(*row_first_column, values, first_column)?;
205 let last = Row::offset(*row_first_column, values, last_column)?;
206 values.get(first..=last)
207 }
208 Row::Cells(_) => None,
209 }
210 }
211
212 pub fn remove_row(&mut self, row: i32) {
214 let Some((chunk_index, index)) = locate(row) else {
215 return;
216 };
217 let Some(Some(chunk)) = self.chunks.get_mut(chunk_index) else {
218 return;
219 };
220 if chunk.rows[index].take().is_some() {
221 chunk.used -= 1;
222 self.row_count -= 1;
223 if chunk.used == 0 {
224 self.chunks[chunk_index] = None;
225 }
226 }
227 }
228
229 pub fn set_row(&mut self, row: i32, cells: impl IntoIterator<Item = (i32, Cell)>) {
232 let Some(row_data) = self.row_or_insert(row) else {
233 return;
234 };
235 let mut cells: Vec<(i32, Cell)> = cells.into_iter().collect();
239 if !cells.is_sorted_by(|earlier, later| earlier.0 < later.0) {
242 cells.sort_by_key(|(column, _)| *column);
243 cells.dedup_by(|later, earlier| {
246 if later.0 == earlier.0 {
247 std::mem::swap(&mut later.1, &mut earlier.1);
248 true
249 } else {
250 false
251 }
252 });
253 }
254 cells.shrink_to_fit();
255 *row_data = Row::from_cells(cells);
256 }
257}
258
259impl PartialEq for SheetData {
262 fn eq(&self, other: &Self) -> bool {
263 self.row_count == other.row_count && self.rows_in_order().eq(other.rows_in_order())
264 }
265}