# Chara
[](https://crates.io/crates/chara)
[](https://docs.rs/chara)
A lightweight parser for layered character definitions using a simple line-based format.
## Format
```text
internal_name: Optional Display Name # Inline comment
- Variant Name: image_path
- Another Variant: other_path
- None # Disables layer
```
Both separators are colons: `internal_name: display_name` for a layer,
`variant_name: image_path` for a variant. The display name and the image path
are optional.
## Usage
Add to your project:
```toml
[dependencies]
chara = "0.2"
```
Basic parsing:
```rust
use chara::CharacterDefinition;
let input = r"
base
- Default: base.png
expression: Mood
- Happy: happy.png
- Sad: sad.png
";
let def = CharacterDefinition::parse(input);
```
`parse` is lenient and never fails: malformed lines are skipped. Use
`try_parse` to reject them instead — it returns a `Result<_, ParseError>`
that reports the first structural problem with its line number (orphan
variant, missing name, empty layer, duplicate name).
## Features
- Zero dependencies
- First variant is default
- Empty path disables layer
- Preserves declaration order
## Used by
- [chara-server](https://gitlab.com/porky11/chara-server) — HTTP server that renders `.chara` files as interactive character previews
- [pukram-server](https://gitlab.com/porky11/pukram-server) — HTTP server rendering Pukram documents (stories, visual novels, character pages) as HTML
## For AI coding agents
- Single public entry point with two explicit modes: lenient `parse` (infallible)
and strict `try_parse` (returns `ParseError`). No hidden global state or config.
- `ParseError` is an exhaustive enum with line numbers and a `Display` message —
no stringly-typed errors, no panics on bad input.
- Plain public data (`CharacterDefinition` → `LayerGroup` → `LayerEntry`); fields
are owned `Box<str>`, declaration order is preserved, empty path means disabled.