Skip to main content

ironcalc_base/
calc_result.rs

1use std::cmp::Ordering;
2
3use crate::expressions::{parser::ArrayNode, token::Error, types::CellReferenceIndex};
4
5#[derive(Clone)]
6pub struct Range {
7    pub left: CellReferenceIndex,
8    pub right: CellReferenceIndex,
9}
10
11#[derive(Clone)]
12pub(crate) enum CalcResult {
13    String(String),
14    Number(f64),
15    Boolean(bool),
16    Error {
17        error: Error,
18        origin: CellReferenceIndex,
19        message: String,
20    },
21    Range {
22        left: CellReferenceIndex,
23        right: CellReferenceIndex,
24    },
25    EmptyCell,
26    EmptyArg,
27    Array(Vec<Vec<ArrayNode>>),
28    Lambda(usize),
29}
30
31impl CalcResult {
32    pub fn new_error(error: Error, origin: CellReferenceIndex, message: String) -> CalcResult {
33        CalcResult::Error {
34            error,
35            origin,
36            message,
37        }
38    }
39    pub fn new_args_number_error(origin: CellReferenceIndex) -> CalcResult {
40        CalcResult::Error {
41            error: Error::ERROR,
42            origin,
43            message: "Wrong number of arguments".to_string(),
44        }
45    }
46    pub fn is_error(&self) -> bool {
47        matches!(self, CalcResult::Error { .. })
48    }
49}
50
51impl Ord for CalcResult {
52    // ..., -2, -1, 0, 1, 2, ..., A-Z, FALSE, TRUE, empty;
53    fn cmp(&self, other: &Self) -> Ordering {
54        match (self, other) {
55            (CalcResult::Number(value1), CalcResult::Number(value2)) => {
56                if (value2 - value1).abs() < f64::EPSILON {
57                    return Ordering::Equal;
58                }
59                if value1 < value2 {
60                    return Ordering::Less;
61                }
62                Ordering::Greater
63            }
64            (CalcResult::Number(_value1), CalcResult::String(_value2)) => Ordering::Less,
65            (CalcResult::Number(_value1), CalcResult::Boolean(_value2)) => Ordering::Less,
66            (CalcResult::String(value1), CalcResult::String(value2)) => {
67                let value1 = value1.to_uppercase();
68                let value2 = value2.to_uppercase();
69                value1.cmp(&value2)
70            }
71            (CalcResult::String(_value1), CalcResult::Boolean(_value2)) => Ordering::Less,
72            (CalcResult::Boolean(value1), CalcResult::Boolean(value2)) => {
73                if value1 == value2 {
74                    return Ordering::Equal;
75                }
76                if *value1 {
77                    return Ordering::Greater;
78                }
79                Ordering::Less
80            }
81            (CalcResult::EmptyCell, CalcResult::String(_value2)) => Ordering::Greater,
82            (CalcResult::EmptyArg, CalcResult::String(_value2)) => Ordering::Greater,
83            (CalcResult::String(_value1), CalcResult::EmptyCell) => Ordering::Less,
84            (CalcResult::EmptyCell, CalcResult::Number(_value2)) => Ordering::Greater,
85            (CalcResult::EmptyArg, CalcResult::Number(_value2)) => Ordering::Greater,
86            (CalcResult::Number(_value1), CalcResult::EmptyCell) => Ordering::Less,
87            (CalcResult::EmptyCell, CalcResult::EmptyCell) => Ordering::Equal,
88            (CalcResult::EmptyCell, CalcResult::EmptyArg) => Ordering::Equal,
89            (CalcResult::EmptyArg, CalcResult::EmptyCell) => Ordering::Equal,
90            (CalcResult::EmptyArg, CalcResult::EmptyArg) => Ordering::Equal,
91            // NOTE: Errors and Ranges are not covered
92            (_, _) => Ordering::Greater,
93        }
94    }
95}
96
97impl PartialOrd for CalcResult {
98    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
99        Some(self.cmp(other))
100    }
101}
102
103impl PartialEq for CalcResult {
104    fn eq(&self, other: &Self) -> bool {
105        self.cmp(other) == Ordering::Equal
106    }
107}
108
109impl Eq for CalcResult {}