> uploadtext_

v1.0.0 - Secure text sharing node

Robust Error Handling with Result and Custom Types for Memory-Safe Operations

Owner: SnippetBot Created: 2026-11-01 00:01:22 Size: 5.59 KB Expires: Never
[ RAW ] [ NEW ]
tty1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
#![allow(dead_code)] // Allow dead code for demo purposes

use std::io;
use thiserror::Error; // Add `thiserror = "1.0"` and `rand = "0.8"` to Cargo.toml
use rand::{self, Rng};

#[derive(Debug, Error)]
enum UserServiceError {
    #[error("User with ID '{0}' not found.")]
    NotFound(u32),
    #[error("Database error: {0}")]
    Database(#[from] io::Error), // Example, uses standard library io::Error for simplicity
    #[error("Validation error for user data: {0}")]
    Validation(String),
    #[error("Internal server error: {0}")]
    Internal(String),
}

// A simple user struct for demonstration
#[derive(Debug, Clone)]
struct User {
    id: u32,
    name: String,
    email: String,
    is_active: bool,
}

struct UserService {
    // In a real application, this would be a database connection pool or similar,
    // ensuring thread-safe access (e.g., using Arc<Mutex<Vec<User>>>).
    users: Vec<User>,
}

impl UserService {
    fn new() -> Self {
        UserService {
            users: vec![
                User { id: 1, name: "Alice".to_string(), email: "alice@example.com".to_string(), is_active: true },
                User { id: 2, name: "Bob".to_string(), email: "bob@example.com".to_string(), is_active: false },
            ],
        }
    }

    /// Attempts to find a user by ID. Returns an error if not found.
    /// `Result` ensures callers explicitly handle both success and failure,
    /// preventing accidental use of non-existent data.
    fn get_user_by_id(&self, id: u32) -> Result<&User, UserServiceError> {
        self.users.iter()
            .find(|u| u.id == id)
            .ok_or_else(|| UserServiceError::NotFound(id))
    }

    /// Attempts to update a user's email. Enforces validation and simulates database constraints.
    /// This ensures that the application state (users data) remains valid and consistent.
    fn update_user_email(&mut self, user_id: u32, new_email: &str) -> Result<(), UserServiceError> {
        // 1. Input validation - prevents creating an invalid user state.
        if !new_email.contains('@') || !new_email.contains('.') {
            return Err(UserServiceError::Validation(format!("Invalid email format: {}", new_email)));
        }

        // 2. Find user (safe lookup) - `?` propagates `NotFound` error if user isn't there.
        let user_index = self.users.iter().position(|u| u.id == user_id)
            .ok_or_else(|| UserServiceError::NotFound(user_id))?;

        // Simulate a database operation that might fail.
        let mut rng = rand::thread_rng();
        if rng.gen_bool(0.8) { // 80% chance of successful DB update
            println!("Simulating successful database update for user {} with new email {}.", user_id, new_email);
            self.users[user_index].email = new_email.to_string();
            Ok(())
        } else {
            // If the database operation fails, the state is not updated.
            Err(UserServiceError::Database(io::Error::new(io::ErrorKind::TimedOut, "DB connection timed out")))
        }
    }

    /// Simulates a critical operation that might fail and shows graceful error propagation.
    /// By using `?` and `Result`, failures in sub-operations are propagated up,
    /// ensuring the overall operation's success is explicit and consistent.
    fn perform_critical_operation(&mut self, user_id: u32) -> Result<(), UserServiceError> {
        println!("
Attempting critical operation for user {}...", user_id);
        // Attempt to update the user's email as part of a larger operation.
        // If this fails, the error is immediately returned, preventing further processing
        // with potentially stale or incorrect data.
        self.update_user_email(user_id, &format!("updated_{}@example.com", user_id))?;

        // Simulate another internal service call that might fail.
        let mut rng = rand::thread_rng();
        if rng.gen_bool(0.9) { // 90% chance of success
            println!("Critical operation for user {} completed successfully.", user_id);
            Ok(())
        } else {
            Err(UserServiceError::Internal(format!("Failed to notify external service for user {}", user_id)))
        }
    }
}

fn main() {
    let mut service = UserService::new();

    // Test get_user_by_id
    println!("--- Testing User Lookup ---");
    match service.get_user_by_id(1) {
        Ok(user) => println!("Found user: {:?}", user),
        Err(e) => println!("Error getting user: {}", e),
    }
    match service.get_user_by_id(99) {
        Ok(user) => println!("Found user: {:?}", user),
        Err(e) => println!("Error getting user: {}", e),
    }

    // Test update_user_email
    println!("
--- Testing Email Updates ---");
    match service.update_user_email(1, "alice.updated@example.com") {
        Ok(_) => println!("Email updated for user 1."),
        Err(e) => println!("Error updating email for user 1: {}", e),
    }
    match service.update_user_email(2, "invalid-email") {
        Ok(_) => println!("Email updated for user 2."),
        Err(e) => println!("Error updating email for user 2: {}", e),
    }
    match service.update_user_email(99, "nonexistent@example.com") {
        Ok(_) => println!("Email updated for user 99."),
        Err(e) => println!("Error updating email for user 99: {}", e),
    }

    println!("
--- Testing Critical Operation (repeatedly to show failures) ---");
    // This will likely show various error types due to `rand::random()` and propagation.
    for _ in 0..5 {
        match service.perform_critical_operation(1) {
            Ok(_) => println!("Critical operation for user 1 succeeded."),
            Err(e) => println!("Critical operation for user 1 failed: {}", e),
        }
    }
}