1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc(html_root_url = "https://docs.rs/data-matrix/0.2.0")]
3
4#![doc = include_str!("../README.rustdoc.md")]
6
7mod datamatrix_builder;
8mod errors;
9
10pub use crate::errors::Error;
11use crate::Error::IncorrectMatrixLabels;
12pub use datamatrix_builder::DataMatrixBuilder;
13
14#[derive(Debug, Clone)]
16pub struct DataMatrix {
17 data: Vec<Vec<f64>>,
19
20 row_labels: Vec<String>,
22
23 col_labels: Vec<String>,
25}
26
27impl DataMatrix {
28 pub fn new(
33 data: Vec<Vec<f64>>,
34 row_labels: Vec<String>,
35 col_labels: Vec<String>,
36 ) -> Result<Self, Error> {
37 if data.len() != row_labels.len() {
38 return Err(IncorrectMatrixLabels {
39 expected: row_labels.len(),
40 actual: data.len(),
41 });
42 }
43 if data.is_empty() || data[0].len() != col_labels.len() {
44 return Err(IncorrectMatrixLabels {
45 expected: col_labels.len(),
46 actual: data[0].len(),
47 });
48 }
49
50 Ok(Self {
51 data,
52 row_labels,
53 col_labels,
54 })
55 }
56
57 pub fn nrows(&self) -> usize {
59 self.data.len()
60 }
61
62 pub fn ncols(&self) -> usize {
64 if let Some(first_row) = self.data.first() {
65 first_row.len()
66 } else {
67 0
68 }
69 }
70
71 pub fn get(&self, i: usize, j: usize) -> Option<f64> {
73 self.data.get(i).and_then(|row| row.get(j)).copied()
74 }
75
76 pub fn get_by_label(&self, row_label: &str, col_label: &str) -> Option<f64> {
78 let row_idx = self.row_labels.iter().position(|r| r == row_label)?;
79 let col_idx = self.col_labels.iter().position(|c| c == col_label)?;
80 self.get(row_idx, col_idx)
81 }
82
83 pub fn row_index(&self, label: &str) -> Option<usize> {
85 self.row_labels.iter().position(|r| r == label)
86 }
87
88 pub fn col_index(&self, label: &str) -> Option<usize> {
90 self.col_labels.iter().position(|r| r == label)
91 }
92
93 pub fn row_label(&self, index: usize) -> &String {
95 &self.row_labels[index]
96 }
97
98 pub fn col_label(&self, index: usize) -> &String {
100 &self.col_labels[index]
101 }
102
103 pub fn row_labels(&self) -> &[String] {
107 &self.row_labels
108 }
109
110 pub fn col_labels(&self) -> &[String] {
114 &self.col_labels
115 }
116
117 pub fn data(&self) -> &Vec<Vec<f64>> {
119 &self.data
120 }
121
122 pub fn is_square(&self) -> bool {
124 self.nrows() == self.ncols()
125 }
126}