# punycode-rs
A Rust implementation of [Punycode](https://datatracker.ietf.org/doc/html/rfc3492) (RFC 3492)
— the ASCII-compatible encoding at the heart of Internationalized Domain Names. It turns
Unicode into ASCII and back: `münchen` ⇄ `mnchen-3ya` (which IDNA then prefixes as
`xn--mnchen-3ya`).
The implementation is a faithful port of Python's standard-library `punycode` codec, and is
verified against it byte-for-byte (encode and decode, including malformed-input handling).
## Usage
```rust
use punycode_rs::{encode, decode};
assert_eq!(encode("münchen"), "mnchen-3ya");
assert_eq!(decode("mnchen-3ya").unwrap(), "münchen");
// Pure ASCII gains a trailing '-'.
assert_eq!(encode("abc"), "abc-");
// Decoding malformed input returns an error.
assert!(decode("not ascii é").is_err());
```
## Installation
```sh
cargo add punycode-rs
```
```toml
[dependencies]
punycode-rs = "0.1"
```
Requires a Rust toolchain with 2024-edition support (Rust 1.85 or newer).
## How it works
Punycode separates a string into its ASCII "base" (kept verbatim) and its non-ASCII
characters, then encodes each non-ASCII character as a single integer **delta** that records
both *which* character it is and *where* it gets inserted. Deltas are written as base-36
generalized variable-length integers using an **adaptive bias** that self-tunes for
compactness. Decoding mirrors the process exactly. (See RFC 3492 §3.)
## Scope
This crate is raw Punycode — the encoding algorithm itself. It does **not** include the full
IDNA `ToASCII`/`ToUnicode` pipeline (the `xn--` prefix handling and UTS-46 Unicode mapping),
which layers on top and pulls in large Unicode data tables.
## License
Licensed under the [MIT License](LICENSE-MIT).