use crate::schema::CqlType;
use crate::types::Value;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum IntWidth {
Byte,
Short,
Int,
Long,
}
impl IntWidth {
fn narrow(self, sum: i64) -> Value {
match self {
IntWidth::Byte => Value::TinyInt(sum as i8),
IntWidth::Short => Value::SmallInt(sum as i16),
IntWidth::Int => Value::Integer(sum as i32),
IntWidth::Long => Value::BigInt(sum),
}
}
}
#[derive(Debug, Clone)]
pub(super) enum NumericAcc {
Integral { sum: i64, width: IntWidth },
Floating(f64),
}
impl NumericAcc {
pub(super) fn init(result_type: Option<&CqlType>) -> Self {
let width = match result_type {
Some(CqlType::TinyInt) => IntWidth::Byte,
Some(CqlType::SmallInt) => IntWidth::Short,
Some(CqlType::Int) => IntWidth::Int,
Some(CqlType::BigInt | CqlType::Counter) => IntWidth::Long,
_ => return NumericAcc::Floating(0.0),
};
NumericAcc::Integral { sum: 0, width }
}
pub(super) fn add(&mut self, value: &Value) -> bool {
match self {
NumericAcc::Integral { sum, .. } => match value.as_i64() {
Some(v) => {
*sum = sum.wrapping_add(v);
true
}
None => false,
},
NumericAcc::Floating(sum) => match value.as_f64() {
Some(v) => {
*sum += v;
true
}
None => false,
},
}
}
pub(super) fn finalize_sum(&self) -> Value {
match self {
NumericAcc::Integral { sum, width } => width.narrow(*sum),
NumericAcc::Floating(sum) => Value::Float(*sum),
}
}
pub(super) fn finalize_avg(&self, count: u64) -> Value {
debug_assert!(
count > 0,
"finalize_avg requires at least one accepted input"
);
match self {
NumericAcc::Integral { sum, width } => width.narrow(sum / count as i64),
NumericAcc::Floating(sum) => Value::Float(sum / count as f64),
}
}
}