# type-lib v0.2.0 — Foundation
**The public API surface that 1.0 will preserve.** v0.2.0 turns the scaffold into
a working parse-dont-validate library built on two composable pieces — the
`Validator` trait and the `Refined<T, V>` wrapper — plus a ready-made
`ValidationError`, a `prelude`, full rustdoc with examples on every item, and an
end-to-end integration suite. Zero runtime overhead: `Refined` is
`#[repr(transparent)]` over its value. The only public item carried over from
v0.1.0, `VERSION`, is unchanged.
## 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 across value
types.
## What's new in 0.2.0
### `Validator` — reusable, type-level rules
A `Validator<T>` is a validation rule implemented on a zero-sized marker type and
selected through the type system. It carries no state and is never instantiated.
The single `validate` method is a pure predicate over a borrowed value.
```rust
use type_lib::{ValidationError, Validator};
struct NonEmpty;
impl<S: AsRef<str> + ?Sized> Validator<S> for NonEmpty {
type Error = ValidationError;
fn validate(value: &S) -> Result<(), Self::Error> {
if value.as_ref().is_empty() {
Err(ValidationError::new("non_empty", "value must not be empty"))
} else {
Ok(())
}
}
}
```
Because `T` is `?Sized` and rules can be written over a borrow (`S: AsRef<str>`),
a single marker type validates `&str`, `String`, and `str` alike. The associated
`Error` type means a rule can return either the bundled `ValidationError` or any
bespoke, structured error.
### `Refined<T, V>` — the zero-cost validated wrapper
`Refined<T, V>` holds a `T` proven to satisfy `V`. It is constructed only by
validating once, through `Refined::new`, and the type proves the invariant from
then on.
```rust
use type_lib::{Refined, ValidationError, Validator};
# struct NonEmpty;
# impl<S: AsRef<str> + ?Sized> Validator<S> for NonEmpty {
# type Error = ValidationError;
# fn validate(v: &S) -> Result<(), Self::Error> {
# if v.as_ref().is_empty() { Err(ValidationError::new("non_empty", "empty")) } else { Ok(()) }
# }
# }
type Username = Refined<String, NonEmpty>;
let user = Username::new("alice".to_owned()); // Ok(_)
assert!(user.is_ok());
assert!(Username::new(String::new()).is_err()); // rejected
```
It is `#[repr(transparent)]` over `T` — same size, same alignment — so the
guarantee costs nothing at runtime. There is deliberately **no `DerefMut`, no
public field, and no unchecked constructor**: a validated value cannot be mutated
into an invalid one behind the type's back. Reading is via `Deref`, `get`, or
`into_inner`; `Refined` delegates `Clone`/`Copy`/`Debug`/`Display`/`PartialEq`/
`Eq`/`PartialOrd`/`Ord`/`Hash` to the inner value, bounded on `T` rather than the
marker `V`, so it slots into collections and comparisons unchanged. Cloning never
re-validates.
### `ValidationError` — a ready-made error
`ValidationError` is the default failure type for simple rules: a stable,
machine-readable `code` plus a human-readable `message`. It is `Copy`, allocates
nothing, has a `const` constructor, and works under `no_std`. Under the `std`
feature it implements `std::error::Error`.
```rust
use type_lib::ValidationError;
const EMPTY: ValidationError = ValidationError::new("non_empty", "value must not be empty");
assert_eq!(EMPTY.code(), "non_empty");
assert_eq!(EMPTY.to_string(), "non_empty: value must not be empty");
```
### `prelude` and documentation
A `prelude` module re-exports `Refined`, `Validator`, and `ValidationError`. Every
public item has rustdoc with at least one runnable example, and `docs/API.md` now
documents the full surface — each item with its parameters, return values, error
semantics, and multiple examples — alongside a Patterns section (domain-type
aliasing, cross-borrow rules, structured errors, updating a refined value).
### Tests
Unit tests live beside each item; `tests/foundation.rs` exercises the public API
end to end the way a downstream crate would — defining rules, wrapping values,
using refined values as map keys, and round-tripping through `into_inner`.
## Breaking changes
**None** relative to v0.1.0. `VERSION` is unchanged; everything else in v0.2.0 is
purely additive.
## 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
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
```
All green. Counts at this tag (identical with and without default features):
- 12 unit tests
- 6 integration tests (`foundation.rs` + `smoke.rs`)
- 17 doctests
## What's next
- **v0.5.0 — Implementation.** Built-in rule sets (length, range, pattern,
character class, …), rule composition, and a derive macro for generating
validated newtypes; property tests and benchmarks.
## Installation
```toml
[dependencies]
type-lib = "0.2.0"
# no_std build
type-lib = { version = "0.2.0", default-features = false }
```
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.1.0...v0.2.0`](https://github.com/jamesgober/type-lib/compare/v0.1.0...v0.2.0).
**Changelog:** [`CHANGELOG.md`](https://github.com/jamesgober/type-lib/blob/main/CHANGELOG.md#020---2026-05-27).