RustValidity is a powerful, flexible, and easy-to-use validation library for Rust that provides struct-level validation. It offers a wide range of built-in validation rules and supports custom validation logic.
Saeed Ghanbari - GitHub
- Comprehensive Rule Set: Includes common validations for strings, numbers, collections, and more
- Extensible: Easily create custom validation rules
- Flexible Error Handling: Support for single and multiple validation errors
- Attribute-Based Validation: Optional derive macro for struct field validation (with the
derive
feature) - Conditional Validation: Rules that apply only under specific conditions
- Cross-field Validation: Validate fields based on the values of other fields
- Collection Validation: Validate arrays, vectors, maps, and other collections
- Multiple error handling
- Nested struct validation
Add this to your Cargo.toml
:
[dependencies]
rustvalidity = "0.1.0"
use rustvalidity::error::ValidationError;
use rustvalidity::validator::{Validator, Validate};
use rustvalidity::rules::{common, numeric, collection};
struct User {
username: String,
email: String,
age: i32,
interests: Vec<String>,
}
impl Validate for User {
fn validate(&self) -> Result<(), ValidationError> {
// Create a new validator instance
let mut validator = Validator::new();
// Add validation rules
validator.add_rule("required", common::Required);
validator.add_rule("username_length", common::Length { min: 3, max: Some(20) });
validator.add_rule("email", common::Email { check_dns: false });
validator.add_rule("min_age", numeric::Min { value: 18 });
validator.add_rule("interests_required", collection::MinSize { min: 1 });
// Validate fields
if let Err(err) = validator.get_rule("required").unwrap().validate_any(&self.username) {
return Err(err);
}
if let Err(err) = validator.get_rule("username_length").unwrap().validate_any(&self.username) {
return Err(err);
}
if let Err(err) = validator.get_rule("email").unwrap().validate_any(&self.email) {
return Err(err);
}
if let Err(err) = validator.get_rule("min_age").unwrap().validate_any(&self.age) {
return Err(err);
}
if let Err(err) = validator.get_rule("interests_required").unwrap().validate_any(&self.interests) {
return Err(err);
}
Ok(())
}
}
fn main() {
let user = User {
username: "johndoe".to_string(),
email: "john@example.com".to_string(),
age: 25,
interests: vec!["coding".to_string(), "reading".to_string()],
};
match user.validate() {
Ok(_) => println!("User is valid!"),
Err(err) => println!("Validation failed: {}", err),
}
}
Required
: Validates that a value is not emptyLength
: Validates string length (min, max)Email
: Validates email formatUrlRule
: Validates URL format with optional scheme restrictionsUuidRule
: Validates UUID formatJson
: Validates JSON formatDate
: Validates date format and rangePhone
: Validates phone number formatOneOf
: Validates that a value is one of a set of allowed valuesCustom
: Create custom validation rules with closures
Min
: Validates minimum valueMax
: Validates maximum valueRange
: Validates value within a rangePositive
: Validates positive numbersNegative
: Validates negative numbersDivisibleBy
: Validates divisibility
Unique
: Validates collection elements are uniqueContains
: Validates collection contains a specific valueEach
: Applies a validation rule to each elementMap
: Validates map keys and valuesMinSize
: Validates minimum collection sizeMaxSize
: Validates maximum collection sizeExactSize
: Validates exact collection size
If
: Validates a value only if a condition is trueUnless
: Validates a value only if a condition is falseRequiredIf
: Validates that a value is required if a condition is trueRequiredWith
: Validates that a value is required if another field has a specific valueRequiredWithout
: Validates that a value is required if another field does not have a specific valueRequiredIfAny
: Validates that a value is required if any of the specified conditions are trueRequiredIfAll
: Validates that a value is required if all of the specified conditions are true
Password
: Validates password complexityCreditCard
: Validates credit card numbersSemVer
: Validates semantic version stringsDomain
: Validates domain namesPort
: Validates port numbersIP
: Validates IP addressesRegexRule
: Validates against a regular expression
You can create custom validation rules by implementing the Rule
trait:
use rustvalidity::error::ValidationError;
use rustvalidity::rules::Rule;
struct MyCustomRule;
impl Rule for MyCustomRule {
fn validate_any(&self, value: &dyn std::any::Any) -> Result<(), ValidationError> {
// Your custom validation logic here
Ok(())
}
}
Rustvalidity provides two types of validation errors:
ValidationError::Single
- A single validation error with a messageValidationError::Multiple
- Multiple validation errors grouped by field
You can collect all validation errors using the validate_all
method:
let errors = validator.validate_all(&value);
Check out the examples directory for more usage examples:
user_validation.rs
- Basic validation exampleattribute_validation.rs
- Advanced validation with struct attributes
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.