1use crate::core::CompiledFormula;
5use crate::core::SharedVec;
6use serde::{Deserialize, Serialize};
7
8use super::bitmask::Bitmask;
9use super::cell::generate_unique_id;
10use super::result_data::ResultData;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
25pub enum ColumnData {
26 Integer {
28 validity: Bitmask,
30 values: SharedVec<i64>,
32 },
33 Float {
35 validity: Bitmask,
37 values: SharedVec<f64>,
39 },
40 Any(SharedVec<ResultData>),
43}
44
45impl ColumnData {
46 pub(crate) fn new(size: usize) -> Self {
47 Self::Integer {
48 validity: Bitmask::with_size(size),
49 values: vec![0; size].into(),
50 }
51 }
52
53 pub fn len(&self) -> usize {
55 match self {
56 Self::Integer { validity, .. } => validity.len,
57 Self::Float { validity, .. } => validity.len,
58 Self::Any(v) => v.len(),
59 }
60 }
61
62 pub fn is_empty(&self) -> bool {
64 self.len() == 0
65 }
66
67 pub(crate) fn push(&mut self, value: ResultData) {
68 let index = self.len();
69 self.insert(index, value);
70 }
71
72 pub fn get(&self, index: usize) -> Option<ResultData> {
78 if index >= self.len() {
79 return None;
80 }
81 match self {
82 Self::Integer { validity, values } => {
83 if validity.get(index) {
84 Some(ResultData::Integer(values[index]))
85 } else {
86 Some(ResultData::None)
87 }
88 }
89 Self::Float { validity, values } => {
90 if validity.get(index) {
91 Some(ResultData::Float(values[index]))
92 } else {
93 Some(ResultData::None)
94 }
95 }
96 Self::Any(v) => Some(v[index].clone()),
97 }
98 }
99
100 pub(crate) fn demote_to_any(&mut self) {
101 let len = self.len();
102 let mut any = Vec::with_capacity(len);
103 for i in 0..len {
104 any.push(self.get(i).unwrap());
105 }
106 *self = Self::Any(any.into());
107 }
108
109 pub(crate) fn promote_to_float(&mut self) {
110 if let Self::Integer { validity, values } = self {
111 let float_values = values.iter().map(|&i| i as f64).collect();
112 *self = Self::Float {
113 validity: validity.clone(),
114 values: float_values,
115 };
116 }
117 }
118
119 pub(crate) fn resize(&mut self, size: usize) {
120 match self {
121 Self::Integer { validity, values } => {
122 values.resize(size, 0);
123 *validity = Bitmask::with_size(size);
124 }
125 Self::Float { validity, values } => {
126 values.resize(size, 0.0);
127 *validity = Bitmask::with_size(size);
128 }
129 Self::Any(v) => {
130 v.resize(size, ResultData::None);
131 }
132 }
133 }
134
135 pub(crate) fn set(&mut self, index: usize, value: ResultData) {
136 if index >= self.len() {
137 return;
138 }
139 match self {
140 Self::Integer { validity, values } => match value {
141 ResultData::Integer(i) => {
142 validity.set(index, true);
143 values[index] = i;
144 }
145 ResultData::Float(f) => {
146 self.promote_to_float();
147 self.set(index, ResultData::Float(f));
148 }
149 ResultData::None => {
150 validity.set(index, false);
151 values[index] = 0;
152 }
153 _ => {
154 self.demote_to_any();
155 if let Self::Any(v) = self {
156 v[index] = value;
157 }
158 }
159 },
160 Self::Float { validity, values } => match value {
161 ResultData::Float(f) => {
162 validity.set(index, true);
163 values[index] = f;
164 }
165 ResultData::Integer(i) => {
166 validity.set(index, true);
167 values[index] = i as f64;
168 }
169 ResultData::None => {
170 validity.set(index, false);
171 values[index] = 0.0;
172 }
173 _ => {
174 self.demote_to_any();
175 if let Self::Any(v) = self {
176 v[index] = value;
177 }
178 }
179 },
180 Self::Any(v) => {
181 v[index] = value;
182 }
183 }
184 }
185
186 pub(crate) fn insert(&mut self, index: usize, value: ResultData) {
187 match self {
188 Self::Integer { validity, values } => match value {
189 ResultData::Integer(i) => {
190 validity.insert(index, true);
191 values.insert(index, i);
192 }
193 ResultData::Float(f) => {
194 self.promote_to_float();
195 self.insert(index, ResultData::Float(f));
196 }
197 ResultData::None => {
198 validity.insert(index, false);
199 values.insert(index, 0);
200 }
201 _ => {
202 self.demote_to_any();
203 if let Self::Any(v) = self {
204 v.insert(index, value);
205 }
206 }
207 },
208 Self::Float { validity, values } => match value {
209 ResultData::Float(f) => {
210 validity.insert(index, true);
211 values.insert(index, f);
212 }
213 ResultData::Integer(i) => {
214 validity.insert(index, true);
215 values.insert(index, i as f64);
216 }
217 ResultData::None => {
218 validity.insert(index, false);
219 values.insert(index, 0.0);
220 }
221 _ => {
222 self.demote_to_any();
223 if let Self::Any(v) = self {
224 v.insert(index, value);
225 }
226 }
227 },
228 Self::Any(v) => {
229 v.insert(index, value);
230 }
231 }
232 }
233
234 pub(crate) fn remove(&mut self, index: usize) {
235 match self {
236 Self::Integer { validity, values } => {
237 validity.remove(index);
238 values.remove(index);
239 }
240 Self::Float { validity, values } => {
241 validity.remove(index);
242 values.remove(index);
243 }
244 Self::Any(v) => {
245 v.remove(index);
246 }
247 }
248 }
249
250 pub(crate) fn drain<R: std::ops::RangeBounds<usize> + Clone>(&mut self, range: R) {
251 match self {
252 Self::Integer { validity, values } => {
253 validity.drain(range.clone());
254 values.drain(range);
255 }
256 Self::Float { validity, values } => {
257 validity.drain(range.clone());
258 values.drain(range);
259 }
260 Self::Any(v) => {
261 v.drain(range);
262 }
263 }
264 }
265}
266
267impl Default for ColumnData {
268 fn default() -> Self {
269 Self::Integer {
270 validity: Bitmask::with_size(0),
271 values: SharedVec::new(),
272 }
273 }
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize)]
291pub struct DataColumn {
292 #[serde(default = "generate_unique_id")]
295 pub id: u64,
296 #[serde(default)]
298 pub name: String,
299 #[serde(skip, default)]
301 pub(crate) data: ColumnData,
302 pub(crate) src: SharedVec<String>,
305 #[serde(skip, default)]
307 pub(crate) compiled_src: SharedVec<CompiledFormula>,
308 #[serde(skip, default)]
310 pub(crate) dirty_indices: SharedVec<usize>,
311 #[serde(default)]
314 pub(crate) styles: SharedVec<Option<crate::core::CellStyle>>,
315}
316
317pub(crate) struct ColumnPosition {
318 pub row: usize,
319 pub char_offset: usize,
320}
321
322impl DataColumn {
323 pub fn new(size: usize) -> Self {
326 Self {
327 id: generate_unique_id(),
328 name: String::new(),
329 data: ColumnData::new(size),
330 src: vec![String::new(); size].into(),
331 compiled_src: vec![CompiledFormula::default(); size].into(),
332 dirty_indices: SharedVec::new(),
333 styles: vec![None; size].into(),
334 }
335 }
336
337 pub fn len(&self) -> usize {
339 self.src.len()
340 }
341
342 pub fn is_empty(&self) -> bool {
344 self.src.is_empty()
345 }
346
347 pub fn src(&self, row: usize) -> Option<&str> {
349 self.src.get(row).map(String::as_str)
350 }
351
352 pub fn value(&self, row: usize) -> Option<ResultData> {
357 self.data.get(row)
358 }
359
360 pub fn values(&self) -> &ColumnData {
363 &self.data
364 }
365
366 pub fn compiled(&self, row: usize) -> Option<&CompiledFormula> {
369 self.compiled_src.get(row)
370 }
371
372 pub fn style(&self, row: usize) -> Option<&crate::core::CellStyle> {
374 self.styles.get(row).and_then(Option::as_ref)
375 }
376
377 pub(crate) fn mark_dirty(&mut self, row: usize) {
378 if !self.dirty_indices.contains(&row) {
379 self.dirty_indices.push(row);
380 }
381 }
382
383 #[cfg(test)]
390 pub(crate) fn from_src(name: impl Into<String>, src: Vec<String>) -> Self {
391 let mut col = Self::new(src.len());
392 col.name = name.into();
393 col.src = src.into();
394 col
395 }
396
397 pub(crate) fn rebuild_after_load(&mut self) {
403 let size = self.src.len();
404 self.data.resize(size);
405 self.compiled_src = vec![CompiledFormula::default(); size].into();
406 self.styles.resize(size, None);
407 }
408
409 pub(crate) fn push_row(&mut self) {
411 self.src.push(String::new());
412 self.compiled_src.push(CompiledFormula::default());
413 self.data.push(ResultData::None);
414 self.styles.push(None);
415 }
416
417 pub(crate) fn insert_row(&mut self, index: usize) {
420 if index >= self.len() {
421 self.push_row();
422 return;
423 }
424 self.src.insert(index, String::new());
425 self.compiled_src.insert(index, CompiledFormula::default());
426 self.data.insert(index, ResultData::None);
427 self.styles.insert(index, None);
428 self.shift_dirty_after_insert(index, 1);
429 }
430
431 pub(crate) fn remove_row(&mut self, index: usize) {
434 if index >= self.len() {
435 return;
436 }
437 self.src.remove(index);
438 self.compiled_src.remove(index);
439 self.data.remove(index);
440 self.styles.remove(index);
441 self.drop_dirty_range(index, index + 1);
442 }
443
444 pub(crate) fn drain_rows<R: std::ops::RangeBounds<usize>>(&mut self, range: R) {
449 let start = match range.start_bound() {
450 std::ops::Bound::Included(&n) => n,
451 std::ops::Bound::Excluded(&n) => n + 1,
452 std::ops::Bound::Unbounded => 0,
453 };
454 let end = match range.end_bound() {
455 std::ops::Bound::Included(&n) => n + 1,
456 std::ops::Bound::Excluded(&n) => n,
457 std::ops::Bound::Unbounded => self.len(),
458 };
459 let start = start.min(self.len());
460 let end = end.min(self.len());
461 if start >= end {
462 return;
463 }
464 self.src.drain(start..end);
465 self.compiled_src.drain(start..end);
466 self.data.drain(start..end);
467 self.styles.drain(start..end);
468 self.drop_dirty_range(start, end);
469 }
470
471 pub(crate) fn resize_rows(&mut self, len: usize) {
474 while self.len() < len {
475 self.push_row();
476 }
477 if self.len() > len {
478 self.drain_rows(len..);
479 }
480 }
481
482 fn drop_dirty_range(&mut self, start: usize, end: usize) {
484 let removed = end - start;
485 self.dirty_indices.retain(|&i| i < start || i >= end);
486 for i in self.dirty_indices.iter_mut() {
487 if *i >= end {
488 *i -= removed;
489 }
490 }
491 }
492
493 fn shift_dirty_after_insert(&mut self, index: usize, count: usize) {
495 for i in self.dirty_indices.iter_mut() {
496 if *i >= index {
497 *i += count;
498 }
499 }
500 }
501
502 pub(crate) fn insert(&mut self, position: ColumnPosition, input: &str) {
504 let ColumnPosition { row, char_offset } = position;
505 let index = row;
506 if index < self.src.len() {
507 if self.src[index].is_empty() {
508 self.src[index].push_str(input);
509 } else {
510 self.src[index].insert_str(char_offset, input);
511 }
512 } else {
513 self.resize_rows(index + 1);
515 self.src[index] = input.to_string();
516 }
517 }
518}