Skip to main content

connectorx/
data_order.rs

1//! This module provides two data orders: row-wise and column-wise for tabular data,
2//! as well as a function to coordinate the data order between source and destination.
3
4use crate::errors::ConnectorXError;
5use fehler::{throw, throws};
6#[derive(Copy, Clone, Eq, PartialEq, Debug)]
7pub enum DataOrder {
8    RowMajor,
9    ColumnMajor,
10}
11
12/// Given the supported data order from source and destination, decide the optimal data order
13/// for producing and writing.
14#[throws(ConnectorXError)]
15pub fn coordinate(src: &[DataOrder], dst: &[DataOrder]) -> DataOrder {
16    assert!(!src.is_empty() && !dst.is_empty());
17
18    match (src, dst) {
19        ([s, ..], [d, ..]) if s == d => *s,
20        ([s, ..], [_, d, ..]) if s == d => *s,
21        ([_, s, ..], [d, ..]) if s == d => *s,
22        _ => throw!(ConnectorXError::CannotResolveDataOrder(
23            src.to_vec(),
24            dst.to_vec()
25        )),
26    }
27}
28
29#[cfg(test)]
30mod tests {
31    use super::{coordinate, DataOrder};
32
33    #[test]
34    fn selects_matching_first_supported_order() {
35        assert!(matches!(
36            coordinate(&[DataOrder::RowMajor], &[DataOrder::RowMajor]),
37            Ok(DataOrder::RowMajor)
38        ));
39    }
40
41    #[test]
42    fn selects_matching_secondary_supported_order() {
43        assert!(matches!(
44            coordinate(
45                &[DataOrder::RowMajor, DataOrder::ColumnMajor],
46                &[DataOrder::ColumnMajor],
47            ),
48            Ok(DataOrder::ColumnMajor)
49        ));
50        assert!(matches!(
51            coordinate(
52                &[DataOrder::ColumnMajor],
53                &[DataOrder::RowMajor, DataOrder::ColumnMajor],
54            ),
55            Ok(DataOrder::ColumnMajor)
56        ));
57    }
58
59    #[test]
60    fn reports_when_orders_cannot_be_resolved() {
61        assert!(coordinate(&[DataOrder::RowMajor], &[DataOrder::ColumnMajor]).is_err());
62    }
63}