Three-Crate Architecture
Relevant source files
The following files were used as context for generating this wiki page:
The guiltty project is structured as a three-crate Cargo workspace designed to provide a pixel-level 2D graphics library for terminals. The architecture enforces a strict separation between backend-agnostic drawing logic and protocol-specific rendering implementations. This modularity allows the project to support multiple terminal protocols while maintaining a unified API for consumers.
The core of the system revolves around the guiltty-core crate, which defines the primitives and drawing logic, and the guiltty-kitty crate, which provides the first implementation of the Backend trait using the Kitty graphics protocol. The guiltty crate serves as a simplified facade for end-users.
Sources: README.md:14-30, Cargo.toml:1-10
Crate Responsibilities and Dependencies
The workspace is divided into three primary crates, each with a specific role in the graphics pipeline.
| Crate | Purpose | Key Components |
|---|---|---|
guiltty-core | Backend-agnostic graphics engine. | Canvas, Shape, Sprite, Backend trait. |
guiltty-kitty | Kitty Graphics Protocol implementation. | KittyBackend. |
guiltty | Facade for library consumers. | Re-exports of core and kitty APIs. |
Sources: crates/guiltty-core/Cargo.toml, crates/guiltty-kitty/Cargo.toml, crates/guiltty/Cargo.toml
Dependency Flow
The following diagram illustrates the unidirectional dependency flow between the crates in the workspace.
The facade crate depends on both the core engine and the specific backend, while the backend depends only on the core primitives.
Sources: crates/guiltty/Cargo.toml:10-12, crates/guiltty-kitty/Cargo.toml:10-11
guiltty-core: The Graphics Engine
guiltty-core contains the fundamental logic for 2D rasterization. It manages a pixel buffer (RGBA8) and provides methods for drawing shapes, text, and sprites. It is strictly backend-agnostic, meaning it does not know how the pixels are eventually transmitted to a terminal.
Key Data Structures
- Color: An RGBA8 structure representing a single pixel.
- Canvas: The main render target, maintaining a
Vec<Color>buffer. - Sprite: A movable bitmap that preserves the background of the canvas using a "save-under/restore-under" mechanism.
- Backend Trait: Defines the interface that any rendering backend must implement to display the canvas.
Sources: crates/guiltty-core/src/lib.rs:7-30, crates/guiltty-core/src/lib.rs:88-100, crates/guiltty-core/src/lib.rs:496-510, crates/guiltty-core/src/lib.rs:78-85
The Backend Trait
The Backend trait is the bridge between the graphics engine and the terminal output. It requires an associated Error type and a present method.
pub trait Backend {
type Error: std::error::Error;
fn present(&mut self, canvas: &Canvas) -> Result<(), Self::Error>;
}
Sources: crates/guiltty-core/src/lib.rs:78-85
guiltty-kitty: Protocol Implementation
guiltty-kitty implements the KittyBackend, which transforms the Canvas pixel buffer into Kitty graphics protocol escape sequences.
Transmission Logic
The KittyBackend performs the following steps during present():
- Extracts the raw RGBA8 bytes from the
Canvas. - Encodes the bytes using Base64.
- Chunks the Base64 data into 4096-byte segments (as per protocol limits).
- Wraps chunks in APC (Application Program Command) escape sequences (
\x1b_G...;...\x1b\\). - Writes the sequences to a provided
io::Writetarget (defaults tostdout).
Sources: crates/guiltty-kitty/src/lib.rs:18-22, crates/guiltty-kitty/src/lib.rs:70-115
Data Transformation Flow
This diagram shows the flow of data from the raw pixel buffer in guiltty-core to the final terminal output handled by guiltty-kitty.
Sources: crates/guiltty-kitty/src/lib.rs:70-115
guiltty: The Facade Crate
The guiltty crate is a thin wrapper intended to be the main entry point for users. It re-exports all major types from both guiltty-core and guiltty-kitty to allow users to interact with the library through a single dependency.
pub use guiltty_core::{
Backend, Bitmap, Canvas, Color, Error, Fill, Point, Rect, Shape, Sprite, TextStyle,
};
pub use guiltty_kitty::KittyBackend;
Sources: crates/guiltty/src/lib.rs:4-9
Conclusion
The Three-Crate Architecture ensures that guiltty remains extensible and maintainable. By isolating the rasterization logic in guiltty-core, the project allows for the development of new backends (beyond Kitty) without modifying the core drawing algorithms. The use of a facade crate simplifies the consumer's experience, providing a unified interface to the entire graphics system.
Sources: README.md:14-25