🎯 Exemplos recomendados
Balanced sample collections from various categories for you to explore
Exemplos de Tratamento de Erros Web Rust
Exemplos de tratamento de erros Web Rust incluindo captura de exceções, registro e validação de parâmetros
💻 Registro de Logs rust
🟢 simple
⭐⭐⭐
Escrever logs em arquivos e console com diferentes níveis
⏱️ 20 min
🏷️ rust, web, error handling
Prerequisites:
Basic Rust, chrono crate
// 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(¤t_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(())
}
💻 Validação de Parâmetros rust
🟢 simple
⭐⭐⭐
Validar parâmetros de função com regras personalizadas e mensagens de erro
⏱️ 20 min
🏷️ rust, web, error handling
Prerequisites:
Basic 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 + std::fmt::Debug>(value: T, field: &str) -> Result<(), ValidationError> {
if value <= T::from(0).unwrap() {
return Err(ValidationError::Custom(
format!("{:?} must be positive", field)
));
}
Ok(())
}
/// Validate non-negative number
fn validate_non_negative<T: PartialOrd>(value: T, field: &str) -> Result<(), ValidationError> {
if value < T::from(0).unwrap() {
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("[email protected]") {
Ok(_) => println!("'[email protected]' 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: "[email protected]".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 ===");
}
💻 Captura de Exceções rust
🟡 intermediate
⭐⭐⭐
Tratar erros usando Result, Option e tipos de erro personalizados
⏱️ 25 min
🏷️ rust, web, error handling
Prerequisites:
Intermediate 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(())
}