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
//! Data table implementation.

use crate::{access, clone, err::Error, file::Save};
use std::{fmt::Display, fs::File, io::Write, ops::AddAssign, path::Path};

/// Table of row data.
pub struct Table<T> {
    /// Count data.
    rows: Vec<Vec<T>>,
    /// Number of columns.
    num_cols: usize,
}

impl<T> Table<T> {
    access!(rows, Vec<Vec<T>>);
    clone!(num_cols, usize);

    /// Construct a new instance.
    #[inline]
    #[must_use]
    pub fn new(rows: Vec<Vec<T>>) -> Self {
        debug_assert!(!rows.is_empty());
        let num_cols = rows[0].len();
        for row in &rows {
            debug_assert!(row.len() == num_cols);
        }

        Self { rows, num_cols }
    }

    /// Deconstruct the table and yield the inner rows vector.
    #[allow(clippy::missing_const_for_fn)]
    #[inline]
    #[must_use]
    pub fn into_inner(self) -> Vec<Vec<T>> {
        self.rows
    }
}

impl<T: AddAssign + Clone> AddAssign<&Self> for Table<T> {
    #[inline]
    fn add_assign(&mut self, rhs: &Self) {
        debug_assert!(self.rows.len() == rhs.rows.len());
        debug_assert!(self.num_cols == rhs.num_cols);

        for (lhs, rhs) in self.rows.iter_mut().zip(&rhs.rows) {
            for (l, r) in lhs.iter_mut().zip(rhs) {
                *l += r.clone();
            }
        }
    }
}

impl<T: Display> Save for Table<T> {
    #[inline]
    fn save_data(&self, path: &Path) -> Result<(), Error> {
        let mut file = File::create(path)?;

        for row in &self.rows {
            let mut iter = row.iter();
            if let Some(x) = iter.next() {
                write!(file, "{:>32}", x)?;
            }

            for x in iter {
                write!(file, ", {:>32}", x)?;
            }
            writeln!(file)?;
        }

        Ok(())
    }
}