use crate::dataframe::DataFrame;
use crate::types::Value;
use crate::VeloxxError;
#[derive(Debug, Clone)]
pub enum Condition {
Eq(String, Value),
Gt(String, Value),
Lt(String, Value),
And(Box<Condition>, Box<Condition>),
Or(Box<Condition>, Box<Condition>),
Not(Box<Condition>),
}
impl Condition {
pub fn evaluate(&self, df: &DataFrame, row_index: usize) -> Result<bool, VeloxxError> {
match self {
Condition::Eq(col_name, value) => {
let series = df
.get_column(col_name)
.ok_or(VeloxxError::ColumnNotFound(col_name.to_string()))?;
let cell_value = series.get_value(row_index);
Ok(cell_value.as_ref() == Some(value))
}
Condition::Gt(col_name, value) => {
let series = df
.get_column(col_name)
.ok_or(VeloxxError::ColumnNotFound(col_name.to_string()))?;
let cell_value = series.get_value(row_index);
match (cell_value.as_ref(), value) {
(Some(Value::I32(a)), Value::I32(b)) => Ok(a > b),
(Some(Value::F64(a)), Value::F64(b)) => Ok(a > b),
_ => Err(VeloxxError::InvalidOperation(format!(
"Cannot compare {cell_value:?} and {value:?}"
))),
}
}
Condition::Lt(col_name, value) => {
let series = df
.get_column(col_name)
.ok_or(VeloxxError::ColumnNotFound(col_name.to_string()))?;
let cell_value = series.get_value(row_index);
match (cell_value.as_ref(), value) {
(Some(Value::I32(a)), Value::I32(b)) => Ok(a < b),
(Some(Value::F64(a)), Value::F64(b)) => Ok(a < b),
_ => Err(VeloxxError::InvalidOperation(format!(
"Cannot compare {cell_value:?} and {value:?}"
))),
}
}
Condition::And(left, right) => {
Ok(left.evaluate(df, row_index)? && right.evaluate(df, row_index)?)
}
Condition::Or(left, right) => {
Ok(left.evaluate(df, row_index)? || right.evaluate(df, row_index)?)
}
Condition::Not(cond) => Ok(!cond.evaluate(df, row_index)?),
}
}
}