Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Input Validation

Validate user input with structured error handling.

Username Validation

#![allow(unused)]
fn main() {
use rok_utils::{RokError, Str};

fn validate_username(username: &str) -> Result<String, RokError> {
    let normalized = Str::of(username)
        .trim()
        .lower()
        .value();

    if normalized.is_empty() {
        return Err(RokError::ValidationFailure {
            field: "username".to_string(),
            reason: "Username cannot be empty".to_string(),
        });
    }

    if normalized.len() < 3 {
        return Err(RokError::ValidationFailure {
            field: "username".to_string(),
            reason: "Username must be at least 3 characters".to_string(),
        });
    }

    if normalized.len() > 20 {
        return Err(RokError::ValidationFailure {
            field: "username".to_string(),
            reason: "Username must be at most 20 characters".to_string(),
        });
    }

    Ok(normalized)
}
}

Email Validation

#![allow(unused)]
fn main() {
use rok_utils::{RokError, Str};

fn validate_email(email: &str) -> Result<String, RokError> {
    let trimmed = Str::of(email).trim().value();

    if trimmed.is_empty() {
        return Err(RokError::ValidationFailure {
            field: "email".to_string(),
            reason: "Email cannot be empty".to_string(),
        });
    }

    if !trimmed.contains('@') {
        return Err(RokError::ValidationFailure {
            field: "email".to_string(),
            reason: "Email must contain @".to_string(),
        });
    }

    let parts: Vec<&str> = trimmed.split('@').collect();
    if parts.len() != 2 || parts[0].is_empty() || parts[1].is_empty() {
        return Err(RokError::ValidationFailure {
            field: "email".to_string(),
            reason: "Invalid email format".to_string(),
        });
    }

    Ok(trimmed.to_string())
}
}

Password Validation

#![allow(unused)]
fn main() {
use rok_utils::{RokError, Str};

fn validate_password(password: &str) -> Result<(), RokError> {
    let pwd = Str::of(password);

    if pwd.len() < 8 {
        return Err(RokError::ValidationFailure {
            field: "password".to_string(),
            reason: "Password must be at least 8 characters".to_string(),
        });
    }

    // Check for uppercase
    if !password.chars().any(|c| c.is_uppercase()) {
        return Err(RokError::ValidationFailure {
            field: "password".to_string(),
            reason: "Password must contain at least one uppercase letter".to_string(),
        });
    }

    // Check for lowercase
    if !password.chars().any(|c| c.is_lowercase()) {
        return Err(RokError::ValidationFailure {
            field: "password".to_string(),
            reason: "Password must contain at least one lowercase letter".to_string(),
        });
    }

    // Check for digit
    if !password.chars().any(|c| c.is_ascii_digit()) {
        return Err(RokError::ValidationFailure {
            field: "password".to_string(),
            reason: "Password must contain at least one digit".to_string(),
        });
    }

    Ok(())
}
}

Batch Validation

#![allow(unused)]
fn main() {
use rok_utils::{RokError, Str};

#[derive(Debug)]
struct ValidationResult {
    valid: bool,
    errors: Vec<RokError>,
}

fn validate_registration(
    username: &str,
    email: &str,
    password: &str,
) -> ValidationResult {
    let mut errors = Vec::new();

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

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

    if let Err(e) = validate_password(password) {
        errors.push(e);
    }

    ValidationResult {
        valid: errors.is_empty(),
        errors,
    }
}
}