Crate checked_rs

source ·
Expand description

§checked-rs

A library for encoding validation semantics into the type system.

§Overview

The main components of this library are the structs View (plus the Validator trait), HardClamp, SoftClamp and the attribute macro clamped. Additionally, there are some traits and types such as Behavior and ClampGuard that either configure how overflow is handled or provide an alternative way to interact with the clamped types.

§HardClamp

The HardClamp struct is a wrapper around an unsigned integer that clamps the value to a specified range.

use checked_rs::prelude::*;

let mut val = HardClamp::<u8, Saturating, 0, 10>::new(5).unwrap();
assert_eq!(val.get(), 5);

val += 5;
assert_eq!(val.get(), 10);

val -= 15;
assert_eq!(val.get(), 0);

val += 20;
assert_eq!(val.get(), 10);

§SoftClamp

The SoftClamp struct is a wrapper around an unsigned integer that can be checked for if it is within a specified range.

use checked_rs::prelude::*;

let mut val = SoftClamp::<u8, Saturating, 0, 10>::new(5);
assert_eq!(*val, 5);
assert_eq!(val.is_valid(), true);

val += 5;
assert_eq!(*val, 10);
assert_eq!(val.is_valid(), true);

val -= 15;
assert_eq!(*val, 0);
assert_eq!(val.is_valid(), true);

*val = 30;
assert_eq!(*val, 30);
assert_eq!(val.is_valid(), false);

§Behavior

The Behavior trait is used to configure how overflow is handled for the clamped types. There are two inherent implementations of Behavior that can be used: Panicking and Saturating. The default behavior is to panic on overflow.

§ClampGuard

The ClampGuard struct is a RAII type that is used to modify a clamped value via an exclusive borrow. It will allow the value it tracks to go out of bounds temporarily, but will not allow any value to propagate to the original that is invalid. This is also useful when you want to change a value temporarily and then revert it back to the original value if the change is not valid or is otherwise unwanted.

use checked_rs::prelude::*;

let mut val = HardClamp::<u8, Saturating, 0, 10>::new(5).unwrap();

assert_eq!(val.get(), 5);

let mut g = val.modify();

assert_eq!(g.is_changed(), false);

*g = 10;

assert_eq!(g.is_changed(), true);

g.commit().unwrap();

assert_eq!(val.get(), 10);

let mut g = val.modify();
*g = 15;

assert!(g.check().is_err());

g.discard();

assert_eq!(val.get(), 10);

§View

The View struct is a wrapper around a value that encodes it’s validation logic into the wrapper. The Validator trait is used to define the validation logic for a View. This wrapper is lightweight and can be used in place of the raw value via the Deref and/or AsRef traits.

use checked_rs::prelude::*;

#[derive(Clone, Copy)]
struct NotSeven;

impl Validator for NotSeven {
    type Item = i32;
    type Error = anyhow::Error;

    fn validate(item: &Self::Item) -> Result<()> {
        if *item == 7 {
            Err(anyhow::anyhow!("Value must not be 7"))
        } else {
            Ok(())
        }
    }
}

let mut item = View::with_validator(0, NotSeven);
let mut g = item.modify();

*g = 7;
assert_eq!(*g, 7);
assert!(g.check().is_err());

*g = 10;
assert!(g.commit().is_ok());

// the guard is consumed by commit, so we can't check it again
// the `View`'s value should be updated
assert_eq!(&*item, &10);

§clamped attribute macro

The clamped attribute macro is used to create a specialized clamped type. The macro can only be used on enums where each variant represents a specific state within the clamped range. This can be useful when there are multiple states that correspond to a certain set of rules and you want them to be easily distinguishable while still being able to use them in a single integer-like type.

use checked_rs::prelude::*;

#[clamped(u16, default = 600, behavior = Saturating, lower = 100, upper = 600)]
#[derive(Debug, Clone, Copy)]
enum ResponseCode {
    #[eq(100)]
    Continue,
    #[eq(200)]
    Success,
    #[eq(300)]
    Redirection,
    #[eq(400)]
    BadRequest,
    #[eq(404)]
    NotFound,
    #[range(500..=599)]
    ServerError,
    #[other]
    Unknown,
    #[eq(600)]
    Invalid,
}

Modules§

Macros§

Traits§