4 releases
Uses new Rust 2021
new 0.2.1 | May 21, 2022 |
---|---|
0.2.0 | May 10, 2022 |
0.1.2 | May 4, 2022 |
0.1.1 | May 4, 2022 |
0.1.0 |
|
#181 in Data structures
186 downloads per month
29KB
516 lines
type-rules
A tool to easily constrain a struct and recover errors.
Table of Contents
Install
# Cargo.toml
[dependencies]
type-rules = { version = "0.2.1", features = ["derive", "regex"] }
Basic checking
You can declare a struct and impose some constraints on each field and check the validity like this:
use chrono::prelude::*;
use type_rules::prelude::*;
#[derive(Validator)]
struct NewUser {
#[rule(MaxLength(100), RegEx(r"^\S+@\S+\.\S+"))]
email: String,
#[rule(MinMaxLength(8, 50))]
password: String,
#[rule(Opt(MaxRange(Utc::now())))]
birth_date: Option<DateTime<Utc>>
}
let new_user = NewUser {
email: "examples@examples.com".to_string(),
password: "OPw$5%hJ".to_string(),
birth_date: None,
};
assert!(new_user.check_validity().is_ok());
let new_user = NewUser {
email: "examples@examples.com".to_string(),
password: "O".to_string(),
birth_date: None,
};
assert!(new_user.check_validity().is_err()); //Value is too short
Also works with enums :
use type_rules::prelude::*;
#[derive(Validator)]
enum MyEnum {
Option1(#[rule(MaxLength(200))] String),
Option2 {
#[rule(MinMaxRange(1, 10))]
integer: u32
},
Option3,
}
Advanced checking
To check recursively, you can use the Validate
rule
use type_rules::prelude::*;
#[derive(Validator)]
struct EmailWrapper(#[rule(MaxLength(100), RegEx(r"^\S+@\S+\.\S+"))] String);
#[derive(Validator)]
struct User {
#[rule(Validate())]
email: EmailWrapper,
#[rule(MinMaxLength(8, 50))]
password: String,
}
You can use expressions directly in rule derive attribute.
For example, you can use const or function directly in the rule parameters:
use type_rules::prelude::*;
use chrono::prelude::*;
#[derive(Validator)]
struct BirthDate(#[rule(MaxRange(Utc::now()))] DateTime<Utc>);
use type_rules::prelude::*;
#[derive(Validator)]
struct Range {
#[rule(MaxRange(self.max))]
min: u32,
#[rule(MinRange(self.min))]
max: u32,
};
Or use expressions to express a rule directly. Here is an example of using a rule with more complex values:
use std::env;
use type_rules::prelude::*;
fn generate_max_payload_rule() -> MaxLength {
MaxLength(match env::var("MAX_PAYLOAD") {
Ok(val) => val.parse().unwrap_or_else(|_| 10000),
Err(_) => 10000,
})
}
#[derive(Validator)]
struct Payload(#[rule(generate_max_payload_rule())] String);
In this case the generate_max_payload_rule
function is executed at each check
Make your own rule
If you need a specific rule, just make a tuple struct (or struct if you make the declaration outside the struct
definition)
that implements the Rule
feature :
use type_rules::prelude::*;
struct IsEven();
impl Rule<i32> for IsEven {
fn check(&self, value: &i32) -> Result<(), String> {
if value % 2 == 0 {
Ok(())
} else {
Err("Value is not even".into())
}
}
}
#[derive(Validator)]
struct MyInteger(#[rule(IsEven())] i32);
Rules list
Here a list of the rules you can find in this crate.
Each rule has its own documentation with examples.
Check the length of any type that implements AsRef<str>
such
as String
or &str
:
MinLength
: Minimum length ex:MinLength(5)
MaxLength
: Maximum length ex:MaxLength(20)
MinMaxLength
: Minimum and maximum length ex:MinMaxLength(5, 20)
Check the range for anything that implements PartialOrd<Self>
like all numeric/floating types
or dates with chrono
:
MinRange
: Minimum range ex:MinRange(5)
MaxRange
: Maximum range ex:MaxRange(20)
MinMaxRange
: Minimum and maximum range ex:MinMaxRange(5, 20)
Check the size of a Vec<T>
:
MinSize
: Minimum size ex:MinSize(5)
MaxSize
: Maximum size ex:MaxSize(20)
MinMaxSize
: Minimum and maximum size ex:MinMaxSize(5, 20)
others :
Opt
: Apply another rule to inner value of anOption
ex:Opt(MinMaxRange(1, 4))
And
: Rule to ensure that 2 other rules areOk
ex:And(MaxLength(1000), RegEx(r"^\S+@\S+\.\S+"))
Or
: Rule to apply an Or condition on two other rules. ex:Or(MaxRange(-1), MinRange(1))
Eval
: Rule to constrain any type to a predicate ex:Eval(predicate, "Error message")
Validate
: Recursive checking ex:Validate()
In
: Rule to constrain a type to bein
a collection ex:In(["apple", "banana", "orange", "pear"], "Value need to be a fruit")
All
: Rule to constrain a collection to valid the specified rule ex:All(MinLength(1), "You can't use empty string")
RegEx
: check if a type that implementAsRef<str>
(String, &str, ...) matches the regex. You need theregex
feature to use it. ex:RegEx(r"^\S+@\S+\.\S+")
Dependencies
~100KB