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
derivefeature) - 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.