algeon-cudf 0.1.2

Safe libcudf execution component for Algeon
Documentation
use std::fmt;

use super::{Column, ColumnView, Scalar, Table, TableView};

#[expect(dead_code, reason = "debug info fields formatted via Debug")]
#[derive(Debug)]
struct ExecutionDomainDebugInfo {
    kind: &'static str,
    id: u64,
    stream: usize,
    memory_resource: Option<usize>,
}

impl ExecutionDomainDebugInfo {
    fn for_column(column: &Column) -> Self {
        Self {
            kind: column.__debug_execution_domain_kind(),
            id: column.__debug_execution_domain_id(),
            stream: column.__debug_execution_domain_stream_value(),
            memory_resource: Some(column.__debug_execution_domain_mr_value()),
        }
    }

    fn for_column_view(view: &ColumnView<'_>) -> Self {
        Self {
            kind: view.__debug_execution_domain_kind(),
            id: view.__debug_execution_domain_id(),
            stream: view.__debug_execution_domain_stream_value(),
            memory_resource: Some(view.__debug_execution_domain_mr_value()),
        }
    }

    fn for_table(table: &Table) -> Self {
        Self {
            kind: table.__debug_execution_domain_kind(),
            id: table.__debug_execution_domain_id(),
            stream: table.__debug_execution_domain_stream_value(),
            memory_resource: Some(table.__debug_execution_domain_mr_value()),
        }
    }

    fn for_table_view(view: &TableView<'_>) -> Self {
        Self {
            kind: view.__debug_execution_domain_kind(),
            id: view.__debug_execution_domain_id(),
            stream: view.__debug_execution_domain_stream_value(),
            memory_resource: Some(view.__debug_execution_domain_mr_value()),
        }
    }

    fn for_scalar(scalar: &Scalar) -> Self {
        Self {
            kind: scalar.__debug_execution_domain_kind(),
            id: scalar.__debug_execution_domain_id(),
            stream: scalar.__debug_execution_domain_stream_value(),
            memory_resource: None,
        }
    }
}

#[derive(Debug)]
struct ColumnDebugMetadata {
    dtype: String,
    len: Option<usize>,
    nullable: Option<bool>,
    null_count: Option<usize>,
    execution_domain: ExecutionDomainDebugInfo,
}

impl ColumnDebugMetadata {
    fn unknown(execution_domain: ExecutionDomainDebugInfo) -> Self {
        Self { dtype: "?".to_string(), len: None, nullable: None, null_count: None, execution_domain }
    }
}

#[expect(dead_code, reason = "debug info fields formatted via Debug")]
#[derive(Debug)]
struct TableColumnDebugSummary {
    index: usize,
    dtype: String,
    nullable: Option<bool>,
    null_count: Option<usize>,
}

#[derive(Debug)]
struct TableDebugMetadata {
    num_columns: Option<usize>,
    num_rows: Option<usize>,
    columns: Vec<TableColumnDebugSummary>,
    execution_domain: ExecutionDomainDebugInfo,
}

impl TableDebugMetadata {
    fn unknown(execution_domain: ExecutionDomainDebugInfo) -> Self {
        Self { num_columns: None, num_rows: None, columns: Vec::new(), execution_domain }
    }
}

fn dtype_name<T>(dtype: Option<T>) -> String
where T: Into<super::types::DataType> {
    dtype.map(|dtype| format!("{:?}", dtype.into().id())).unwrap_or_else(|| "?".to_string())
}

fn build_column_debug_metadata(
    view: Option<&ColumnView<'_>>,
    execution_domain: ExecutionDomainDebugInfo,
) -> ColumnDebugMetadata {
    let Some(view) = view else {
        return ColumnDebugMetadata::unknown(execution_domain);
    };

    ColumnDebugMetadata {
        dtype: dtype_name(view.data_type().ok()),
        len: view.len().ok(),
        nullable: view.nullable().ok(),
        null_count: view.null_count().ok(),
        execution_domain,
    }
}

fn build_table_column_debug_summary(view: Option<&ColumnView<'_>>, index: usize) -> TableColumnDebugSummary {
    let Some(view) = view else {
        return TableColumnDebugSummary { index, dtype: "?".to_string(), nullable: None, null_count: None };
    };

    TableColumnDebugSummary {
        index,
        dtype: dtype_name(view.data_type().ok()),
        nullable: view.nullable().ok(),
        null_count: view.null_count().ok(),
    }
}

fn build_table_debug_metadata(
    view: Option<&TableView<'_>>,
    execution_domain: ExecutionDomainDebugInfo,
) -> TableDebugMetadata {
    let Some(view) = view else {
        return TableDebugMetadata::unknown(execution_domain);
    };

    let num_columns = view.num_columns().ok();
    let num_rows = view.num_rows().ok();
    let columns = num_columns
        .map(|num_columns| {
            (0..num_columns)
                .map(|index| {
                    let column = view.column(index).ok();
                    build_table_column_debug_summary(column.as_ref(), index)
                })
                .collect()
        })
        .unwrap_or_default();

    TableDebugMetadata { num_columns, num_rows, columns, execution_domain }
}

impl fmt::Debug for Column {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let view = self.view().ok();
        let metadata = build_column_debug_metadata(view.as_ref(), ExecutionDomainDebugInfo::for_column(self));

        f.debug_struct("Column")
            .field("dtype", &metadata.dtype)
            .field("len", &metadata.len)
            .field("nullable", &metadata.nullable)
            .field("null_count", &metadata.null_count)
            .field("execution_domain", &metadata.execution_domain)
            .finish()
    }
}

impl fmt::Debug for ColumnView<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let metadata = build_column_debug_metadata(Some(self), ExecutionDomainDebugInfo::for_column_view(self));

        f.debug_struct("ColumnView")
            .field("dtype", &metadata.dtype)
            .field("len", &metadata.len)
            .field("nullable", &metadata.nullable)
            .field("null_count", &metadata.null_count)
            .field("execution_domain", &metadata.execution_domain)
            .finish()
    }
}

impl fmt::Debug for Table {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let view = self.view().ok();
        let metadata = build_table_debug_metadata(view.as_ref(), ExecutionDomainDebugInfo::for_table(self));

        f.debug_struct("Table")
            .field("num_columns", &metadata.num_columns)
            .field("num_rows", &metadata.num_rows)
            .field("columns", &metadata.columns)
            .field("execution_domain", &metadata.execution_domain)
            .finish()
    }
}

impl fmt::Debug for TableView<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let metadata = build_table_debug_metadata(Some(self), ExecutionDomainDebugInfo::for_table_view(self));

        f.debug_struct("TableView")
            .field("num_columns", &metadata.num_columns)
            .field("num_rows", &metadata.num_rows)
            .field("columns", &metadata.columns)
            .field("execution_domain", &metadata.execution_domain)
            .finish()
    }
}

impl fmt::Debug for Scalar {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let dtype = dtype_name(self.data_type().ok());
        let valid = self.is_valid().ok();
        let execution_domain = ExecutionDomainDebugInfo::for_scalar(self);

        f.debug_struct("Scalar")
            .field("dtype", &dtype)
            .field("valid", &valid)
            .field("execution_domain", &execution_domain)
            .finish()
    }
}