The Backend Interface
Relevant source files
The following files were used as context for generating this wiki page:
The Backend Interface in guiltty defines the contract for rendering pixel-level 2D graphics onto terminal displays. It decouples the core drawing logic, which manages buffers for shapes, text, and sprites, from the specific escape sequences and transmission protocols required by various terminal emulators.
At its core, the interface is defined by the Backend trait, which allows guiltty-core to remain agnostic of the underlying rendering technology. The primary implementation provided by the project is the KittyBackend, which utilizes the Kitty Graphics Protocol to transmit raw pixel data to compatible terminals.
Sources: crates/guiltty-core/src/lib.rs:105-115, README.md:16-19, crates/guiltty/src/lib.rs:4-9
Architecture and Core Traits
The architecture separates concern into two distinct areas: the backend-agnostic canvas management and the backend-specific transmission logic.
The Backend Trait
The Backend trait is the fundamental interface within guiltty-core. It requires an associated Error type and a present method that accepts a reference to a Canvas.
The diagram above illustrates the relationship between the abstract Backend trait and its concrete implementation, KittyBackend.
Sources: crates/guiltty-core/src/lib.rs:105-115, crates/guiltty-kitty/src/lib.rs:71-74
Data Flow: Canvas to Terminal
The data flow starts with the Canvas, which maintains a Vec<Color> representing the pixel buffer. When present() is called, the backend retrieves this data, typically as row-major RGBA8 bytes.
The flow shows how internal pixel data is transformed and transmitted through the backend.
Sources: crates/guiltty-core/src/lib.rs:113, crates/guiltty-core/src/lib.rs:163-169, crates/guiltty-kitty/src/lib.rs:75-80
Kitty Graphics Protocol Implementation
The KittyBackend is the first-class implementation of the Backend interface. It specifically targets terminals supporting the Kitty graphics protocol version 0.20.0 or later.
Protocol Encoding and Chunking
The KittyBackend encodes the Canvas pixel buffer into base64-encoded Application Program Control (APC) escape sequences. Due to protocol limitations, data is split into chunks of 4096 bytes.
| Parameter | Function | Description |
|---|---|---|
a=T | Action | Transmit and display the image. |
f=32 | Format | Specifies RGBA8 pixel format. |
i=<id> | Image ID | Unique ID to distinguish images in the terminal namespace. |
p=<id> | Placement ID | Reuses Image ID to ensure repeated calls update the same screen location. |
m=<0|1> | More Data | 1 indicates more chunks follow; 0 indicates the final chunk. |
q=2 | Quiet Mode | Suppresses OK/Error responses from the terminal. |
C=1 | Cursor | Prevents the terminal cursor from moving after display. |
Sources: crates/guiltty-kitty/src/lib.rs:11-13, crates/guiltty-kitty/src/lib.rs:96-115, tasks/plan.md:32-38
Transmission Logic
The backend uses a generic io::Write target, allowing it to output to stdout by default or to a Vec<u8> for protocol testing.
// crates/guiltty-kitty/src/lib.rs:75-80
fn present(&mut self, canvas: &Canvas) -> Result<(), Error> {
let to_backend_err = |e: io::Error| Error::Backend(e.to_string());
let rgba = canvas.rgba8_bytes();
let encoded = BASE64.encode(&rgba);
let chunks: Vec<&[u8]> = encoded.as_bytes().chunks(MAX_CHUNK_LEN).collect();
Sources: crates/guiltty-kitty/src/lib.rs:26-31, crates/guiltty-kitty/src/lib.rs:75-80
Error Handling
The backend interface uses a unified Error enum to handle recoverable conditions. While the Backend trait allows for backend-specific error types, KittyBackend utilizes the project-wide Error type.
| Error Variant | Source | Description |
|---|---|---|
Backend(String) | KittyBackend | Captures IO errors during terminal transmission or escape sequence writing. |
ImageLoad(String) | guiltty-core | Returned if Bitmap::from_file fails (missing or malformed file). |
Sources: crates/guiltty-core/src/lib.rs:85-91, crates/guiltty-kitty/src/lib.rs:71-76
Summary of Integration
The guiltty facade crate simplifies consumption of the backend interface by re-exporting both the core API and the default KittyBackend.
This structure allows developers to interact with a single library while leveraging the modularity of the underlying core and backend crates.
Sources: crates/guiltty/src/lib.rs:4-9, crates/guiltty/Cargo.toml:15-17, README.md:28-36