use ndarray::Array2;
use num_complex::Complex64;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ApotBinType {
Int,
Real,
Double,
Complex,
DComplex,
Text,
}
impl ApotBinType {
pub(super) fn record_name(self) -> &'static str {
match self {
Self::Int => "Int",
Self::Real => "Real",
Self::Double => "Double",
Self::Complex => "Complex",
Self::DComplex => "DComplex",
Self::Text => "String",
}
}
pub(super) fn matrix_name(self) -> &'static str {
match self {
Self::Int => "integer",
Self::Real => "real",
Self::Double => "double",
Self::Complex => "complex",
Self::DComplex => "double complex",
Self::Text => "string",
}
}
pub(super) fn token_width(self) -> usize {
match self {
Self::Complex | Self::DComplex => 2,
Self::Int | Self::Real | Self::Double | Self::Text => 1,
}
}
pub(super) fn is_real(self) -> bool {
matches!(self, Self::Real | Self::Double)
}
pub(super) fn is_complex(self) -> bool {
matches!(self, Self::Complex | Self::DComplex)
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ApotBinValue {
Int(i64),
Real(f64),
Complex(Complex64),
Text(String),
}
#[derive(Debug, Clone, PartialEq)]
pub struct ApotBinRecords {
pub column_types: Vec<ApotBinType>,
pub rows: Vec<Vec<ApotBinValue>>,
}
impl ApotBinRecords {
#[must_use]
pub fn row_count(&self) -> usize {
self.rows.len()
}
#[must_use]
pub fn column_count(&self) -> usize {
self.column_types.len()
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ApotBinMatrixValues {
Int(Array2<i64>),
Real(Array2<f64>),
Complex(Array2<Complex64>),
Text(Array2<String>),
}
impl ApotBinMatrixValues {
fn dim(&self) -> (usize, usize) {
match self {
Self::Int(values) => values.dim(),
Self::Real(values) => values.dim(),
Self::Complex(values) => values.dim(),
Self::Text(values) => values.dim(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ApotBinMatrix {
pub value_type: ApotBinType,
pub values: ApotBinMatrixValues,
}
impl ApotBinMatrix {
#[must_use]
pub fn shape(&self) -> (usize, usize) {
self.values.dim()
}
#[must_use]
pub fn row_count(&self) -> usize {
self.shape().0
}
#[must_use]
pub fn column_count(&self) -> usize {
self.shape().1
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ApotBinPayload {
HeadersOnly,
Records(ApotBinRecords),
Matrix(ApotBinMatrix),
}
#[derive(Debug, Clone, PartialEq)]
pub struct ApotBinSection {
pub section_number: usize,
pub headers: Vec<String>,
pub header_texts: Vec<String>,
pub column_labels: Vec<String>,
pub column_label_text: Option<String>,
pub payload: ApotBinPayload,
pub trailing_headers: Vec<String>,
pub trailing_header_texts: Vec<String>,
}
impl ApotBinSection {
#[must_use]
pub fn records(&self) -> Option<&ApotBinRecords> {
match &self.payload {
ApotBinPayload::Records(records) => Some(records),
ApotBinPayload::HeadersOnly | ApotBinPayload::Matrix(_) => None,
}
}
#[must_use]
pub fn matrix(&self) -> Option<&ApotBinMatrix> {
match &self.payload {
ApotBinPayload::Matrix(matrix) => Some(matrix),
ApotBinPayload::HeadersOnly | ApotBinPayload::Records(_) => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ApotBinData {
pub sections: Vec<ApotBinSection>,
}
impl ApotBinData {
#[must_use]
pub fn section_count(&self) -> usize {
self.sections.len()
}
#[must_use]
pub fn matrix_count(&self) -> usize {
self.sections
.iter()
.filter(|section| section.matrix().is_some())
.count()
}
}