pub mod array;
pub mod data_traits;
pub mod index;
pub mod mapping;
pub use array::*;
pub use data_traits::*;
pub use mapping::*;
use crate::backend::{Backend, DataContainer, DataType, GroupOp};
use anyhow::{Ok, Result, bail};
use nalgebra_sparse::csc::CscMatrix;
use nalgebra_sparse::csr::CsrMatrix;
use ndarray::{Array, RemoveAxis};
use polars::frame::DataFrame;
#[derive(Debug, Clone, PartialEq)]
pub enum Data {
ArrayData(ArrayData),
Scalar(DynScalar),
Mapping(Mapping),
}
impl<T: Clone + Into<Data>> From<&T> for Data {
fn from(data: &T) -> Self {
data.clone().into()
}
}
impl From<DataFrame> for Data {
fn from(data: DataFrame) -> Self {
Data::ArrayData(ArrayData::DataFrame(data))
}
}
macro_rules! impl_into_data {
($($from_type:ty => $to_type:ident),*) => {
$( impl_into_data!($from_type, $to_type); )*
};
($from_type:ty, $to_type:ident) => {
impl From<$from_type> for Data {
fn from(data: $from_type) -> Self {
Data::Scalar(DynScalar::$to_type(data))
}
}
impl<D: RemoveAxis> From<Array<$from_type, D>> for Data {
fn from(data: Array<$from_type, D>) -> Self {
Data::ArrayData(ArrayData::Array(DynArray::$to_type(data.into_dyn())))
}
}
impl From<CsrMatrix<$from_type>> for Data {
fn from(data: CsrMatrix<$from_type>) -> Self {
Data::ArrayData(ArrayData::CsrMatrix(DynCsrMatrix::$to_type(data)))
}
}
impl From<CscMatrix<$from_type>> for Data {
fn from(data: CscMatrix<$from_type>) -> Self {
Data::ArrayData(ArrayData::CscMatrix(DynCscMatrix::$to_type(data)))
}
}
};
}
impl_into_data!(
i8 => I8, i16 => I16, i32 => I32, i64 => I64,
u8 => U8, u16 => U16, u32 => U32, u64 => U64,
f32 => F32, f64 => F64,
bool => Bool, String => String
);
macro_rules! impl_into_data2 {
($($from_type:ty => $to_type:ident),*) => {
$( impl_into_data2!($from_type, $to_type); )*
};
($from_type:ty, $to_type:ident) => {
impl From<$from_type> for Data {
fn from(data: $from_type) -> Self {
Data::$to_type(data)
}
}
};
}
impl_into_data2!(DynScalar => Scalar, ArrayData => ArrayData, Mapping => Mapping);
macro_rules! impl_try_from_for_scalar {
($($from:ident => $to:ident),*) => {
$( impl_try_from_for_scalar!($from, $to); )*
};
($from:ident, $to:ident) => {
impl TryFrom<Data> for $to {
type Error = anyhow::Error;
fn try_from(data: Data) -> Result<Self> {
match data {
Data::Scalar(DynScalar::$from(data)) => Ok(data),
_ => bail!("Cannot convert data to {}", stringify!($to)),
}
}
}
impl<D: RemoveAxis> TryFrom<Data> for Array<$to, D> {
type Error = anyhow::Error;
fn try_from(v: Data) -> Result<Self> {
match v {
Data::ArrayData(data) => data.try_into(),
_ => bail!("Cannot convert data to {} Array", stringify!($to)),
}
}
}
};
}
impl_try_from_for_scalar!(
I8 => i8, I16 => i16, I32 => i32, I64 => i64,
U8 => u8, U16 => u16, U32 => u32, U64 => u64,
F32 => f32, F64 => f64,
Bool => bool, String => String
);
impl TryFrom<Data> for DataFrame {
type Error = anyhow::Error;
fn try_from(value: Data) -> Result<Self, Self::Error> {
match value {
Data::ArrayData(data) => data.try_into(),
_ => bail!("Cannot convert data to DataFrame"),
}
}
}
impl TryFrom<Data> for Mapping {
type Error = anyhow::Error;
fn try_from(v: Data) -> Result<Self> {
match v {
Data::Mapping(data) => Ok(data),
_ => bail!("Cannot convert data to Mapping"),
}
}
}
impl Readable for Data {
fn read<B: Backend>(container: &DataContainer<B>) -> Result<Self> {
match container.encoding_type()? {
DataType::Categorical
| DataType::Array(_)
| DataType::DataFrame
| DataType::CscMatrix(_)
| DataType::CsrMatrix(_) => ArrayData::read(container).map(|x| x.into()),
DataType::Scalar(_) => DynScalar::read(container).map(|x| x.into()),
DataType::Mapping => Mapping::read(container).map(|x| x.into()),
DataType::NullableArray => bail!("Cannot read NullableArray into Data"),
}
}
}
impl Element for Data {
fn data_type(&self) -> DataType {
match self {
Data::ArrayData(data) => data.data_type(),
Data::Scalar(data) => data.data_type(),
Data::Mapping(data) => data.data_type(),
}
}
fn metadata(&self) -> MetaData {
match self {
Data::ArrayData(data) => data.metadata(),
Data::Scalar(data) => data.metadata(),
Data::Mapping(data) => data.metadata(),
}
}
}
impl Writable for Data {
fn write<B: Backend, G: GroupOp<B>>(
&self,
location: &G,
name: &str,
) -> Result<DataContainer<B>> {
match self {
Data::ArrayData(data) => data.write(location, name),
Data::Scalar(data) => data.write(location, name),
Data::Mapping(data) => data.write(location, name),
}
}
}