language 0.3.3

Typed BCP47 language tags with built-in names, plural metadata, and conversion helpers.
Documentation
# STYLE_RUST.md — Rust Style Rules

These rules apply **only** to Rust code in this repository.
All comments and messages must also follow the Global Language Rules in `AGENTS.md`.

---

# 1. Indentation

- Use **tabs** (`\t`) for all indentation.

---

# 2. Declaration Order

Each Rust file must follow this order:

```
mod
use
macro_rules
type
const
trait
enum
struct
fn
```

Within each group:

- `pub` items appear before non-`pub`.

---

# 3. Imports and Headers

Allowed `use` section headers:

- `// std`
- `// crates.io`
- `// self`

Rules:

- Preserve existing header groups.
- Do not invent new groups.
- Do not add headers above non-import definitions.
- If `crate::prelude::*` is imported, avoid redundant imports.

---

# 4. Module Layout (No mod.rs)

Use a flat structure:

```
src/foo.rs
src/foo/bar.rs
src/foo/baz.rs
```

Never create or modify `mod.rs`.

---

# 5. Structs, Enums, and Impl Blocks

For each type:

1. The first `impl` block must appear **immediately after** the type definition.
2. All impls must be **contiguous** without blank lines between them.
3. Impl order:
    1. Inherent impl
    2. Std traits
    3. Third-party traits
    4. Project/self traits

4. Inside `impl Type` blocks, always use `Self` instead of the concrete type name when referring to the implementing type in method signatures (parameters and return types), including references, slices, and generic containers.

Allowed:

```rust
struct A;

impl A {
	fn new() -> Self {
		Self
	}

	fn from_owned(value: Self) -> Self {
		value
	}

	fn from_ref(value: &Self) -> &Self {
		value
	}

	fn collect_all(values: &[Self]) -> Vec<Self> {
		values.to_vec()
	}
}
```

Forbidden:

```rust
struct A;

impl A {
	fn new() -> A {
		A
	}

	fn from_owned(value: A) -> A {
		value
	}

	fn from_ref(value: &A) -> &A {
		value
	}

	fn collect_all(values: &[A]) -> Vec<A> {
		values.to_vec()
	}
}
```

---

# 6. Generics & Trait Bounds

- All bounds go in a `where` clause.
- Inline trait bounds **forbidden**.
- Exception: `impl Trait` is always allowed.

Allowed:

```rust
fn render<T>(value: T) -> String
where
	T: Display,
{
```

Forbidden:

```rust
fn render<T: Display>(value: T) -> String {
```

---

# 7. Logging Rules

- Never import tracing macros.
- Use fully-qualified macros (`tracing::info!`).
- Prefer named captures:

```rust
tracing::info!("User: {user_id}");
```

- Never create temporary variables solely for logging.

---

# 8. Borrowing & Ownership

- Prefer `&value` over `.as_ref()` or `.as_str()` where applicable.
- Avoid unnecessary `.clone()`.
- Use `into_iter()` when consuming collections intentionally.

---

# 9. Numeric Literals

- When using a numeric type suffix, always separate the value and suffix with a single underscore:
    - Allowed: `10_f64`, `1_u32`, `0_i64`
    - Forbidden: `10f64`, `1u32`, `0i64`

- For decimal integer literals with more than three digits (ignoring the sign), insert an underscore every three digits from the right:
    - Allowed: `1_000`, `10_000`, `1_000_000`
    - Forbidden: `1000`, `10000`, `1000000`

---

# 10. Vertical Spacing

Inside Rust functions:

- Same-category statements: **no blank lines**.
- Different categories: **one blank line**.
- Before final return/tail expression: **exactly one** blank line (unless single-expression body).

---

# 11. Comments & Documentation

- Must follow Global Language Rules.
- Clear English, proper punctuation.
- No slang, abbreviations, or mixed-language text.

---

# 12. Forbidden Style

Never:

- Use spaces for indentation.
- Use inline trait bounds.
- Add blank lines between a type and its first impl.
- Add blank lines between impl blocks.
- Use `mod.rs`.
- Import tracing macros.

---

# 13. Closure Parameters

- In short-lived closures where the meaning is obvious and the bindings are not reused elsewhere, prefer single-letter names (e.g., `k`, `v`, `e`).
- Use descriptive names when a closure spans multiple lines, when the role is not immediately clear, or when the bindings are referenced outside the closure.