1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use super::*;

impl Table {
    /// Build a CSVX table from a CSV string.
    ///
    /// # Example
    /// ```
    /// use csvx::Table;
    ///
    /// let raw_csv = "pi,3^5,\"ref(0,0)\",-(1/0)
    /// 12%5,\"pow(3,5)\",0/NaN,\"\"\"Apollo\"\"\"
    /// A1+A2,\"if(true , sqrt(25),round(if(false,1.1,2.5)))\",D2+1969,";
    /// println!("RAW CSV DATA:\n{}\n", raw_csv);
    ///
    /// let mut table = Table::new(raw_csv)?;
    /// println!("CALCULATED TABLE:\n{}", table);
    /// ```
    pub fn new<T: Borrow<str>>(raw_csv: T) -> Result<Self, Box<dyn Error>> {
        let mut reader = csv::ReaderBuilder::new()
            .has_headers(false)
            .from_reader(raw_csv.borrow().as_bytes());
        let mut raw_csv_table: Vec<Vec<String>> = vec![];

        for record in reader.records() {
            match record {
                Ok(record) => {
                    raw_csv_table.push(record.iter().map(|item| item.to_owned()).collect())
                }
                _ => return Err(Box::new(TableError::CSVParseError)),
            }
        }

        let mut raw_table = vec![];
        let mut tree_table = vec![];
        let mut ref_src_table = vec![];
        let mut dependents_table = vec![];
        let mut calculated_table = vec![];
        for raw_csv_line in raw_csv_table {
            let mut raw_line = vec![];
            let mut tree_line = vec![];
            let mut ref_src_line = vec![];
            let mut dependents_line = vec![];
            let mut calculated_line = vec![];
            for raw_item in raw_csv_line {
                let (tree, refs) = Self::build_tree(&raw_item);

                let mut dependents = HashMap::new();
                for dependent in refs {
                    *(dependents.entry(dependent).or_insert(0)) += 1;
                }

                raw_line.push(raw_item);
                ref_src_line.push(vec![]);
                dependents_line.push(dependents);
                tree_line.push(tree);
                calculated_line.push(Value::Error);
            }
            raw_table.push(raw_line);
            tree_table.push(tree_line);
            ref_src_table.push(ref_src_line);
            dependents_table.push(dependents_line);
            calculated_table.push(calculated_line);
        }

        for y in 0..ref_src_table.len() {
            for x in 0..ref_src_table[y].len() {
                for &(x_of_src, y_of_src) in dependents_table[y][x].keys() {
                    if y_of_src < ref_src_table.len() && x_of_src < ref_src_table[y].len() {
                        ref_src_table[y_of_src][x_of_src].push((x, y));
                    }
                }
            }
        }

        for y in 0..tree_table.len() {
            for x in 0..tree_table[y].len() {
                Self::calc(
                    x,
                    y,
                    &mut tree_table,
                    &mut ref_src_table,
                    &mut dependents_table,
                    &mut calculated_table,
                    &mut vec![],
                );
            }
        }

        Ok(Table {
            raw_table,
            tree_table,
            ref_src_table,
            dependents_table,
            calculated_table,
            current_pos_y: 0,
        })
    }
}