#validation #mongo-db #async #forms

validate-ro

A flexible validation framework with sync/async support and MongoDB integration

7 releases

Uses new Rust 2024

0.3.1 Jun 12, 2025
0.3.0 Jun 12, 2025
0.2.0 Jun 12, 2025
0.1.4 May 28, 2025

#530 in Web programming

Download history 190/week @ 2025-05-19 401/week @ 2025-05-26 21/week @ 2025-06-02 353/week @ 2025-06-09 29/week @ 2025-06-16

852 downloads per month

MIT/Apache

53KB
1K SLoC

Validation Library

Crates.io Documentation License

A flexible, extensible validation framework for Rust with support for both synchronous and asynchronous validation, including MongoDB integration for unique checks.

Features

  • 🛠️ 40+ built-in validators for common validation scenarios
  • Async support for database-backed validation
  • 🏗️ Composable rules with fluent builder pattern
  • 📝 Nested field validation using dot notation
  • 🧩 Custom validators for specialized requirements
  • 🗃️ MongoDB integration for unique field validation
  • 🏷️ Default values for missing fields
  • 🚦 Flexible error handling with detailed error messages

Installation

Add to your Cargo.toml:

[dependencies]
validate-ro = "0.1"

Quick Start

use validate_ro::{FormValidator,Rules,rules, rules::Rule};
use serde_json::json;

fn main() {
    // Build a validator
    let validator = FormValidator::new()
        .add("username", Rules::new().add(Rule::required()).add(Rule::min_length(5)))
        .add("email", rules![Rule::required(),Rule::email(None)])
        .add("age", Rules::new().add(Rule::integer()).add(Rule::min_value(18.0)).default(json!(21)));

    // Validate some data
    let data = json!({
        "username": "user123",
        "email": "test@example.com"
    });

    match validator.validate(&data) {
        Ok(valid_data) => {
            println!("Valid data: {:?}", valid_data);  // age will be 21 (default)
        },
        Err(errors) => {
            eprintln!("Validation errors: {:?}", errors);
        }
    }
}

Core Concepts

1. Basic Validation

use validate_ro::Rules;
use validate_ro::rules::Rule;

// Single field validation
let is_adult = Rules::new().add(Rule::integer()).add(Rule::min_value(18.0));
assert!(is_adult.validate(&json!(21)).is_ok());

// or use macro
let is_adult = rules![Rule::integer(),Rule::min_value(18.0)];
assert!(is_adult.validate(&json!(21)).is_ok());

2. Combining Rules

let password_validator = Rules::new().add(Rule::required())
    .add(Rule::min_length(8))
    .add(Rule::regex(r"[A-Z]", Some("Must contain uppercase".into())).unwrap());

3. Form Validation

let form_validator = FormValidator::new()
    .add("user.name", Rule::required())
    .add("user.email", Rule::email(None))
    .add("user.age", Rule::integer());

4. Async Validation (MongoDB)

#[tokio::main]
async fn main() {
    let client = mongodb::Client::with_uri_str("mongodb://localhost:27017").await.unwrap();
    let db = Arc::new(client.database("test"));
    
    let validator = FormValidator::new()
        .add("email", Rule::unique("users", "email", None));

    let result = validator.validate_async(&db, &json!({"email": "user@example.com"})).await;
}

Available Validators

Basic Validators

  • required() - Field must be present and not null
  • string() - Must be a string
  • integer() - Must be an integer
  • float() - Must be a float
  • boolean() - Must be a boolean
  • array() - Must be an array
  • object() - Must be an object

String Validators

  • length(n) - Exact length
  • min_length(n) - Minimum length
  • max_length(n) - Maximum length
  • email() - Valid email format
  • url() - Valid URL format
  • ip() - Valid IP address
  • regex() - Matches regex pattern
  • accepted() - Common "accepted" terms (true, 1, "yes", "on")

Numeric Validators

  • min_value(n) - Minimum value
  • max_value(n) - Maximum value
  • equal(n) - Exact value match
  • numeric() - Can be parsed as number

Collection Validators

  • in_values() - Value must be in allowed set
  • not_in_values() - Value must not be in excluded set

Database Validators

  • unique() - Field value must be unique in MongoDB collection

File Validators

  • extensions() - File extension must be in allowed set

Advanced Usage

Custom Validators

let validator = Rule::custom(|value| {
    if let Some(s) = value.as_str() {
        if s.starts_with("prefix_") {
            Ok(())
        } else {
            Err(ValidationError::Custom("Must start with 'prefix_'".into()))
        }
    } else {
        Err(ValidationError::TypeError {
            expected: "string".into(),
            got: value.to_string()
        })
    }
});

Error Handling

match validator.validate(&data) {
    Ok(valid_data) => { /* handle success */ },
    Err(errors) => {
        for (field, field_errors) in errors {
            println!("Field '{}' errors:", field);
            for error in field_errors {
                println!("- {}", error);
            }
        }
    }
}

Performance

The library is designed for efficiency:

  • Minimal allocations
  • Lazy validation (stops on first error when configured)
  • Thread-safe by design

Contributing

Contributions are welcome! Please open an issue or submit a PR for:

  • New features
  • Performance improvements
  • Bug fixes

License

Dual-licensed under MIT or Apache 2.0 at your option.

Dependencies

~17–29MB
~452K SLoC