Files
Aura/crates/aura-core/src/cell.rs
T
Brummel f51d54a1c1 docs(cell): name Scalar as the param-authoring surface; no tagged Cell ctors by design
Cell is the kind-erased hot-path carrier (C7): the value carries no tag, so
there are deliberately no tuple-style/tagged constructors (`Cell::I64(..)`).
Document on the struct that Scalar is the value to reach for when authoring a
param / bind / sweep point / RunManifest field, and that the from_* ctors are the
carrier-side entry. Resolves the discoverability papercut without softening the
carrier split.

closes #100
2026-06-22 11:24:08 +02:00

71 lines
3.1 KiB
Rust

//! `Cell` — a type-erased 64-bit word holding one scalar value with its kind
//! stripped away (C7). The type lives in the schema / column / port, never in
//! the value, so a cell is read back only by naming its type via a typed
//! accessor. `Scalar` is built on top of this; `Cell` itself knows nothing of
//! `Scalar` or `ScalarKind`.
use crate::scalar::Timestamp;
/// A type-erased 64-bit cell: the raw storage of one scalar value with its kind
/// stripped away. The bits are meaningless on their own — the type lives in the
/// schema/column/port, not in the value (C7), so the word is recovered **only**
/// by naming the type at the call site via a typed accessor ([`Cell::i64`],
/// [`Cell::f64`], [`Cell::bool`], [`Cell::ts`]). Each reinterprets the word with
/// no tag to check and therefore no branch — the caller's choice of accessor
/// *is* the type context the hot path already holds. The inner word is private;
/// there is no kind-free way to read it.
///
/// All four base types fit one 64-bit word: `i64`/`Timestamp`/`bool` reuse the
/// same integer word, `f64` via its IEEE-754 bit pattern. `Eq`/`Hash` are
/// bit-exact (so `+0.0`/`-0.0` differ and a `NaN` bit pattern equals itself) —
/// the semantics of a raw word, not of a number.
///
/// **Authoring vs. carrier — reach for [`Scalar`](crate::scalar::Scalar) to
/// build a value.** `Cell` is the hot-path *carrier*, so it deliberately has no
/// tuple-style or tagged constructors (`Cell::I64(3)` does not exist, by design,
/// not omission). When *authoring* a value — a node param, a `bind`/sweep point,
/// a `RunManifest` field — use `Scalar`, the kind-tagged, self-describing carrier
/// of the param plane. The `from_i64`/`from_f64`/`from_bool`/`from_ts` ctors here
/// are the carrier-side entry used once a value crosses into the kind-erased hot
/// path; a self-describing `Cell::I64` would re-introduce the very tag the
/// carrier split strips (C7).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Cell(u64);
impl Cell {
/// Store an `i64` (identity bit-cast).
pub fn from_i64(v: i64) -> Self {
Cell(v as u64)
}
/// Store an `f64` as its IEEE-754 bit pattern.
pub fn from_f64(v: f64) -> Self {
Cell(v.to_bits())
}
/// Store a `bool` as `0`/`1`.
pub fn from_bool(v: bool) -> Self {
Cell(v as u64)
}
/// Store a [`Timestamp`] (its `i64` epoch-ns, bit-cast).
pub fn from_ts(v: Timestamp) -> Self {
Cell(v.0 as u64)
}
/// Read the word as `i64` (identity bit-cast). The caller asserts the type
/// by choosing this accessor; there is no tag to check, hence no branch.
pub fn i64(self) -> i64 {
self.0 as i64
}
/// Read the word as `f64` from its IEEE-754 bit pattern. Branch-free.
pub fn f64(self) -> f64 {
f64::from_bits(self.0)
}
/// Read the word as `bool` (any non-zero word is `true`). Branch-free.
pub fn bool(self) -> bool {
self.0 != 0
}
/// Read the word as a [`Timestamp`] (identity bit-cast). Branch-free.
pub fn ts(self) -> Timestamp {
Timestamp(self.0 as i64)
}
}