Skip to main content

matten_data/
lib.rs

1//! `matten-data` โ€” a tiny table-to-Tensor preparation companion for small PoC
2//! datasets.
3//!
4//! # Status
5//!
6//! **Production-ready** (RFC-085). This is a scope-locked companion (RFC-033) for the boring
7//! step between table-like input and a numeric [`matten::Tensor`]. The API is
8//! mostly stable but pre-1.0; pin the minor version. Under lock-step family versioning
9//! (RFC-030) the crate shares the workspace family version; maturity is the Status
10//! label, not the version number.
11//!
12//! # The workflow
13//!
14//! ```text
15//! small CSV / table-like data
16//!   -> inspect schema
17//!   -> select columns by name
18//!   -> clean missing values explicitly
19//!   -> convert to numeric explicitly
20//!   -> matten::Tensor
21//! ```
22//!
23//! ```
24//! # #[cfg(not(feature = "csv"))] fn main() {}
25//! # #[cfg(feature = "csv")] fn main() -> Result<(), matten_data::MattenDataError> {
26//! use matten_data::Table;
27//!
28//! let csv = "sales,cost,note\n10,2,a\n20,,b\n30,4,c";
29//! let table = Table::from_csv_str(csv)?;
30//!
31//! // Inspect, select, clean, convert โ€” every step explicit.
32//! let tensor = table
33//!     .select_columns(["sales", "cost"])?
34//!     .fill_missing(0.0)?
35//!     .try_numeric()?
36//!     .to_tensor()?;
37//!
38//! assert_eq!(tensor.shape(), &[3, 2]);
39//! assert_eq!(tensor.as_slice(), &[10.0, 2.0, 20.0, 0.0, 30.0, 4.0]);
40//! # Ok(())
41//! # }
42//! ```
43//!
44//! # What it is not
45//!
46//! `matten-data` is **not a dataframe library**. It has no joins, group-by, pivot,
47//! query DSL, lazy execution, indexing/`loc`/`iloc`, rolling/window operations,
48//! datetime engine, or categorical dtype system. For those workloads use
49//! [Polars](https://pola.rs), [DataFusion](https://datafusion.apache.org), Pandas,
50//! or another dataframe/query tool. It is a small conversion helper for
51//! application-validated or trusted data, not a CSV firewall or input sandbox.
52//!
53//! # Streaming (optional, `streaming` feature)
54//!
55//! `CsvBatchReader` (RFC-082) reads a CSV file in row-count-bounded [`Table`]
56//! batches, off by default behind the `streaming` feature. This is a memory
57//! strategy, not a dataframe engine: batches carry no schema evolution, no
58//! lenient/skip-malformed mode, and no streaming numeric conversion โ€” a batch is
59//! exactly a `Table`, and every existing `Table` operation works on it unchanged.
60//! This crate's production-ready promotion (RFC-085) covers this feature too:
61//! stable in what it does, but its scope may still grow (RFC-082 ยง5 defers nine
62//! further items, including async and resumability).
63//!
64//! # Relationship to core `dynamic`
65//!
66//! Core `matten`'s `dynamic` feature is *value-level* ingestion (mixed values
67//! inside a `Tensor`, with explicit `try_numeric()`). `matten-data` is *table-level*
68//! preparation (headers, named columns, schema summary, table-shaped missing-value
69//! policy) whose end goal is a numeric `Tensor`. It does not expose a second
70//! computation engine.
71//!
72//! # Conversion rules
73//!
74//! Numeric conversion is strict and explicit (`try_numeric` then `to_tensor`):
75//! integers and floats become `f64`; booleans and non-numeric text are rejected;
76//! a remaining missing cell is rejected (fill it first). Missing values never
77//! silently become zero, and booleans never silently become `1`/`0`.
78
79#![forbid(unsafe_code)]
80
81#[cfg(feature = "csv")]
82mod csv;
83mod error;
84mod numeric;
85mod schema;
86#[cfg(feature = "streaming")]
87mod stream;
88mod table;
89
90#[cfg(all(test, feature = "csv"))]
91mod tests;
92
93pub use error::MattenDataError;
94pub use numeric::NumericTable;
95pub use schema::{ColumnKind, ColumnSummary, SchemaSummary};
96#[cfg(feature = "streaming")]
97pub use stream::CsvBatchReader;
98pub use table::{CellValue, Table};