# readable-code-korean

Korean-like Hangul word generator for [readable-code](https://github.com/semanticist21/readable-code) share codes.

Generates pronounceable, natural-reading Hangul pseudo-words — not dictionary words, not secret tokens. Composes precomposed Hangul syllables directly via the Unicode algorithm. Depends only on [`readable-code-core`](https://crates.io/crates/readable-code-core).

## Install

```sh
cargo add readable-code-korean
```

## Usage

```rust
use readable_code_korean::hangul;

let code = hangul(3).dash().digits(4).build();
// "가노미-4821"

let code = hangul(3).dash().hangul(4).dash().digits(4).build();
// "가노미-라보수혼-7520"
```

`build()` is the finalizer. It joins the chained fragments and returns the code `String`.

## How words are generated

Each syllable is composed directly from its jamo via the Unicode formula:

```text
syllable = 0xAC00 + (choseong * 21 + jungseong) * 28 + jongseong
```

The index tables deliberately avoid the full Hangul space. Random complete Hangul reads as noise (`쟁헹웅항`), so jamo are constrained and weighted by how they read:

- **Initial consonant (choseong)** — common consonants weighted up; `ㅊㅋㅌㅍ` kept rare.
- **Medial vowel (jungseong)** — clear open vowels weighted up.
- **Final consonant (jongseong)** — mostly open syllables; only soft finals `ㄴ ㄹ ㅁ ㅇ`, never two finals in a row.

The onset after a final consonant (batchim) is constrained to avoid consonant assimilation across the boundary (for example `신라` → `실라`), so the written form matches how it is read.

## API

### `hangul(length) -> KoreanBuilder<OsRandom>`

Primary fluent API using the secure default random source (with final consonants). Returns a builder with one Hangul pseudo-word already added, so you can keep chaining.

Builder methods (each consumes and returns `self`): `hangul(length)`, `dash()`, `digits(length)` / `nums(length)`, `add(value)`, `build()`.

### `hangul_with(length, final_consonants, rng) -> KoreanBuilder<R>`

Same fluent API with a caller-supplied `RandomSource` and a `final_consonants` flag (`false` = open syllables only) — use for deterministic, reproducible output:

```rust
use readable_code_korean::hangul_with;
use readable_code_core::SplitMix64;

let code = hangul_with(3, true, SplitMix64::new(1)).dash().digits(4).build();
```

### `ko_word(length, final_consonants, rng) -> String`

Lower-level helper that returns a plain `String` for one Hangul pseudo-word, with no builder chain. Use it to drop a generated word into your own composition:

```rust
use readable_code_core::{code, OsRandom};
use readable_code_korean::ko_word;

let mut rng = OsRandom::new();
let token = ko_word(3, true, &mut rng);     // e.g. "가노미"
let open = ko_word(3, false, &mut rng);     // open syllables only, no final consonant
```

It borrows the random source mutably (`&mut R`) instead of owning it, so you can interleave several draws from one source.

## Concept

Readable public share codes, not secret tokens. Keep uniqueness separate from the readable part — store codes under a database `UNIQUE` constraint and retry on collision.

## License

MIT
