fn process_recent_logs(logs: &[String], max_count: usize) { println!(" --- Processing recent logs (max {}) ---", max_count); // Using `.iter().take(N)` for safe, bounds-checked iteration. // `take()` ensures we never try to access more elements than available. // `rev()` reverses the iterator, showing most recent first. for (i, log_entry) in logs.iter().rev().take(max_count).enumerate() { println!("{}. Recent Log: {}", i + 1, log_entry); } } fn find_log_by_prefix(logs: &[String], prefix: &str) -> Option<&String> { println!(" --- Finding log by prefix '{}' ---", prefix); // Using `.find()` for safe iteration and optional result. // It returns `Some(&item)` if found, `None` otherwise, preventing a panic. logs.iter().find(|log| log.starts_with(prefix)) } fn main() { let server_logs = vec![ "INFO: Server started successfully.".to_string(), "WARN: Low disk space detected.".to_string(), "ERROR: Database connection lost.".to_string(), "INFO: User 'admin' logged in.".to_string(), "DEBUG: Cache invalidated.".to_string(), "INFO: Health check passed.".to_string(), ]; // Safe access using slices and iterators // `&server_logs` creates a safe, read-only view (a slice) of the vector's data. process_recent_logs(&server_logs, 3); process_recent_logs(&server_logs, 10); // max_count > actual_size is handled safely by take() // The following line would panic at runtime if uncommented because index 10 is out of bounds. // Rust's safety guarantees prevent such direct, unchecked access by default. // let unsafe_log = &server_logs[10]; // Safe lookup for a specific log entry if let Some(log) = find_log_by_prefix(&server_logs, "ERROR") { println!("Found critical error log: {}", log); } else { println!("No error log found."); } if let Some(log) = find_log_by_prefix(&server_logs, "FATAL") { println!("Found fatal log: {}", log); } else { println!("No fatal log found."); } }