csvx 0.1.17

Comma-Separated Values eXtended
Documentation
use super::*;

pub struct Node {
    leaf: Box<ThreadSafeNode>,
    old_dependents_range: Option<(usize, usize, usize, usize)>,
}

impl super::Node for Node {
    fn new(seqs: Vec<Vec<Token>>) -> (Box<ThreadSafeNode>, Vec<(usize, usize)>) {
        let (leaf, leaf_refs) = parse(&seqs[0]);
        (
            Box::new(Self {
                leaf,
                old_dependents_range: None,
            }),
            leaf_refs,
        )
    }

    fn calc(
        &mut self,
        calculated_table: &Vec<Vec<Value>>,
    ) -> (Value, Vec<(usize, usize)>, Vec<(usize, usize)>) {
        let mut leaf = self.leaf.calc(calculated_table);

        if let Some((x1, y1, x2, y2)) = self.old_dependents_range {
            leaf.1.append(&mut compute_refs_from_range(x1, y1, x2, y2));
        }

        let value = match leaf.0 {
            Value::Range(x1, y1, x2, y2) => {
                leaf.2.append(&mut compute_refs_from_range(x1, y1, x2, y2));
                self.old_dependents_range = Some((x1, y1, x2, y2));

                let rx: Vec<usize> = (x1.min(x2)..=x1.max(x2)).collect();
                let ry: Vec<usize> = (y1.min(y2)..=y1.max(y2)).collect();

                ry.iter().fold(Value::Integer(0), |b, y| {
                    if let Some(row) = calculated_table.get(*y) {
                        let sum_of_row =
                            rx.iter()
                                .fold(Value::Integer(0), |b, x| match (b, row.get(*x)) {
                                    (Value::Integer(b), Some(Value::Integer(item))) => {
                                        Value::Integer(b + item)
                                    }
                                    (Value::Integer(b), Some(Value::Float(item))) => {
                                        Value::Float(b as f64 + item)
                                    }
                                    (Value::Float(b), Some(Value::Integer(item))) => {
                                        Value::Float(b + *item as f64)
                                    }
                                    (Value::Float(b), Some(Value::Float(item))) => {
                                        Value::Float(b + item)
                                    }
                                    _ => Value::Error,
                                });

                        match (b, sum_of_row) {
                            (Value::Integer(b), Value::Integer(row)) => Value::Integer(b + row),
                            (Value::Integer(b), Value::Float(row)) => Value::Float(b as f64 + row),
                            (Value::Float(b), Value::Integer(row)) => Value::Float(b + row as f64),
                            (Value::Float(b), Value::Float(row)) => Value::Float(b + row),
                            _ => Value::Error,
                        }
                    } else {
                        Value::Error
                    }
                })
            }
            _ => Value::Error,
        };

        (value, leaf.1, leaf.2)
    }
}