use crate::csv_handler::CellRange;
use anyhow::Result;
pub trait DataReader: Send + Sync {
fn read(&self, path: &str) -> Result<Vec<Vec<String>>>;
fn read_with_headers(&self, path: &str) -> Result<Vec<Vec<String>>>;
fn read_range(&self, path: &str, range: &CellRange) -> Result<Vec<Vec<String>>>;
fn read_as_json(&self, path: &str) -> Result<String>;
fn supports_format(&self, path: &str) -> bool;
}
pub trait DataWriter: Send + Sync {
fn write(&self, path: &str, data: &[Vec<String>], options: DataWriteOptions) -> Result<()>;
fn write_range(
&self,
path: &str,
data: &[Vec<String>],
start_row: usize,
start_col: usize,
) -> Result<()>;
fn append(&self, path: &str, data: &[Vec<String>]) -> Result<()>;
fn supports_format(&self, path: &str) -> bool;
}
#[derive(Debug, Clone, Default)]
pub struct DataWriteOptions {
pub sheet_name: Option<String>,
pub column_names: Option<Vec<String>>,
pub include_headers: bool,
}
pub trait FileHandler: DataReader + DataWriter {
fn format_name(&self) -> &'static str;
fn supported_extensions(&self) -> &'static [&'static str];
}
pub trait FormatDetector: Send + Sync {
fn detect_format(&self, path: &str) -> Result<String>;
fn is_supported(&self, format: &str) -> bool;
fn supported_formats(&self) -> Vec<String>;
}
pub trait SchemaProvider: Send + Sync {
fn get_schema(&self, path: &str) -> Result<Vec<(String, String)>>;
fn get_column_names(&self, path: &str) -> Result<Vec<String>>;
fn get_row_count(&self, path: &str) -> Result<usize>;
fn get_column_count(&self, path: &str) -> Result<usize>;
}
pub trait StreamingReader: Send + Sync {
fn open(&self, path: &str) -> Result<Box<dyn StreamingReadIterator>>;
}
pub trait StreamingReadIterator: Iterator<Item = Result<Vec<String>>> {
fn current_row(&self) -> usize;
}
pub trait StreamingWriter: Send + Sync {
fn create(&self, path: &str) -> Result<Box<dyn StreamingWriteHandle>>;
}
pub trait StreamingWriteHandle: Send + Sync {
fn write_row(&mut self, row: &[String]) -> Result<()>;
fn rows_written(&self) -> usize;
fn flush(&mut self) -> Result<()>;
}
pub trait CellRangeProvider: Send + Sync {
fn parse_range(&self, range_str: &str) -> Result<CellRange>;
fn to_cell_reference(&self, row: usize, col: usize) -> String;
fn from_cell_reference(&self, cell: &str) -> Result<(usize, usize)>;
}
pub trait SortOperator: Send + Sync {
fn sort(&self, data: &mut Vec<Vec<String>>, column: usize, ascending: bool) -> Result<()>;
}
pub trait FilterOperator: Send + Sync {
fn filter(
&self,
data: &[Vec<String>],
column: usize,
condition: FilterCondition,
) -> Result<Vec<Vec<String>>>;
}
pub trait TransformOperator: Send + Sync {
fn transform(&self, data: &mut Vec<Vec<String>>, operation: TransformOperation) -> Result<()>;
}
pub trait DataOperator: SortOperator + FilterOperator + TransformOperator {}
#[derive(Debug, Clone)]
pub enum FilterCondition {
Equals(String),
NotEquals(String),
GreaterThan(String),
GreaterThanOrEqual(String),
LessThan(String),
LessThanOrEqual(String),
Contains(String),
StartsWith(String),
EndsWith(String),
Regex(String),
}
#[derive(Debug, Clone)]
pub enum TransformOperation {
RenameColumn {
from: usize,
to: String,
},
DropColumn(usize),
AddColumn {
name: String,
formula: Option<String>,
},
FillNa {
column: usize,
value: String,
},
}