use std::cmp::Ordering;
use crate::expressions::token::Error;
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub struct CellReference {
pub sheet: u32,
pub column: i32,
pub row: i32,
}
#[derive(Debug, Clone)]
pub struct Range {
pub left: CellReference,
pub right: CellReference,
}
#[derive(Clone)]
pub(crate) enum CalcResult {
String(String),
Number(f64),
Boolean(bool),
Error {
error: Error,
origin: CellReference,
message: String,
},
Range {
left: CellReference,
right: CellReference,
},
EmptyCell,
EmptyArg,
}
impl CalcResult {
pub fn new_error(error: Error, origin: CellReference, message: String) -> CalcResult {
CalcResult::Error {
error,
origin,
message,
}
}
pub fn new_args_number_error(origin: CellReference) -> CalcResult {
CalcResult::Error {
error: Error::ERROR,
origin,
message: "Wrong number of arguments".to_string(),
}
}
pub fn is_error(&self) -> bool {
matches!(self, CalcResult::Error { .. })
}
}
impl Ord for CalcResult {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(CalcResult::Number(value1), CalcResult::Number(value2)) => {
if (value2 - value1).abs() < f64::EPSILON {
return Ordering::Equal;
}
if value1 < value2 {
return Ordering::Less;
}
Ordering::Greater
}
(CalcResult::Number(_value1), CalcResult::String(_value2)) => Ordering::Less,
(CalcResult::Number(_value1), CalcResult::Boolean(_value2)) => Ordering::Less,
(CalcResult::String(value1), CalcResult::String(value2)) => {
let value1 = value1.to_uppercase();
let value2 = value2.to_uppercase();
value1.cmp(&value2)
}
(CalcResult::String(_value1), CalcResult::Boolean(_value2)) => Ordering::Less,
(CalcResult::Boolean(value1), CalcResult::Boolean(value2)) => {
if value1 == value2 {
return Ordering::Equal;
}
if *value1 {
return Ordering::Greater;
}
Ordering::Less
}
(CalcResult::EmptyCell, CalcResult::String(_value2)) => Ordering::Greater,
(CalcResult::EmptyArg, CalcResult::String(_value2)) => Ordering::Greater,
(CalcResult::String(_value1), CalcResult::EmptyCell) => Ordering::Less,
(CalcResult::EmptyCell, CalcResult::Number(_value2)) => Ordering::Greater,
(CalcResult::EmptyArg, CalcResult::Number(_value2)) => Ordering::Greater,
(CalcResult::Number(_value1), CalcResult::EmptyCell) => Ordering::Less,
(CalcResult::EmptyCell, CalcResult::EmptyCell) => Ordering::Equal,
(CalcResult::EmptyCell, CalcResult::EmptyArg) => Ordering::Equal,
(CalcResult::EmptyArg, CalcResult::EmptyCell) => Ordering::Equal,
(CalcResult::EmptyArg, CalcResult::EmptyArg) => Ordering::Equal,
(_, _) => Ordering::Greater,
}
}
}
impl PartialOrd for CalcResult {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for CalcResult {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Eq for CalcResult {}