use crate::atomic;
use crate::error;
pub(crate) fn cast_binary_arithmetic(
a: atomic::Atomic,
b: atomic::Atomic,
) -> error::Result<(atomic::Atomic, atomic::Atomic)> {
let a = cast_untyped_arithmetic(a)?;
let b = cast_untyped_arithmetic(b)?;
cast_binary(a, b)
}
pub(crate) fn cast_binary_compare(
a: atomic::Atomic,
b: atomic::Atomic,
) -> error::Result<(atomic::Atomic, atomic::Atomic)> {
let a = cast_untyped_compare(a);
let b = cast_untyped_compare(b);
cast_binary(a, b)
}
fn cast_untyped_arithmetic(value: atomic::Atomic) -> error::Result<atomic::Atomic> {
if let atomic::Atomic::Untyped(s) = value {
atomic::Atomic::parse_atomic::<f64>(&s)
} else {
Ok(value)
}
}
fn cast_untyped_compare(value: atomic::Atomic) -> atomic::Atomic {
if let atomic::Atomic::Untyped(s) = value {
atomic::Atomic::String(atomic::StringType::String, s)
} else {
value
}
}
fn cast_binary(
a: atomic::Atomic,
b: atomic::Atomic,
) -> error::Result<(atomic::Atomic, atomic::Atomic)> {
use atomic::Atomic::*;
match (&a, &b) {
(Decimal(_), Float(_)) | (Integer(_, _), Float(_)) => Ok((a.cast_to_float()?, b)),
(Float(_), Decimal(_)) | (Float(_), Integer(_, _)) => Ok((a, b.cast_to_float()?)),
(Decimal(_), Double(_)) | (Integer(_, _), Double(_)) | (Float(_), Double(_)) => {
Ok((a.cast_to_double()?, b))
}
(Double(_), Decimal(_)) | (Double(_), Integer(_, _)) | (Double(_), Float(_)) => {
Ok((a, b.cast_to_double()?))
}
(Decimal(_), Integer(_, _)) => Ok((a, b.cast_to_decimal()?)),
(Integer(_, _), Decimal(_)) => Ok((a.cast_to_decimal()?, b)),
(DateTimeStamp(_), DateTime(_)) => Ok((a.cast_to_date_time()?, b)),
(DateTime(_), DateTimeStamp(_)) => Ok((a, b.cast_to_date_time()?)),
_ => Ok((a, b)),
}
}