enumerated_latin 1.0.0

Encodes short strings as numeric values
Documentation
<!--
SPDX-FileCopyrightText: 2025 Slatian

SPDX-License-Identifier: LGPL-3.0-only
-->

# Enumerated Latin

Enumerated Latin is a crate to map strings made of the 26 letters `a` to `z` or `A` to `Z` (case insensitive) to a continuous space of integers by treating the text like a base26 encoded number plus an end marker.

Example:
```rust
use enumerated_latin::EnumeratedLatinEncode;
use enumerated_latin::EnumeratedLatinDecode;

let encoded: u64 = "Example".enumerated_latin_encode().unwrap();

assert_eq!(encoded, 9540966270);

let decoded_again = encoded.enumerated_latin_decode_lowercase().unwrap();

assert_eq!(decoded_again, "example".to_string());
```

## Intended use

Intended use of this is to generate numeric identifiers for short pieces of text, while still allowing to compare against ranges in fixed-length scenarios.

This arises — for example — when working with ISO-codes for languages, scripts countries etc. preserving the order within the same length helps with efficiently checking against private-use and similar ranges.

Intended area of use is in the backend of applications, where the difference between a string and a number actually matters.

For frontends it is recommended to prefer readability over performance whenever possible.

## How the encoding works

In short: The string prefixed with a `b` and then parsed like a most significant first (same order as everyday numbers) base26 number, where `a` maps to `0` and `z` to `25`.

Example: `az` would be encoded as `baz`: `(26^2)*1 + (26^1)*0 + (26^0)*25 = 701`

```rust
use enumerated_latin::EnumeratedLatinEncode;

assert_eq!("az".enumerated_latin_encode(), Ok(701 as u16))
```

The `b` at the start is because with `a` mapping to zero, leading `a`s act like leading `0`s in everyday base10 numbers, there is no way from the numeric value to tell how many of them were present. The trailing `b` ensures, that one can always deduce the original length from the numeric value.

The everyday base10 equivalent to prepending the `b` would be prepending a `1` i.e. `000` to `1000` and `00` to `100`.

This results in the following facts about the encoding:
* An empty string encodes to a `1`
* The first valid non-empty string is `a` with a value of `26`
* Within the same length, the encoded strings sort alphabetically
* Longer string means bigger number
* There is a gap in the encoding space between different length strings
* Assuming a length `l`, the first value is `26^l` and the last one is `((26^l)*2)-1)`.

## Encoding targets

Encoding each letter takes roughly 5 bits of information plus one bit for the end cap, you can use this information to roughly estimate which datatype you'll need.

Valid encoding target types are:

| Type   | supported length |
|--------|------------------|
| `u8`   | 1                |
| `i16`  | 2                |
| `u16`  | 3                |
| `i32`  | 6                |
| `u32`  | 6                |
| `i64`  | 13               |
| `u64`  | 13               |
| `i128` | 26               |
| `u128` | 26               |

## Licensing

`enumerated_latin` is licensed as `LGPL-3.0-only` and [REUSE 3.3](https://reuse.software/spec-3.3/) compliant.

When contributing add yourself as a copyright holder to the files you modified.