Architecture
ratatui-unity is two halves stitched by a thin C ABI:
- Rust core (
src/) — wrapsratatui, maintains terminal state, layouts widgets, rasterizes the resulting buffer of cells into RGB24 pixels viafontdue. - Unity C# bindings (
Packages/com.farukcan.ratatui.unity/Runtime/) — calls into the native crate viaDllImport, marshals aTexture2Dper frame.
Frame Flow
sequenceDiagram
participant U as Unity (C#)
participant N as Native (Rust)
participant R as Ratatui buffer
participant P as Pixel buffer
U->>N: BeginFrame()
N->>R: clear cells
U->>N: Block / Paragraph / Chart / ...
N->>R: enqueue widget commands
U->>N: EndFrameRaw() / EndFrameRawIfDirty()
N->>R: render widgets into cell buffer
N->>P: rasterize cells (font + colors → RGB24)
N-->>U: pixel ptr + size
U->>U: Texture2D.LoadRawTextureData(ptr)
Module Map (Rust)
| Module | Responsibility |
|---|---|
lib.rs |
C ABI exports (ratatui_* functions) |
terminal.rs |
TerminalState, WidgetCommand enum + shared data types, frame state |
commands.rs |
Render dispatch — translates queued WidgetCommands into ratatui calls |
renderer.rs |
Cell buffer → RGB24 pixel pipeline, compute_buffer_hash |
font.rs |
fontdue font cache, glyph rasterization |
color.rs |
Ratatui Color → RGB conversion |
C# Surface (Unity)
| Type | Role |
|---|---|
RatatuiTerminal |
High-level handle: BeginFrame / widgets / EndFrameRaw |
RatatuiRenderer |
MonoBehaviour host: texture management, input, OnGUI fallback |
RatatuiNative |
Raw DllImport declarations |
CanvasBuilder |
Fluent builder for the Canvas widget |
ChartBuilder |
Fluent builder for Chart widget |
Constraint |
Layout constraints (Length, Min, Percentage …) |
StyledText, ITab |
Styling and tabular widget helpers |
RatatuiTerminalApps |
Static bootstrap/registry for scene-independent terminal apps |
RatatuiTerminalApp |
Abstract base for apps with open/close/toggle lifecycle |
RatatuiFocusManager |
Keyboard focus arbitration across multiple renderers |
See Terminal Apps for the app discovery and open/close API.
Memory & Lifetime
- Each
RatatuiTerminalowns a Rust-sideTerminalStateallocated byratatui_createand freed byratatui_destroy. - The native handle is wrapped in a
SafeHandle(RatatuiHandle), so the runtime keeps it alive for the duration of every P/Invoke and releases it exactly once. - The pixel buffer lives in Rust; C# receives a borrowed pointer per frame and must copy via
Texture2D.LoadRawTextureDatabefore the nextBeginFrame(). - Call
RatatuiTerminal.Dispose()deterministically (usingblock or explicit call). An undisposed object is still reclaimed by theSafeHandlefinalizer, but only whenever the GC gets around to it. SetCustomFontresizes the native pixel buffer to the new font's cell metrics and refreshesPixelWidth/PixelHeight; any texture sized from them must be recreated.
See the Rust API for the exact extern "C" surface, and the C# API for the wrappers Unity code touches.