Elysia Tools

Browse tools, examples, visual explainers, and topic guides from one clear workspace.

Top Categories

Hubs

Language
ZHDERUPTENFRES

Elysia Tools

Navigation

Rust

Web Error Handling Rust Samples

Web Rust error handling examples including exception catching, logging, and parameter validation

Samples

Entries inside this sample collection

CoderustIntermediate

Exception Catching

Handle errors using Result, Option, and custom error types

Difficulty

6/10

Estimated time

25 min

Tags

rust, web, error handling

Prerequisites

Intermediate Rust

rust
// Web Rust Exception Catching Examples
// Error handling with Result, Option, and custom errors

use std::fmt;
use std::io;

// 1. Custom Error Types

/// Custom error type with detailed information
#[derive(Debug)]
enum AppError {
    Io(io::Error),
    Parse(String),
    Validation(String),
    NotFound(String),
    Permission(String),
}

impl fmt::Display for AppError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            AppError::Io(err) => write!(f, "IO error: {}", err),
            AppError::Parse(msg) => write!(f, "Parse error: {}", msg),
            AppError::Validation(msg) => write!(f, "Validation error: {}", msg),
            AppError::NotFound(msg) => write!(f, "Not found: {}", msg),
            AppError::Permission(msg) => write!(f, "Permission denied: {}", msg),
        }
    }
}

impl std::error::Error for AppError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            AppError::Io(err) => Some(err),
            _ => None,
        }
    }
}

impl From<io::Error> for AppError {
    fn from(err: io::Error) -> Self {
        AppError::Io(err)
    }
}

// 2. Result Handling

/// Basic Result handling
fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        Err(String::from("Division by zero"))
    } else {
        Ok(a / b)
    }
}

/// Result with custom error
fn read_file_content(path: &str) -> Result<String, AppError> {
    std::fs::read_to_string(path).map_err(AppError::from)
}

/// Chain multiple Results
fn process_file(path: &str) -> Result<usize, AppError> {
    let content = read_file_content(path)?;
    let count = content.lines().count();
    Ok(count)
}

// 3. Option Handling

/// Safe division returning Option
fn safe_divide(a: f64, b: f64) -> Option<f64> {
    if b == 0.0 {
        None
    } else {
        Some(a / b)
    }
}

/// Get element from vector
fn get_element<T>(vec: &[T], index: usize) -> Option<&T> {
    vec.get(index)
}

/// Parse to integer with Option
fn parse_optional(s: &str) -> Option<i32> {
    s.parse().ok()
}

// 4. Error Propagation

/// Function that propagates errors
fn load_config(path: &str) -> Result<String, AppError> {
    let content = std::fs::read_to_string(path)?;
    Ok(content)
}

/// Function with custom error creation
fn validate_username(name: &str) -> Result<(), AppError> {
    if name.is_empty() {
        return Err(AppError::Validation("Username cannot be empty".to_string()));
    }
    if name.len() < 3 {
        return Err(AppError::Validation("Username must be at least 3 characters".to_string()));
    }
    if name.len() > 20 {
        return Err(AppError::Validation("Username must be at most 20 characters".to_string()));
    }
    Ok(())
}

// 5. Multiple Error Types

/// Operation that can fail in multiple ways
fn complex_operation(path: &str) -> Result<String, Box<dyn std::error::Error>> {
    let content = std::fs::read_to_string(path)?;
    let trimmed = content.trim();
    if trimmed.is_empty() {
        return Err("File is empty".into());
    }
    Ok(trimmed.to_string())
}

// 6. Error Recovery

/// Attempt operation with fallback
fn read_with_fallback(path: &str, fallback: &str) -> String {
    read_file_content(path).unwrap_or_else(|_| fallback.to_string())
}

/// Try multiple alternatives
fn try_alternatives(paths: &[&str]) -> Result<String, AppError> {
    for path in paths {
        if let Ok(content) = read_file_content(path) {
            return Ok(content);
        }
    }
    Err(AppError::NotFound("No valid path found".to_string()))
}

// 7. Error Context

/// Add context to errors
fn read_file_with_context(path: &str) -> Result<String, AppError> {
    std::fs::read_to_string(path)
        .map_err(|e| AppError::Io(e))
        .and_then(|content| {
            if content.is_empty() {
                Err(AppError::Parse(format!("File {} is empty", path)))
            } else {
                Ok(content)
            }
        })
}

// 8. Panic Handling

/// Function that may panic
fn risky_operation(value: i32) -> i32 {
    if value < 0 {
        panic!("Negative value not allowed: {}", value);
    }
    value * 2
}

/// Catch panic using std::panic
fn safe_risky_operation(value: i32) -> Result<i32, String> {
    std::panic::catch_unwind(|| risky_operation(value))
        .map_err(|_| "Panic occurred".to_string())
}

// 9. Combining Results

/// Combine multiple Results
fn combine_results(results: Vec<Result<i32, String>>) -> Result<Vec<i32>, String> {
    results.into_iter().collect()
}

/// Collect first error or all successes
fn collect_first_error<T, E>(results: Vec<Result<T, E>>) -> Result<Vec<T>, E> {
    results.into_iter().collect()
}

// 10. Conditional Error Handling

/// Handle error based on type
fn handle_io_error(result: Result<String, io::Error>) -> String {
    match result {
        Ok(content) => content,
        Err(e) if e.kind() == io::ErrorKind::NotFound => "File not found".to_string(),
        Err(e) if e.kind() == io::ErrorKind::PermissionDenied => "Permission denied".to_string(),
        Err(e) => format!("IO error: {}", e),
    }
}

// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Web Rust Exception Catching Examples ===\n");

    // 1. Basic Result handling
    println!("--- 1. Basic Result ---");
    match divide(10.0, 2.0) {
        Ok(result) => println!("10 / 2 = {}", result),
        Err(e) => println!("Error: {}", e),
    }
    match divide(10.0, 0.0) {
        Ok(result) => println!("10 / 0 = {}", result),
        Err(e) => println!("Error: {}", e),
    }

    // 2. Option handling
    println!("
--- 2. Option ---");
    println!("10 / 2 = {:?}", safe_divide(10.0, 2.0));
    println!("10 / 0 = {:?}", safe_divide(10.0, 0.0));

    let vec = vec![1, 2, 3];
    println!("Element at index 1: {:?}", get_element(&vec, 1));
    println!("Element at index 10: {:?}", get_element(&vec, 10));

    // 3. Custom errors
    println!("
--- 3. Custom Errors ---");
    match validate_username("") {
        Ok(_) => println!("Username valid"),
        Err(e) => println!("Validation error: {}", e),
    }
    match validate_username("ab") {
        Ok(_) => println!("Username valid"),
        Err(e) => println!("Validation error: {}", e),
    }
    match validate_username("valid_user") {
        Ok(_) => println!("Username valid"),
        Err(e) => println!("Validation error: {}", e),
    }

    // 4. Error propagation
    println!("
--- 4. Error Propagation ---");
    match load_config("nonexistent.txt") {
        Ok(_) => println!("Config loaded"),
        Err(e) => println!("Load error: {}", e),
    }

    // 5. Multiple error types
    println!("
--- 5. Multiple Error Types ---");
    match complex_operation("test.txt") {
        Ok(content) => println!("Content length: {}", content.len()),
        Err(e) => println!("Error: {}", e),
    }

    // 6. Fallback
    println!("
--- 6. Fallback ---");
    let result = read_with_fallback("missing.txt", "default content");
    println!("With fallback: {}", result);

    // 7. Try alternatives
    println!("
--- 7. Try Alternatives ---");
    let paths = ["file1.txt", "file2.txt", "file3.txt"];
    match try_alternatives(&paths) {
        Ok(_) => println!("Found a valid file"),
        Err(e) => println!("All alternatives failed: {}", e),
    }

    // 8. Combine results
    println!("
--- 8. Combine Results ---");
    let results = vec![
        Ok(1),
        Ok(2),
        Err("Error 3".to_string()),
        Ok(4),
    ];
    match combine_results(results) {
        Ok(values) => println!("All results: {:?}", values),
        Err(e) => println!("Failed with: {}", e),
    }

    // 9. Panic handling
    println!("
--- 9. Panic Handling ---");
    match safe_risky_operation(10) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Panic caught: {}", e),
    }
    match safe_risky_operation(-5) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Panic caught: {}", e),
    }

    // 10. Conditional error handling
    println!("
--- 10. Conditional Error Handling ---");
    let io_result: Result<String, io::Error> = Err(io::Error::new(io::ErrorKind::NotFound, "Not found"));
    println!("IO error: {}", handle_io_error(io_result));

    println!("
=== All Exception Catching Examples Completed ===");
    Ok(())
}
CoderustSimple

Logging

Write logs to files and console with different levels

Difficulty

5/10

Estimated time

20 min

Tags

rust, web, error handling

Prerequisites

Basic Rust, chrono crate

rust
// Web Rust Logging Examples
// Log writing to files and console
//
// Add to Cargo.toml:
// [dependencies]
// log = "0.4"
// env_logger = "0.10"
// chrono = "0.4"

use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::Path;

// 1. Simple Logging to File

/// Log message to file
fn log_to_file(path: &str, message: &str) -> std::io::Result<()> {
    let mut file = OpenOptions::new()
        .create(true)
        .append(true)
        .open(path)?;
    writeln!(file, "{}", message)?;
    Ok(())
}

/// Log with timestamp
fn log_with_timestamp(path: &str, level: &str, message: &str) -> std::io::Result<()> {
    let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S");
    let log_entry = format!("[{}] {} - {}", timestamp, level, message);
    log_to_file(path, &log_entry)
}

// 2. Log Levels

/// Log debug message
fn log_debug(path: &str, message: &str) -> std::io::Result<()> {
    log_with_timestamp(path, "DEBUG", message)
}

/// Log info message
fn log_info(path: &str, message: &str) -> std::io::Result<()> {
    log_with_timestamp(path, "INFO", message)
}

/// Log warning message
fn log_warning(path: &str, message: &str) -> std::io::Result<()> {
    log_with_timestamp(path, "WARNING", message)
}

/// Log error message
fn log_error(path: &str, message: &str) -> std::io::Result<()> {
    log_with_timestamp(path, "ERROR", message)
}

// 3. Structured Logging

/// Structured log entry
#[derive(Debug)]
struct LogEntry {
    timestamp: String,
    level: String,
    message: String,
    module: Option<String>,
}

impl LogEntry {
    fn new(level: &str, message: &str) -> Self {
        LogEntry {
            timestamp: chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f").to_string(),
            level: level.to_string(),
            message: message.to_string(),
            module: None,
        }
    }

    fn with_module(mut self, module: &str) -> Self {
        self.module = Some(module.to_string());
        self
    }

    fn format(&self) -> String {
        match &self.module {
            Some(m) => format!("[{}] [{}] [{}] - {}", self.timestamp, self.level, m, self.message),
            None => format!("[{}] [{}] - {}", self.timestamp, self.level, self.message),
        }
    }
}

/// Write structured log
fn write_structured_log(path: &str, entry: &LogEntry) -> std::io::Result<()> {
    log_to_file(path, &entry.format())
}

// 4. Logger with Multiple Outputs

/// Simple logger that writes to multiple destinations
struct MultiLogger {
    log_file: String,
    console: bool,
}

impl MultiLogger {
    fn new(log_file: &str, console: bool) -> Self {
        MultiLogger {
            log_file: log_file.to_string(),
            console,
        }
    }

    fn log(&self, level: &str, message: &str) -> std::io::Result<()> {
        let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S");
        let log_entry = format!("[{}] {} - {}", timestamp, level, message);

        // Write to file
        if !self.log_file.is_empty() {
            log_to_file(&self.log_file, &log_entry)?;
        }

        // Write to console
        if self.console {
            println!("{}", log_entry);
        }

        Ok(())
    }

    fn info(&self, message: &str) -> std::io::Result<()> {
        self.log("INFO", message)
    }

    fn warning(&self, message: &str) -> std::io::Result<()> {
        self.log("WARNING", message)
    }

    fn error(&self, message: &str) -> std::io::Result<()> {
        self.log("ERROR", message)
    }

    fn debug(&self, message: &str) -> std::io::Result<()> {
        self.log("DEBUG", message)
    }
}

// 5. Rotating Log Files

/// Rotating logger
struct RotatingLogger {
    base_path: String,
    max_size: u64,
    current_file: String,
    current_size: u64,
}

impl RotatingLogger {
    fn new(base_path: &str, max_size: u64) -> Self {
        let current_file = format!("{}.log", base_path);
        RotatingLogger {
            base_path: base_path.to_string(),
            max_size,
            current_file: current_file.clone(),
            current_size: std::fs::metadata(&current_file).map(|m| m.len()).unwrap_or(0),
        }
    }

    fn log(&mut self, message: &str) -> std::io::Result<()> {
        let entry = format!("{}\n", message);
        let entry_size = entry.len() as u64;

        // Check if rotation needed
        if self.current_size + entry_size > self.max_size {
            self.rotate()?;
        }

        // Append to current file
        let mut file = OpenOptions::new()
            .create(true)
            .append(true)
            .open(&self.current_file)?;
        file.write_all(entry.as_bytes())?;
        self.current_size += entry_size;

        Ok(())
    }

    fn rotate(&mut self) -> std::io::Result<()> {
        // Find next available number
        let mut counter = 1;
        loop {
            let archive_name = format!("{}.{}.log", self.base_path, counter);
            if !Path::new(&archive_name).exists() {
                std::fs::rename(&self.current_file, &archive_name)?;
                break;
            }
            counter += 1;
        }

        // Reset current file
        self.current_size = 0;
        Ok(())
    }
}

// 6. Conditional Logging

/// Logger with level filtering
struct LevelLogger {
    log_file: String,
    min_level: String,
}

impl LevelLogger {
    fn new(log_file: &str, min_level: &str) -> Self {
        LevelLogger {
            log_file: log_file.to_string(),
            min_level: min_level.to_string(),
        }
    }

    fn should_log(&self, level: &str) -> bool {
        let levels = vec!["DEBUG", "INFO", "WARNING", "ERROR"];
        let current = levels.iter().position(|&l| l == level).unwrap_or(0);
        let min = levels.iter().position(|&l| l == &self.min_level).unwrap_or(0);
        current >= min
    }

    fn log(&self, level: &str, message: &str) -> std::io::Result<()> {
        if self.should_log(level) {
            log_with_timestamp(&self.log_file, level, message)?;
        }
        Ok(())
    }
}

// 7. Async Logging (Simplified)

/// Async-style logger using channels
use std::sync::mpsc;
use std::thread;

struct AsyncLogger {
    sender: mpsc::Sender<String>,
}

impl AsyncLogger {
    fn new(log_file: &str) -> Self {
        let (sender, receiver) = mpsc::channel();
        let log_file = log_file.to_string();

        thread::spawn(move || {
            let mut file = OpenOptions::new()
                .create(true)
                .append(true)
                .open(&log_file)
                .unwrap();

            for message in receiver {
                writeln!(file, "{}", message).unwrap();
            }
        });

        AsyncLogger { sender }
    }

    fn log(&self, message: &str) -> std::io::Result<()> {
        self.sender.send(message.to_string()).map_err(|e| {
            std::io::Error::new(std::io::ErrorKind::Other, e)
        })?;
        Ok(())
    }
}

// 8. Performance Logging

/// Performance logger
fn log_performance(path: &str, operation: &str, duration_ms: u128) -> std::io::Result<()> {
    let message = format!("Operation '{}' took {}ms", operation, duration_ms);
    log_with_timestamp(path, "PERF", &message)
}

/// Measure execution time
fn measure_time<F, T>(f: F) -> T
where
    F: FnOnce() -> T,
{
    f()
}

/// Measure and log execution time
fn measure_and_log<F, T>(path: &str, operation: &str, f: F) -> T
where
    F: FnOnce() -> T,
{
    let start = std::time::Instant::now();
    let result = f();
    let duration = start.elapsed().as_millis();
    let _ = log_performance(path, operation, duration);
    result
}

// 9. Error Logging

/// Log error with backtrace
fn log_error_with_context(path: &str, error: &str, context: &str) -> std::io::Result<()> {
    let message = format!("Error in '{}': {}", context, error);
    log_with_timestamp(path, "ERROR", &message)
}

/// Log warning with details
fn log_warning_details(path: &str, message: &str, details: &str) -> std::io::Result<()> {
    let log_msg = format!("{} | Details: {}", message, details);
    log_with_timestamp(path, "WARNING", &log_msg)
}

// 10. Batch Logging

/// Log multiple messages efficiently
fn log_batch(path: &str, messages: &[&str]) -> std::io::Result<()> {
    let mut file = OpenOptions::new()
        .create(true)
        .append(true)
        .open(path)?;

    for message in messages {
        let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S");
        writeln!(file, "[{}] - {}", timestamp, message)?;
    }

    Ok(())
}

// Usage Examples
fn main() -> std::io::Result<()> {
    println!("=== Web Rust Logging Examples ===\n");

    let log_file = "application.log";

    // 1. Basic logging
    println!("--- 1. Basic Logging ---");
    log_to_file(log_file, "Application started")?;
    log_with_timestamp(log_file, "INFO", "System initialized")?;

    // 2. Log levels
    println!("
--- 2. Log Levels ---");
    log_debug(log_file, "Debug information")?;
    log_info(log_file, "Application running")?;
    log_warning(log_file, "High memory usage")?;
    log_error(log_file, "Connection failed")?;

    // 3. Structured logging
    println!("
--- 3. Structured Logging ---");
    let entry = LogEntry::new("INFO", "User logged in").with_module("Auth");
    write_structured_log(log_file, &entry)?;

    // 4. Multi-logger
    println!("
--- 4. Multi-Logger ---");
    let logger = MultiLogger::new("multi.log", true);
    logger.info("Multi-logger initialized")?;
    logger.warning("This goes to console and file")?;
    logger.error("Error occurred")?;

    // 5. Level filtering
    println!("
--- 5. Level Filtering ---");
    let level_logger = LevelLogger::new("filtered.log", "WARNING");
    level_logger.log("DEBUG", "This won't be logged")?;
    level_logger.log("WARNING", "This will be logged")?;
    level_logger.log("ERROR", "This will be logged")?;

    // 6. Performance logging
    println!("
--- 6. Performance Logging ---");
    let result = measure_and_log(log_file, "test_operation", || {
        std::thread::sleep(std::time::Duration::from_millis(100));
        42
    });
    println!("Result: {}", result);

    // 7. Error logging
    println!("
--- 7. Error Logging ---");
    log_error_with_context(log_file, "File not found", "load_config")?;
    log_warning_details(log_file, "Slow query", "took 5 seconds")?;

    // 8. Batch logging
    println!("
--- 8. Batch Logging ---");
    let messages = vec![
        "Message 1",
        "Message 2",
        "Message 3",
    ];
    log_batch(log_file, &messages)?;

    // 9. Rotating logger
    println!("
--- 9. Rotating Logger ---");
    let mut rotating_logger = RotatingLogger::new("rotating", 1024);
    for i in 0..10 {
        rotating_logger.log(&format!("Log entry {}", i))?;
    }

    println!("
=== All Logging Examples Completed ===");
    println!("Check {} for log output", log_file);
    Ok(())
}
CoderustSimple

Parameter Validation

Validate function parameters with custom rules and error messages

Difficulty

5/10

Estimated time

20 min

Tags

rust, web, error handling

Prerequisites

Basic Rust

rust
// Web Rust Parameter Validation Examples
// Function parameter validation with custom rules

use std::fmt;

// 1. Validation Error Types

/// Validation error
#[derive(Debug, Clone, PartialEq)]
enum ValidationError {
    TooShort(String, usize),
    TooLong(String, usize),
    InvalidFormat(String),
    OutOfRange(String, String),
    Required(String),
    Custom(String),
}

impl fmt::Display for ValidationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ValidationError::TooShort(field, min) => {
                write!(f, "{} must be at least {} characters", field, min)
            },
            ValidationError::TooLong(field, max) => {
                write!(f, "{} must be at most {} characters", field, max)
            },
            ValidationError::InvalidFormat(field) => {
                write!(f, "{} has invalid format", field)
            },
            ValidationError::OutOfRange(field, range) => {
                write!(f, "{} must be in range {}", field, range)
            },
            ValidationError::Required(field) => {
                write!(f, "{} is required", field)
            },
            ValidationError::Custom(msg) => {
                write!(f, "{}", msg)
            },
        }
    }
}

impl std::error::Error for ValidationError {}

// 2. String Validation

/// Validate string length
fn validate_length(value: &str, field: &str, min: usize, max: usize) -> Result<(), ValidationError> {
    if value.is_empty() {
        return Err(ValidationError::Required(field.to_string()));
    }
    if value.len() < min {
        return Err(ValidationError::TooShort(field.to_string(), min));
    }
    if value.len() > max {
        return Err(ValidationError::TooLong(field.to_string(), max));
    }
    Ok(())
}

/// Validate email format
fn validate_email(email: &str) -> Result<(), ValidationError> {
    if email.is_empty() {
        return Err(ValidationError::Required("Email".to_string()));
    }

    // Basic email validation
    if !email.contains('@') || !email.contains('.') {
        return Err(ValidationError::InvalidFormat("Email".to_string()));
    }

    let parts: Vec<&str> = email.split('@').collect();
    if parts.len() != 2 {
        return Err(ValidationError::InvalidFormat("Email".to_string()));
    }

    let (local, domain) = (parts[0], parts[1]);
    if local.is_empty() || domain.is_empty() || !domain.contains('.') {
        return Err(ValidationError::InvalidFormat("Email".to_string()));
    }

    Ok(())
}

/// Validate URL format
fn validate_url(url: &str) -> Result<(), ValidationError> {
    if url.is_empty() {
        return Err(ValidationError::Required("URL".to_string()));
    }

    if !url.starts_with("http://") && !url.starts_with("https://") {
        return Err(ValidationError::InvalidFormat("URL".to_string()));
    }

    Ok(())
}

/// Validate username
fn validate_username(username: &str) -> Result<(), ValidationError> {
    validate_length(username, "Username", 3, 20)?;

    // Must be alphanumeric with underscores
    if !username.chars().all(|c| c.is_alphanumeric() || c == '_') {
        return Err(ValidationError::InvalidFormat("Username".to_string()));
    }

    Ok(())
}

/// Validate password
fn validate_password(password: &str) -> Result<(), ValidationError> {
    validate_length(password, "Password", 8, 128)?;

    let has_upper = password.chars().any(|c| c.is_uppercase());
    let has_lower = password.chars().any(|c| c.is_lowercase());
    let has_digit = password.chars().any(|c| c.is_ascii_digit());

    if !has_upper {
        return Err(ValidationError::Custom(
            "Password must contain at least one uppercase letter".to_string()
        ));
    }
    if !has_lower {
        return Err(ValidationError::Custom(
            "Password must contain at least one lowercase letter".to_string()
        ));
    }
    if !has_digit {
        return Err(ValidationError::Custom(
            "Password must contain at least one digit".to_string()
        ));
    }

    Ok(())
}

// 3. Numeric Validation

/// Validate number in range
fn validate_range<T: PartialOrd>(value: T, field: &str, min: T, max: T) -> Result<(), ValidationError> {
    if value < min || value > max {
        return Err(ValidationError::OutOfRange(
            field.to_string(),
            format!("{:?} to {:?}", min, max)
        ));
    }
    Ok(())
}

/// Validate positive number
fn validate_positive<T: PartialOrd + Default>(value: T, field: &str) -> Result<(), ValidationError> {
    if value <= T::default() {
        return Err(ValidationError::Custom(
            format!("{} must be positive", field)
        ));
    }
    Ok(())
}

/// Validate non-negative number
fn validate_non_negative<T: PartialOrd + Default>(value: T, field: &str) -> Result<(), ValidationError> {
    if value < T::default() {
        return Err(ValidationError::Custom(
            format!("{} must be non-negative", field)
        ));
    }
    Ok(())
}

// 4. Collection Validation

/// Validate collection not empty
fn validate_not_empty<T>(collection: &[T], field: &str) -> Result<(), ValidationError> {
    if collection.is_empty() {
        return Err(ValidationError::Custom(
            format!("{} must not be empty", field)
        ));
    }
    Ok(())
}

/// Validate collection size
fn validate_collection_size<T>(collection: &[T], field: &str, min: usize, max: usize) -> Result<(), ValidationError> {
    if collection.len() < min {
        return Err(ValidationError::Custom(
            format!("{} must have at least {} items", field, min)
        ));
    }
    if collection.len() > max {
        return Err(ValidationError::Custom(
            format!("{} must have at most {} items", field, max)
        ));
    }
    Ok(())
}

/// Validate all unique
fn validate_all_unique<T: std::hash::Hash + Eq + std::fmt::Debug>(collection: &[T], field: &str) -> Result<(), ValidationError> {
    use std::collections::HashSet;
    let unique: HashSet<_> = collection.iter().collect();
    if unique.len() != collection.len() {
        return Err(ValidationError::Custom(
            format!("{} must contain only unique items", field)
        ));
    }
    Ok(())
}

// 5. Date/Time Validation

/// Validate age range
fn validate_age(age: u32) -> Result<(), ValidationError> {
    if age < 0 {
        return Err(ValidationError::Custom("Age cannot be negative".to_string()));
    }
    if age > 150 {
        return Err(ValidationError::Custom("Age cannot exceed 150".to_string()));
    }
    Ok(())
}

/// Validate year range
fn validate_year(year: i32) -> Result<(), ValidationError> {
    validate_range(year, "Year", 1900, 2100)
}

// 6. Custom Validation Rules

/// Validation rule type
type ValidationRule<T> = Box<dyn Fn(&T) -> Result<(), ValidationError>>;

/// Apply multiple validation rules
fn validate_with_rules<T>(value: &T, rules: &[ValidationRule<T>]) -> Result<(), ValidationError> {
    for rule in rules {
        rule(value)?;
    }
    Ok(())
}

/// Create length rule
fn length_rule(field: &'static str, min: usize, max: usize) -> ValidationRule<String> {
    Box::new(move |value: &String| {
        validate_length(value, field, min, max)
    })
}

/// Create range rule
fn range_rule<T: PartialOrd + Copy>(field: &'static str, min: T, max: T) -> ValidationRule<T> {
    Box::new(move |value: &T| {
        validate_range(*value, field, min, max)
    })
}

// 7. Composite Validation

/// User data validation
#[derive(Debug)]
struct User {
    username: String,
    email: String,
    age: u32,
}

impl User {
    fn validate(&self) -> Result<(), Vec<ValidationError>> {
        let mut errors = Vec::new();

        if let Err(e) = validate_username(&self.username) {
            errors.push(e);
        }

        if let Err(e) = validate_email(&self.email) {
            errors.push(e);
        }

        if let Err(e) = validate_age(self.age) {
            errors.push(e);
        }

        if errors.is_empty() {
            Ok(())
        } else {
            Err(errors)
        }
    }
}

/// Product validation
#[derive(Debug)]
struct Product {
    name: String,
    price: f64,
    quantity: u32,
}

impl Product {
    fn validate(&self) -> Result<(), Vec<ValidationError>> {
        let mut errors = Vec::new();

        validate_length(&self.name, "Name", 1, 100)
            .map_err(|e| errors.push(e)).ok();

        validate_range(self.price, "Price", 0.0, 1000000.0)
            .map_err(|e| errors.push(e)).ok();

        validate_non_negative(self.quantity, "Quantity")
            .map_err(|e| errors.push(e)).ok();

        if errors.is_empty() {
            Ok(())
        } else {
            Err(errors)
        }
    }
}

// 8. Conditional Validation

/// Validate with condition
fn validate_if(condition: bool, validation: Result<(), ValidationError>) -> Result<(), ValidationError> {
    if condition {
        validation
    } else {
        Ok(())
    }
}

/// Validate required if
fn validate_required_if(value: &str, condition: bool, field: &str) -> Result<(), ValidationError> {
    validate_if(condition && value.is_empty(), Err(ValidationError::Required(field.to_string())))
}

// 9. Sanitization

/// Trim and validate
fn validate_trimmed(value: &str, field: &str, min: usize, max: usize) -> Result<(), ValidationError> {
    let trimmed = value.trim();
    validate_length(trimmed, field, min, max)
}

/// Sanitize email
fn sanitize_email(email: &str) -> String {
    email.trim().to_lowercase()
}

// 10. Validation Builder

/// Simple validation builder
struct Validator<'a, T> {
    value: &'a T,
    errors: Vec<ValidationError>,
}

impl<'a, T> Validator<'a, T> {
    fn new(value: &'a T) -> Self {
        Validator {
            value,
            errors: Vec::new(),
        }
    }

    fn add_rule<F>(mut self, rule: F) -> Self
    where
        F: FnOnce(&T) -> Result<(), ValidationError>,
    {
        if let Err(e) = rule(self.value) {
            self.errors.push(e);
        }
        self
    }

    fn validate(self) -> Result<(), Vec<ValidationError>> {
        if self.errors.is_empty() {
            Ok(())
        } else {
            Err(self.errors)
        }
    }
}

// Usage Examples
fn main() {
    println!("=== Web Rust Parameter Validation Examples ===\n");

    // 1. String validation
    println!("--- 1. String Validation ---");
    match validate_username("user123") {
        Ok(_) => println!("'user123' is valid"),
        Err(e) => println!("Error: {}", e),
    }
    match validate_username("ab") {
        Ok(_) => println!("'ab' is valid"),
        Err(e) => println!("Error: {}", e),
    }

    // 2. Email validation
    println!("
--- 2. Email Validation ---");
    match validate_email("user@example.com") {
        Ok(_) => println!("'user@example.com' is valid"),
        Err(e) => println!("Error: {}", e),
    }
    match validate_email("invalid-email") {
        Ok(_) => println!("'invalid-email' is valid"),
        Err(e) => println!("Error: {}", e),
    }

    // 3. Password validation
    println!("
--- 3. Password Validation ---");
    match validate_password("SecurePass123") {
        Ok(_) => println!("Password is valid"),
        Err(e) => println!("Error: {}", e),
    }
    match validate_password("weak") {
        Ok(_) => println!("Password is valid"),
        Err(e) => println!("Error: {}", e),
    }

    // 4. Numeric validation
    println!("
--- 4. Numeric Validation ---");
    match validate_range(50, "Age", 0, 120) {
        Ok(_) => println!("Age 50 is valid"),
        Err(e) => println!("Error: {}", e),
    }
    match validate_range(150, "Age", 0, 120) {
        Ok(_) => println!("Age 150 is valid"),
        Err(e) => println!("Error: {}", e),
    }

    // 5. Collection validation
    println!("
--- 5. Collection Validation ---");
    let items = vec![1, 2, 3, 4, 5];
    match validate_collection_size(&items, "Items", 1, 10) {
        Ok(_) => println!("Collection size is valid"),
        Err(e) => println!("Error: {}", e),
    }

    let empty: Vec<i32> = vec![];
    match validate_not_empty(&empty, "Items") {
        Ok(_) => println!("Collection is valid"),
        Err(e) => println!("Error: {}", e),
    }

    // 6. User validation
    println!("
--- 6. User Validation ---");
    let user = User {
        username: "john_doe".to_string(),
        email: "john@example.com".to_string(),
        age: 25,
    };
    match user.validate() {
        Ok(_) => println!("User is valid: {:?}", user),
        Err(errors) => {
            println!("User validation failed:");
            for e in errors {
                println!("  - {}", e);
            }
        },
    }

    // 7. Product validation
    println!("
--- 7. Product Validation ---");
    let product = Product {
        name: "Laptop".to_string(),
        price: 999.99,
        quantity: 10,
    };
    match product.validate() {
        Ok(_) => println!("Product is valid: {:?}", product),
        Err(errors) => {
            println!("Product validation failed:");
            for e in errors {
                println!("  - {}", e);
            }
        },
    }

    // 8. Validation builder
    println!("
--- 8. Validation Builder ---");
    let result = Validator::new(&"test value")
        .add_rule(|v| validate_length(v, "Field", 3, 20))
        .add_rule(|v| if v.chars().all(|c| c.is_alphanumeric()) {
            Ok(())
        } else {
            Err(ValidationError::InvalidFormat("Field".to_string()))
        })
        .validate();

    match result {
        Ok(_) => println!("Builder validation passed"),
        Err(errors) => {
            println!("Builder validation failed:");
            for e in errors {
                println!("  - {}", e);
            }
        },
    }

    // 9. URL validation
    println!("
--- 9. URL Validation ---");
    match validate_url("https://example.com") {
        Ok(_) => println!("URL is valid"),
        Err(e) => println!("Error: {}", e),
    }

    println!("
=== All Parameter Validation Examples Completed ===");
}

Tools

Tools frequently paired with this sample

Related

Related sample collections

Related

Related workflows

Hub

Authorized Webhook Capture and Endpoint Trust Checks

Capture and replay controlled webhook requests, inspect delivery evidence, and check the receiver HTTPS certificate without treating a valid certificate as proof of business trust.

Hub

Observability Debugging from Logs, Traces, Webhooks, and JSON Payloads

Parse logs, decode traces, inspect webhook/API evidence, explore JSON payloads, and extract recurring patterns before writing an incident-ready debugging note.

Hub

Infer JSON Schema from Samples and Spreadsheets

Derive a reviewable JSON Schema draft from representative JSON samples or XLSX rows, then inspect types, requiredness, nulls, and outliers before treating it as a contract.

Hub

Population Ecology, Biodiversity, and Food Web Calculators

Use educational ecology models to explore population growth, carrying capacity, species interactions, sampled biodiversity, and trophic energy transfer.

Home
Tools3212
Workbench
Samples593
Visualizations471
Viewers103
Hubs239
Tags333
Images, Audio & Video657

Image, audio, and video processing, conversion, and optimization tools

Math, Date & Finance647

Calculators, numerics, date logic, statistics, and finance tools

Design & Color298

Color, layout, graphics, visual styling, and design helper tools

Text & Writing209

Writing, cleanup, formatting, extraction, and text analysis tools

Developer & Web193

Developer utilities, networking, web debugging, and automation helpers

Conversion & Encoding175

Format, file, archive, unit, and encoding conversion tools

Lead Generation Quiz Launch and Contact Handoff
Memorial Drafts: Family Review and Print Handoff
Private Habit Records: Backup, Restore and Sharing Review
Article to X and LinkedIn Drafts: Fact Review and Handoff
Markdown Interactive Deck Review and Offline Handoff

© 2026 Elysia Tools. All rights reserved.

DocsPricingAboutTerms of ServicePrivacy PolicyCookiesContact

Media

AAC to OGG Converter

Convert AAC audio files to OGG Vorbis format with quality and channel controls

Media

Batch Audio Converter

Convert multiple audio files between different formats like MP3, WAV, FLAC, AAC, OGG, Opus with quality settings and batch processing

Media

Audio Codec Swap

Change the codec of an audio file within a chosen output format

Media

Audio Format Converter

Convert audio files between different formats like MP3, WAV, FLAC, AAC, OGG with quality settings and volume adjustment

Media

Audio Ringtone Maker

Create ringtones with trimming and fade in/out

Media

Audio Set CBR

Re-encode audio using Constant Bitrate (CBR)

Media

Batch WAV Audio Converter

Convert multiple WAV files to OGG, AAC, M4A, and OPUS formats with quality settings, bitrate control, and batch processing

Media

FLAC to OGG Converter

Convert FLAC audio to OGG Vorbis with bitrate, resampling, and channel options

Objective-C

macOS Error Handling Objective-C Samples

macOS Objective-C error handling examples including exception handling, logging, and parameter validation

Swift

macOS Error Handling Swift Samples

macOS Swift error handling examples including exception catching, logging, and parameter validation

Go

Web Error Handling Go Samples

Web Go error handling examples including exception catching, logging, and parameter validation

Python

Web Error Handling Python Samples

Web Python error handling examples including exception catching, logging, and parameter validation

TypeScript

Web Error Handling TypeScript Samples

Web TypeScript error handling examples including exception catching, logging, and parameter validation

C#

Windows Error Handling - C# Samples

Comprehensive C# error handling examples for Windows platform including exception handling, logging, and parameter validation