v0.3.0
MoonFrame v0.3.0 — Release Notes
MoonFrame v0.3.0 grows the library's user-facing output surface, completes the join matrix, and adds engineering depth with a pluggable column-storage backend — all on top of the v0.2 method-chain core. Pre-1.0, breaking changes ride the minor version (see Breaking changes).
Highlights
- HTML & Vega-Lite export — render a frame as a styled
<table>or a Vega-Lite v5 chart spec you can paste straight into the Vega editor. - Full join matrix —
right/outercomplete theinner/left/right/outer/crossset. - Read resilience — the CSV / JSON / NDJSON readers gained escape hatches for messy, real-world data.
- Pluggable column storage — an all-valid
Numericfast path alongside the general-purpose ArrowBuiltincolumn, behind a closedColumnStorageseam. - Faster group-by / join and O(1) slicing under the hood.
What's new
Output formats
DataFrame::to_html()/to_html_with_options(...)— a pure, dependency-free renderer (CSSclass,<caption>, amax_rowscap, and HTML escaping by default), parallel toto_markdown.format_vega_lite(df, spec)/write_vega_lite(...)— a complete Vega-Lite v5 spec ($schema+mark+encoding+ inlinedata.values).ChartSpec::bar/line/point/area, withwith_color/with_title.
Join — Right / Outer
JoinType gained Right and Outer, completing the matrix, with right_join / outer_join convenience methods and Polars-aligned semantics (null keys match nothing; NaN keys match; per-how coalesce defaults, overridable with with_coalesce).
Read resilience
infer_schema_rows = 0 scans every row instead of a leading window; on_parse_error (Raise / Null) chooses whether an off-type cell past the window fails the read or downgrades to null; CSV's allow_nonfinite_floats controls whether nan / inf tokens infer as Float or fall back to String.
Pluggable column storage
A Series now holds a ColumnStorage — a closed { Builtin; Numeric } seam. Numeric is an all-valid, unboxed Int64 / Double column with no validity bitmap (the null_count == 0 fast path); from_ints / from_floats pick it automatically, and structural transforms keep a column on the fast path. storage_kind() / to_numeric() / to_builtin() inspect and convert.
Performance
- group-by / join keys are now hashed on native cell values — no per-row string key, and no decimal-string round-trip for numeric keys.
- Bitmap slicing is
O(1)—head/tail/sliceshare the parent's validity buffer (a zero-copy view) instead of repacking it.
Breaking changes
Pre-1.0, breaking changes ride the minor version. The source-level breaks:
Series::storage()now returns@column.ColumnStorage(was@column.BuiltinColumn). The.data()/.validity()reading surface is unchanged, so column-reading call sites still compile; use.to_builtin()for the concreteBuiltinColumn.Series::new(name, ...)takes aColumnStorage(passColumnStorage::from_builtin(col), or use the unchangedSeries::from_builtin).JoinTypegainedRight/Outer— an exhaustivematchover it must now handle the two new variants.- The CSV / JSON / NDJSON
*ReadOptionsstructs gainedpub(all)fields; a full struct literal must add them or switch to::default()(the defaults reproduce the prior behaviour exactly).
Step-by-step upgrade notes are in migration.md.