chara 0.2.1

Parser for layered character definition files
Documentation
# Chara

[![crates.io](https://img.shields.io/crates/v/chara)](https://crates.io/crates/chara)
[![docs.rs](https://docs.rs/chara/badge.svg)](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.