# type-lib v0.5.0 — Implementation
**Most of the feature set, landed.** v0.5.0 fills in the library on top of the
v0.2.0 foundation: a `rules` module of ready-made validators, a `combinator`
module to compose them at the type level, property-based tests, criterion
benchmarks, and runnable examples. It is purely additive — no breaking changes —
and the validation hot path measures in the low nanoseconds.
## What is type-lib?
A validation and type-constraint library for Rust. You declare domain types whose
invariants are enforced at construction and proven by the type system thereafter,
so code that receives a validated value never re-checks it. Wrappers are
zero-overhead, the core is `no_std`-friendly, and rules are reusable and
composable.
## What's new in 0.5.0
### Built-in rules
The new `type_lib::rules` module ships the validators you would otherwise write by
hand. Every one reports [`ValidationError`], so they share a single error type.
- **Length** — `NonEmpty`, `MinLen<MIN>`, `MaxLen<MAX>`, `LenRange<MIN, MAX>`,
built on the new `HasLength` trait (implemented for `str`, `[T]`, references,
and — under `alloc` — `String` / `Vec<T>`). String length counts `char`s, not
bytes.
- **Numeric** — `Positive`, `NonNegative`, `Negative`, `NonPositive` for signed
integers and floats, and `InRange<MIN, MAX>` for the integer types that fit
losslessly in an `i64`.
- **String** — `Ascii`, `Alphanumeric`, `Trimmed` for any `AsRef<str>`.
```rust
use type_lib::rules::{InRange, MaxLen};
use type_lib::Refined;
type Percent = Refined<u8, InRange<0, 100>>;
type ShortName<'a> = Refined<&'a str, MaxLen<32>>;
assert!(Percent::new(50).is_ok());
assert!(Percent::new(150).is_err());
assert!(ShortName::new("ok").is_ok());
```
### Composition with `And`, `Or`, `Not`
The new `type_lib::combinator` module composes rules at the type level. Each
combinator is itself a [`Validator`], so they nest.
```rust
use type_lib::combinator::And;
use type_lib::rules::{Ascii, LenRange};
use type_lib::Refined;
// An API key: 16–64 ASCII characters.
type ApiKey = Refined<String, And<Ascii, LenRange<16, 64>>>;
assert!(ApiKey::new("sk_live_0123456789abcdef".to_owned()).is_ok());
assert!(ApiKey::new("short".to_owned()).is_err());
```
`And` and `Or` require their sub-rules to share an error type (every built-in rule
reports `ValidationError`, so they compose freely); `Not` inverts any rule and
reports its own `ValidationError`. `And`, `Or`, and `Not` are re-exported from the
`prelude`.
### `alloc` feature
A new `alloc` feature enables the length rules for owned `String` / `Vec<T>`
values without requiring full `std`. `std` now implies `alloc`. With no features,
the crate remains `no_std` and every borrowed-value rule still works.
### Property tests
`tests/proptests.rs` uses `proptest` to check rule and combinator invariants
against independent reference predicates over a wide input space: length rules
match the character count, `InRange` matches `RangeInclusive::contains`,
`Refined::new` succeeds exactly when the rule accepts (and round-trips the value),
and `And`/`Or`/`Not` are the boolean conjunction/disjunction/negation of their
parts.
### Benchmarks
`benches/validation.rs` measures the validation hot path with `criterion`. The
wrapper itself adds nothing; the only cost is the rule. Local Criterion means
(Windows x86_64, Rust stable):
- `Refined::new` with `Ascii` on a short `&str`: **~0.9 ns**
- `Refined::new` with `LenRange<3, 16>` on a `&str`: **~2.2 ns**
- `Refined::new` with `InRange<0, 100>` on an `i32`: **~2.6 ns**
- `get` / `Deref` accessors: **sub-nanosecond** (a field read)
### Examples
Four runnable examples under `examples/`: `quick_start`, `built_in_rules`,
`composing_rules`, and `custom_rule`. Run any with, e.g.,
`cargo run --example quick_start`.
## Breaking changes
**None.** Everything in v0.5.0 is additive over v0.2.0. The `Validator` /
`Refined` / `ValidationError` surface is unchanged; `std` now implies the new
`alloc` feature, which only adds impls.
## Verification
Run on Windows x86_64 (Rust stable 1.95 and MSRV 1.75.0) and on Linux (WSL2
Ubuntu); identical commands pass via the CI matrix (Linux/macOS/Windows ×
{stable, 1.75.0}):
```bash
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo clippy --all-targets --no-default-features -- -D warnings
cargo test --all-features
cargo test --no-default-features
cargo bench --bench validation
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
```
All green. Counts at this tag (identical with and without default features):
- 26 unit tests
- 6 end-to-end integration tests (`foundation.rs` + `smoke.rs`)
- 8 property tests (`proptests.rs`)
- 36 doctests
The published crate has **zero runtime dependencies**. The committed `Cargo.lock`
pins the dev-only `proptest` / `criterion` trees to versions that build on the
MSRV (Rust 1.75); newer releases of `clap`, `tempfile`, `half`, and `proptest`
require a newer compiler.
## What's next
- **Derive macro.** A `#[derive]`/attribute macro for generating validated
newtypes, in its own `type-lib-derive` proc-macro crate, re-exported behind a
`derive` feature.
- **v0.9.0 — Hardening + audit.** Feature freeze, the pre-1.0 audit, and final API
review.
## Installation
```toml
[dependencies]
type-lib = "0.5.0"
# no_std (core API + borrowed-value rules)
type-lib = { version = "0.5.0", default-features = false }
# no_std + owned-type rules
type-lib = { version = "0.5.0", default-features = false, features = ["alloc"] }
```
MSRV: Rust 1.75.
## Documentation
- [README](https://github.com/jamesgober/type-lib/blob/main/README.md)
- [API Reference](https://github.com/jamesgober/type-lib/blob/main/docs/API.md)
- [CHANGELOG](https://github.com/jamesgober/type-lib/blob/main/CHANGELOG.md)
---
**Full diff:** [`v0.2.0...v0.5.0`](https://github.com/jamesgober/type-lib/compare/v0.2.0...v0.5.0).
**Changelog:** [`CHANGELOG.md`](https://github.com/jamesgober/type-lib/blob/main/CHANGELOG.md#050---2026-05-27).