Expand description
§type-lib
Parse-dont-validate domain types for Rust, with zero-overhead wrappers.
type-lib turns runtime invariants into compile-time guarantees. Rather than
re-checking a value everywhere it is used, you check it once, at
construction, and carry a type that can only exist in a valid state. Functions
that accept such a type are freed from defensive validation: the type system
has already done it.
§The foundation
Two pieces compose to express “a value that is known to be valid”:
Validator— a reusable, type-level validation rule. It is implemented on a zero-sized marker type and selected through the type system, so it carries no state and adds no storage.Refined— a#[repr(transparent)]wrapper holding a value proven to satisfy aValidator. It has the same size and layout as the value it wraps, so the guarantee is free at runtime.
A ready-made ValidationError covers rules that need only a code and a
message; rules that need structured failures define their own error type via
Validator::Error.
§Built-in rules and combinators
You rarely need to hand-write a rule. The rules module ships the common
ones — length (NonEmpty, MaxLen,
LenRange, …), numeric (Positive,
InRange, …), and string content
(Ascii, Alphanumeric,
Trimmed). The combinator module composes them at the
type level with And, Or, and
Not.
§Example
use type_lib::combinator::And;
use type_lib::rules::{LenRange, Trimmed};
use type_lib::Refined;
// A username: 3–16 characters with no surrounding whitespace.
type Username<'a> = Refined<&'a str, And<Trimmed, LenRange<3, 16>>>;
let user = Username::new("alice");
assert!(user.is_ok());
assert!(Username::new(" x ").is_err()); // whitespace + too shortWriting a bespoke rule is just as direct when the built-ins do not fit:
use type_lib::{Refined, ValidationError, Validator};
struct Even;
impl Validator<i64> for Even {
type Error = ValidationError;
fn validate(value: &i64) -> Result<(), Self::Error> {
if value % 2 == 0 {
Ok(())
} else {
Err(ValidationError::new("even", "value must be even"))
}
}
}
type EvenI64 = Refined<i64, Even>;
assert!(EvenI64::new(4).is_ok());
assert!(EvenI64::new(5).is_err());§Deriving validated newtypes
With the derive feature, #[derive(Validated)] generates a named domain
type from a one-field tuple struct, enforcing a Validator at construction:
use type_lib::rules::InRange;
use type_lib::Validated;
#[derive(Validated)]
#[valid(InRange<0, 100>)]
pub struct Percent(i32);
assert!(Percent::new(50).is_ok());
assert!(Percent::new(150).is_err());§Cargo features
std(default) — impliesallocand implementsstd::error::ErrorforValidationError.alloc— enables the length rules for ownedString/Vec<T>values.derive— enables theValidatedderive macro (see Deriving validated newtypes).
With no features (default-features = false), the crate is no_std and the
core Validator / Refined API plus all borrowed-value rules are
available unchanged.
§Stability
v1.0.0 is the stable API. The public surface is frozen under SemVer: no
breaking change ships without a 2.0. New rules, combinators, and trait impls
arrive as additive minor releases. The error codes returned by the built-in
rules are stable across 1.x.
§License
Dual-licensed under Apache-2.0 OR MIT.
Modules§
- combinator
- Combinators for composing
Validators. - prelude
- Common imports for working with
type-lib. - rules
- Built-in validation rules.
Structs§
- Refined
- A value of type
Tthat is guaranteed to satisfy the validatorV. - Validation
Error - A lightweight validation failure with a machine-readable code and a human-readable message.
Constants§
- VERSION
- Crate version string, populated by Cargo at build time.
Traits§
- Validator
- A reusable validation rule applied to values of type
T.