Skip to content

ADR 0010 — repr(C) tensor metadata across the Rust/C++ boundary (not Arrow)

Accepted · 2026-05-20 · cortex/docs/adr/0010-repr-c-tensor-boundary.md

Status: Accepted Date: 2026-05-20 Source: docs/arch/cortex-repo.md, Data structure abstractions (Arrow vs. C-structs; the zero-copy-to-expression-template pipeline)

Sensor data and tensors cross from the Rust RM (which owns the DMA buffers) into the C++ SDK. Apache Arrow was considered: standard zero-copy interop and self-describing metadata. But Arrow is columnar, while sensor data is dense tensors and row-based IMU records. Its libraries are large for an edge target, and its layout and metadata don’t map directly onto hardware register boundaries.

Pass tensors as a plain repr(C) metadata struct through the cxx bridge (#[cxx::bridge(namespace = "branes::core")] in core/src/bridge.rs). It carries a raw pointer, byte size, shape (rows, cols), stride, and dtype, plus an opaque handle that identifies the RM buffer allocation (the client passes it back to release_buffer). Nothing else: no Arrow-style schema, and no ownership semantics in the descriptor itself; the buffer’s lifetime is managed through the handle. It is a lightweight tensor descriptor in the spirit of DLPack.

The C++ side wraps the pointer in a std::span<T> immediately and hands it to MTL5 views. It never copies.

  • Zero translation layer between DMA buffers and the math; identical binary layout on both sides of the FFI.
  • The binary layout is the contract. Changing the struct means recompiling both sides together; that’s fine in a monorepo built by one CMake tree.
  • No Arrow dependency. If a data-lake or visualization export ever needs Arrow, it belongs at the edge (a daemon or tool), not on the hot path.
  • Current state: TensorMetadata { handle, data_ptr, byte_size, rows, cols, stride, dtype } is defined in core/src/bridge.rs and exercised by tests/integration/cxx_bridge.cpp.