use crate::core::CompiledFormula;
use crate::core::SharedVec;
use serde::{Deserialize, Serialize};
use super::bitmask::Bitmask;
use super::cell::generate_unique_id;
use super::result_data::ResultData;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ColumnData {
Integer {
validity: Bitmask,
values: SharedVec<i64>,
},
Float {
validity: Bitmask,
values: SharedVec<f64>,
},
Any(SharedVec<ResultData>),
}
impl ColumnData {
pub(crate) fn new(size: usize) -> Self {
Self::Integer {
validity: Bitmask::with_size(size),
values: vec![0; size].into(),
}
}
pub fn len(&self) -> usize {
match self {
Self::Integer { validity, .. } => validity.len,
Self::Float { validity, .. } => validity.len,
Self::Any(v) => v.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub(crate) fn push(&mut self, value: ResultData) {
let index = self.len();
self.insert(index, value);
}
pub fn get(&self, index: usize) -> Option<ResultData> {
if index >= self.len() {
return None;
}
match self {
Self::Integer { validity, values } => {
if validity.get(index) {
Some(ResultData::Integer(values[index]))
} else {
Some(ResultData::None)
}
}
Self::Float { validity, values } => {
if validity.get(index) {
Some(ResultData::Float(values[index]))
} else {
Some(ResultData::None)
}
}
Self::Any(v) => Some(v[index].clone()),
}
}
pub(crate) fn demote_to_any(&mut self) {
let len = self.len();
let mut any = Vec::with_capacity(len);
for i in 0..len {
any.push(self.get(i).unwrap());
}
*self = Self::Any(any.into());
}
pub(crate) fn promote_to_float(&mut self) {
if let Self::Integer { validity, values } = self {
let float_values = values.iter().map(|&i| i as f64).collect();
*self = Self::Float {
validity: validity.clone(),
values: float_values,
};
}
}
pub(crate) fn resize(&mut self, size: usize) {
match self {
Self::Integer { validity, values } => {
values.resize(size, 0);
*validity = Bitmask::with_size(size);
}
Self::Float { validity, values } => {
values.resize(size, 0.0);
*validity = Bitmask::with_size(size);
}
Self::Any(v) => {
v.resize(size, ResultData::None);
}
}
}
pub(crate) fn set(&mut self, index: usize, value: ResultData) {
if index >= self.len() {
return;
}
match self {
Self::Integer { validity, values } => match value {
ResultData::Integer(i) => {
validity.set(index, true);
values[index] = i;
}
ResultData::Float(f) => {
self.promote_to_float();
self.set(index, ResultData::Float(f));
}
ResultData::None => {
validity.set(index, false);
values[index] = 0;
}
_ => {
self.demote_to_any();
if let Self::Any(v) = self {
v[index] = value;
}
}
},
Self::Float { validity, values } => match value {
ResultData::Float(f) => {
validity.set(index, true);
values[index] = f;
}
ResultData::Integer(i) => {
validity.set(index, true);
values[index] = i as f64;
}
ResultData::None => {
validity.set(index, false);
values[index] = 0.0;
}
_ => {
self.demote_to_any();
if let Self::Any(v) = self {
v[index] = value;
}
}
},
Self::Any(v) => {
v[index] = value;
}
}
}
pub(crate) fn insert(&mut self, index: usize, value: ResultData) {
match self {
Self::Integer { validity, values } => match value {
ResultData::Integer(i) => {
validity.insert(index, true);
values.insert(index, i);
}
ResultData::Float(f) => {
self.promote_to_float();
self.insert(index, ResultData::Float(f));
}
ResultData::None => {
validity.insert(index, false);
values.insert(index, 0);
}
_ => {
self.demote_to_any();
if let Self::Any(v) = self {
v.insert(index, value);
}
}
},
Self::Float { validity, values } => match value {
ResultData::Float(f) => {
validity.insert(index, true);
values.insert(index, f);
}
ResultData::Integer(i) => {
validity.insert(index, true);
values.insert(index, i as f64);
}
ResultData::None => {
validity.insert(index, false);
values.insert(index, 0.0);
}
_ => {
self.demote_to_any();
if let Self::Any(v) = self {
v.insert(index, value);
}
}
},
Self::Any(v) => {
v.insert(index, value);
}
}
}
pub(crate) fn remove(&mut self, index: usize) {
match self {
Self::Integer { validity, values } => {
validity.remove(index);
values.remove(index);
}
Self::Float { validity, values } => {
validity.remove(index);
values.remove(index);
}
Self::Any(v) => {
v.remove(index);
}
}
}
pub(crate) fn drain<R: std::ops::RangeBounds<usize> + Clone>(&mut self, range: R) {
match self {
Self::Integer { validity, values } => {
validity.drain(range.clone());
values.drain(range);
}
Self::Float { validity, values } => {
validity.drain(range.clone());
values.drain(range);
}
Self::Any(v) => {
v.drain(range);
}
}
}
}
impl Default for ColumnData {
fn default() -> Self {
Self::Integer {
validity: Bitmask::with_size(0),
values: SharedVec::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataColumn {
#[serde(default = "generate_unique_id")]
pub id: u64,
#[serde(default)]
pub name: String,
#[serde(skip, default)]
pub(crate) data: ColumnData,
pub(crate) src: SharedVec<String>,
#[serde(skip, default)]
pub(crate) compiled_src: SharedVec<CompiledFormula>,
#[serde(skip, default)]
pub(crate) dirty_indices: SharedVec<usize>,
#[serde(default)]
pub(crate) styles: SharedVec<Option<crate::core::CellStyle>>,
}
pub(crate) struct ColumnPosition {
pub row: usize,
pub char_offset: usize,
}
impl DataColumn {
pub fn new(size: usize) -> Self {
Self {
id: generate_unique_id(),
name: String::new(),
data: ColumnData::new(size),
src: vec![String::new(); size].into(),
compiled_src: vec![CompiledFormula::default(); size].into(),
dirty_indices: SharedVec::new(),
styles: vec![None; size].into(),
}
}
pub fn len(&self) -> usize {
self.src.len()
}
pub fn is_empty(&self) -> bool {
self.src.is_empty()
}
pub fn src(&self, row: usize) -> Option<&str> {
self.src.get(row).map(String::as_str)
}
pub fn value(&self, row: usize) -> Option<ResultData> {
self.data.get(row)
}
pub fn values(&self) -> &ColumnData {
&self.data
}
pub fn compiled(&self, row: usize) -> Option<&CompiledFormula> {
self.compiled_src.get(row)
}
pub fn style(&self, row: usize) -> Option<&crate::core::CellStyle> {
self.styles.get(row).and_then(Option::as_ref)
}
pub(crate) fn mark_dirty(&mut self, row: usize) {
if !self.dirty_indices.contains(&row) {
self.dirty_indices.push(row);
}
}
#[cfg(test)]
pub(crate) fn from_src(name: impl Into<String>, src: Vec<String>) -> Self {
let mut col = Self::new(src.len());
col.name = name.into();
col.src = src.into();
col
}
pub(crate) fn rebuild_after_load(&mut self) {
let size = self.src.len();
self.data.resize(size);
self.compiled_src = vec![CompiledFormula::default(); size].into();
self.styles.resize(size, None);
}
pub(crate) fn push_row(&mut self) {
self.src.push(String::new());
self.compiled_src.push(CompiledFormula::default());
self.data.push(ResultData::None);
self.styles.push(None);
}
pub(crate) fn insert_row(&mut self, index: usize) {
if index >= self.len() {
self.push_row();
return;
}
self.src.insert(index, String::new());
self.compiled_src.insert(index, CompiledFormula::default());
self.data.insert(index, ResultData::None);
self.styles.insert(index, None);
self.shift_dirty_after_insert(index, 1);
}
pub(crate) fn remove_row(&mut self, index: usize) {
if index >= self.len() {
return;
}
self.src.remove(index);
self.compiled_src.remove(index);
self.data.remove(index);
self.styles.remove(index);
self.drop_dirty_range(index, index + 1);
}
pub(crate) fn drain_rows<R: std::ops::RangeBounds<usize>>(&mut self, range: R) {
let start = match range.start_bound() {
std::ops::Bound::Included(&n) => n,
std::ops::Bound::Excluded(&n) => n + 1,
std::ops::Bound::Unbounded => 0,
};
let end = match range.end_bound() {
std::ops::Bound::Included(&n) => n + 1,
std::ops::Bound::Excluded(&n) => n,
std::ops::Bound::Unbounded => self.len(),
};
let start = start.min(self.len());
let end = end.min(self.len());
if start >= end {
return;
}
self.src.drain(start..end);
self.compiled_src.drain(start..end);
self.data.drain(start..end);
self.styles.drain(start..end);
self.drop_dirty_range(start, end);
}
pub(crate) fn resize_rows(&mut self, len: usize) {
while self.len() < len {
self.push_row();
}
if self.len() > len {
self.drain_rows(len..);
}
}
fn drop_dirty_range(&mut self, start: usize, end: usize) {
let removed = end - start;
self.dirty_indices.retain(|&i| i < start || i >= end);
for i in self.dirty_indices.iter_mut() {
if *i >= end {
*i -= removed;
}
}
}
fn shift_dirty_after_insert(&mut self, index: usize, count: usize) {
for i in self.dirty_indices.iter_mut() {
if *i >= index {
*i += count;
}
}
}
pub(crate) fn insert(&mut self, position: ColumnPosition, input: &str) {
let ColumnPosition { row, char_offset } = position;
let index = row;
if index < self.src.len() {
if self.src[index].is_empty() {
self.src[index].push_str(input);
} else {
self.src[index].insert_str(char_offset, input);
}
} else {
self.resize_rows(index + 1);
self.src[index] = input.to_string();
}
}
}