tabiew 0.16.0

A lightweight TUI application to view and query tabular data files, such as CSV, TSV, and parquet.
use std::path::PathBuf;

use indexmap::IndexMap;
use polars::prelude::{DataType, Scalar};
use serde::{Deserialize, Serialize};
use url::Url;

use crate::misc::sql;

#[derive(Debug, Serialize, Deserialize)]
pub struct Schema {
    pub schema: IndexMap<String, TableInfo>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TableInfo {
    pub origin: TableSource,
    pub height: usize,
    pub width: usize,
    pub total_null: usize,
    pub total_est_size: Size,
    pub schema: TableSchema,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum TableSource {
    Url(Url),
    File(PathBuf),
    Stdin,
    User,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TableSchema {
    pub schema: IndexMap<String, FieldInfo>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct FieldInfo {
    pub dtype: DataType,
    pub est_size: Size,
    pub null_count: usize,
    pub min: Scalar,
    pub max: Scalar,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Size(pub u64);

impl From<&sql::BackendSchema> for Schema {
    fn from(value: &sql::BackendSchema) -> Self {
        Self {
            schema: value
                .iter()
                .map(|(name, info)| (name.clone(), info.into()))
                .collect(),
        }
    }
}

impl From<&sql::TableInfo> for TableInfo {
    fn from(value: &sql::TableInfo) -> Self {
        Self {
            origin: value.source().into(),
            height: value.height(),
            width: value.width(),
            total_null: value.total_null(),
            total_est_size: value.total_est_size().into(),
            schema: value.schema().into(),
        }
    }
}

impl From<&sql::TableSource> for TableSource {
    fn from(value: &sql::TableSource) -> Self {
        match value {
            sql::TableSource::Url(url) => Self::Url(url.clone()),
            sql::TableSource::File(path) => Self::File(path.clone()),
            sql::TableSource::Stdin => Self::Stdin,
            sql::TableSource::User => Self::User,
        }
    }
}

impl From<&sql::TableSchema> for TableSchema {
    fn from(value: &sql::TableSchema) -> Self {
        Self {
            schema: value
                .iter()
                .map(|(name, field)| (name.clone(), field.into()))
                .collect(),
        }
    }
}

impl From<&sql::FieldInfo> for FieldInfo {
    fn from(value: &sql::FieldInfo) -> Self {
        Self {
            dtype: value.dtype().clone(),
            est_size: value.estimated_size().into(),
            null_count: value.null_count(),
            min: value.min().clone(),
            max: value.max().clone(),
        }
    }
}

impl From<sql::Size> for Size {
    fn from(value: sql::Size) -> Self {
        Self(value.into())
    }
}