vt: expose packed cell layout

GhosttyCell was exposed as a raw integer while its manifest entry was only an alias, forcing bulk-read consumers to duplicate the internal cell bit layout.\n\nAdd reflection helpers for packed structs and tagged unions, and keep the C-facing layout metadata next to Cell itself. Extend the ABI manifest and schema with recursive bit descriptors so every content arm, including palette and RGB backgrounds, can be decoded without hardcoded masks.\n\nDocument manifest-driven cell decoding and test the metadata against Zig reflection and real cell values.
This commit is contained in:
Mitchell Hashimoto
2026-08-15 21:04:03 -07:00
parent c75559589e
commit 0e8b7bea63
8 changed files with 813 additions and 16 deletions

View File

@@ -256,9 +256,12 @@ typedef enum GHOSTTY_ENUM_TYPED {
*
* This is the bulk alternative to iterating cells one at a time.
* It lets callers with expensive call boundaries (e.g. WebAssembly
* embedders) read an entire row with a single call, then drill
* into the cells iterator only for cells that need managed data
* (styles, graphemes). */
* embedders) read an entire row with a single call.
*
* Bit positions aren't protected by ABI, so callers should parse them
* out of the manifest from `ghostty_type_json`. Callers with access
* to the C header or without high FFI costs should use `ghostty_cell_get`.
*/
GHOSTTY_RENDER_STATE_ROW_DATA_CELLS_RAW = 5,
GHOSTTY_RENDER_STATE_ROW_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
} GhosttyRenderStateRowData;

View File

@@ -21,19 +21,21 @@ extern "C" {
* Terminal screen cell and row types.
*
* These types represent the contents of a terminal screen. A GhosttyCell
* is a single grid cell and a GhosttyRow is a single row. Both are opaque
* values whose fields are accessed via ghostty_cell_get() and
* ghostty_row_get() respectively.
* is a single grid cell and a GhosttyRow is a single row. Cell fields can
* be accessed via ghostty_cell_get() or decoded from the packed layout in
* ghostty_type_json(). Rows are opaque and accessed via ghostty_row_get().
*
* @{
*/
/**
* Opaque cell value.
* Packed cell value.
*
* Represents a single terminal cell. The internal layout is opaque and
* must be queried via ghostty_cell_get(). Obtain cell values from
* terminal query APIs.
* Represents a single terminal cell. Portable callers can query fields via
* ghostty_cell_get(). Boundary-sensitive callers can decode the packed value
* using the GhosttyCell descriptor returned by ghostty_type_json(). The
* manifest is authoritative for the linked build; hardcoding bit positions
* is unsupported.
*
* @ingroup screen
*/
@@ -55,7 +57,8 @@ typedef uint64_t GhosttyRow;
*
* The memory is not owned by this struct. The pointer is only valid
* for the lifetime documented by the API that produces it. Each value
* is queried via ghostty_cell_get() like any other GhosttyCell.
* can be queried via ghostty_cell_get() or decoded using the GhosttyCell
* packed descriptor returned by ghostty_type_json().
*
* @ingroup screen
*/

View File

@@ -342,6 +342,13 @@ typedef struct {
* this manifest rather than hardcoding them. Consumers should reject unknown
* schema versions and verify the descriptors they require at initialization.
*
* Packed type descriptors define fields using `lsb` and `width`. `lsb` is
* relative to bit zero of the containing numerical value; for nested packed
* layouts it is relative to the immediate containing field. Tagged packed
* unions select an inline arm layout using the named tag field. These layouts
* describe the current linked build and are not a cross-version stability
* promise.
*
* The formal format is defined by the
* <a href="types.schema.json">libghostty-vt ABI manifest JSON Schema</a>.
*