GType

A lightweight, no_std-friendly validated value type.
GType<T, V> wraps a value of type T and guarantees that it satisfies the constraints defined by a validator V.
Validators can provide:
- Minimum and maximum bounds
- Arbitrary validation logic
- Custom error types
Features
no_std compatible
- Zero-cost abstraction after construction
- Optional validation
- Compile-time validator definitions
- Custom validation errors
- Works with primitive and user-defined types
- Preserves common traits such as
Clone, Copy, Eq, Ord, Hash, Display, and Debug
Basic Usage
use g_type::{GType, Validator};
struct Percent;
impl Validator<u8> for Percent {
type Target = u8;
type Error = core::convert::Infallible;
fn min() -> Option<&'static Self::Target> {
Some(&0)
}
fn max() -> Option<&'static Self::Target> {
Some(&100)
}
}
type Percentage = GType<u8, Percent>;
let value = Percentage::try_new(75).unwrap();
assert_eq!(value.into_inner(), 75);
Custom Validation
Validators may perform arbitrary runtime checks.
use g_type::{GType, Validator};
#[derive(Debug, Clone, PartialEq, Eq)]
struct EvenError;
struct Even;
impl Validator<u32> for Even {
type Target = u32;
type Error = EvenError;
fn validate(value: &u32) -> Result<(), Self::Error> {
if value % 2 == 0 {
Ok(())
} else {
Err(EvenError)
}
}
}
type EvenNumber = GType<u32, Even>;
assert!(EvenNumber::try_new(4).is_ok());
assert!(EvenNumber::try_new(5).is_err());
No Validation
Use the default validator when no validation is required.
use g_type::GType;
let value = g_type::GType::<u32>::try_new(42).unwrap();
assert_eq!(value.into_inner(), 42);
Transforming Values
map() transforms the inner value and validates the result using the destination validator.
let value = g_type::GType::<u32>::try_new(50).unwrap();
struct Percent;
impl g_type::Validator<u8> for Percent {
type Target = u8;
type Error = core::convert::Infallible;
fn min() -> Option<&'static Self::Target> {
Some(&0)
}
fn max() -> Option<&'static Self::Target> {
Some(&100)
}
}
let percent = value.map::<u8, Percent, _>(|v| v as u8).unwrap();
assert_eq!(percent.into_inner(), 50);
and_then() allows chaining validated transformations.
let value = g_type::GType::<u32>::try_new(50).unwrap();
struct Percent;
impl g_type::Validator<u8> for Percent {
type Target = u8;
type Error = core::convert::Infallible;
fn min() -> Option<&'static Self::Target> {
Some(&0)
}
fn max() -> Option<&'static Self::Target> {
Some(&100)
}
}
let percent = value.and_then::<u8, Percent, _>(|v| {
g_type::GType::<u8, Percent>::try_new(v as u8)
}).unwrap();
Error Handling
Construction may fail for three reasons:
pub enum GTypeError<E> {
MinExceedsMax,
BelowMinimum,
AboveMaximum,
Validation(E),
}
MinExceedsMax — minimum value exceeds maximum value.
BelowMinimum — value is below the validator minimum.
AboveMaximum — value exceeds the validator maximum.
Validation(E) — custom validator rejected the value.
Design
A validator is a type implementing:
pub trait Validator<T> {
type Target: PartialOrd<Self::Target> + PartialOrd<T> + ?Sized + 'static;
type Error;
#[inline]
fn min() -> Option<&'static Self::Target> {
None
}
#[inline]
fn max() -> Option<&'static Self::Target> {
None
}
#[inline]
fn validate(_: &T) -> Result<(), Self::Error> {
Ok(())
}
}
Validators are stateless marker types. All constraints are defined through associated functions, making them easy to use in const contexts and zero-sized at runtime.