Skip to main content

Crate type_lib

Crate type_lib 

Source
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 a Validator. 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 short

Writing 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

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

The public API established in v0.2.0 is the surface 1.0 will preserve; v0.5.0 added the rule and combinator sets and v0.6.0 the derive macro, all additively.

§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 T that is guaranteed to satisfy the validator V.
ValidationError
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.

Derive Macros§

Validatedderive
Derives a validated newtype: a one-field tuple struct gains a checked constructor, accessors, and Deref, enforcing a Validator at construction.