// rust/01-basic-error-handling.rs/*Basic error handling patterns with Result and Option*/usestd::fs::File;usestd::io::{self,Read};usestd::num::ParseIntError;usestd::str::FromStr;/// Demonstrates basic Result patterns.pubstructDataProcessor{data:Vec<String>,}implDataProcessor{pubfnnew()->Self{Self{data:Vec::new()}}/// Processes data with error handling.pubfnprocess_data(&mutself,input:&str)->Result<usize,String>{ifinput.is_empty(){returnErr("Input cannot be empty".to_string());}letprocessed=input.to_uppercase();self.data.push(processed);Ok(self.data.len())}/// Processes data with Option return.pubfnget_data(&self,index:usize)->Option<&String>{self.data.get(index)}/// Processes data with Result and error propagation.pubfnprocess_file(&self,filename:&str)->Result<String,io::Error>{letmutfile=File::open(filename)?;letmutcontents=String::new();file.read_to_string(&mutcontents)?;Ok(contents)}/// Processes data with custom error handling.pubfnprocess_number(&self,input:&str)->Result<i32,ParseIntError>{input.parse::<i32>()}/// Processes data with error mapping.pubfnprocess_number_with_context(&self,input:&str)->Result<i32,String>{input.parse::<i32>().map_err(|e|format!("Failed to parse '{}' as integer: {}",input,e))}}/// Demonstrates Option patterns.pubstructOptionDemo{data:Vec<Option<String>>,}implOptionDemo{pubfnnew()->Self{Self{data:Vec::new()}}/// Adds data with Option handling.pubfnadd_data(&mutself,data:Option<String>){self.data.push(data);}/// Gets data with Option handling.pubfnget_data(&self,index:usize)->Option<&String>{self.data.get(index)?.as_ref()}/// Processes data with Option chaining.pubfnprocess_data(&self,index:usize)->Option<String>{self.data.get(index)?.as_ref().map(|s|s.to_uppercase())}/// Processes data with Option and default values.pubfnget_data_or_default(&self,index:usize)->String{self.data.get(index).and_then(|opt|opt.as_ref()).map(|s|s.clone()).unwrap_or_else(||"default".to_string())}}/// Demonstrates Result patterns with error chaining.pubstructResultDemo{data:Vec<Result<String,String>>,}implResultDemo{pubfnnew()->Self{Self{data:Vec::new()}}/// Adds data with Result handling.pubfnadd_data(&mutself,data:Result<String,String>){self.data.push(data);}/// Gets data with Result handling.pubfnget_data(&self,index:usize)->Result<&String,&String>{matchself.data.get(index){Some(Ok(data))=>Ok(data),Some(Err(error))=>Err(error),None=>Err(&"Index out of bounds".to_string()),}}/// Processes data with Result chaining.pubfnprocess_data(&self,index:usize)->Result<String,String>{letdata=self.data.get(index).ok_or("Index out of bounds")?;letvalue=data.as_ref().map_err(|e|format!("Error in data: {}",e))?;Ok(value.to_uppercase())}/// Processes data with Result and error mapping.pubfnprocess_data_with_context(&self,index:usize)->Result<String,String>{letdata=self.data.get(index).ok_or_else(||format!("Index {} out of bounds",index))?;letvalue=data.as_ref().map_err(|e|format!("Error in data at index {}: {}",index,e))?;Ok(value.to_uppercase())}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_data_processor(){letmutprocessor=DataProcessor::new();letresult=processor.process_data("hello");assert!(result.is_ok());assert_eq!(result.unwrap(),1);letresult=processor.process_data("");assert!(result.is_err());assert_eq!(result.unwrap_err(),"Input cannot be empty");}#[test]fntest_option_demo(){letmutdemo=OptionDemo::new();demo.add_data(Some("hello".to_string()));demo.add_data(None);assert_eq!(demo.get_data(0),Some(&"hello".to_string()));assert_eq!(demo.get_data(1),None);assert_eq!(demo.process_data(0),Some("HELLO".to_string()));assert_eq!(demo.process_data(1),None);assert_eq!(demo.get_data_or_default(0),"hello");assert_eq!(demo.get_data_or_default(1),"default");}#[test]fntest_result_demo(){letmutdemo=ResultDemo::new();demo.add_data(Ok("hello".to_string()));demo.add_data(Err("error".to_string()));assert_eq!(demo.get_data(0),Ok(&"hello".to_string()));assert_eq!(demo.get_data(1),Err(&"error".to_string()));assert_eq!(demo.process_data(0),Ok("HELLO".to_string()));assert_eq!(demo.process_data(1),Err("Error in data: error".to_string()));}}
// rust/02-custom-error-types.rs/*Custom error types and error handling patterns*/usestd::fmt;usestd::io;usestd::num::ParseIntError;usethiserror::Error;/// Custom error type for data processing.#[derive(Error, Debug)]pubenumDataProcessingError{#[error("Input validation failed: {0}")]Validation(String),#[error("Processing failed: {0}")]Processing(String),#[error("IO error: {0}")]Io(#[from]io::Error),#[error("Parse error: {0}")]Parse(#[from]ParseIntError),#[error("Unknown error: {0}")]Unknown(String),}/// Custom error type for business logic.#[derive(Error, Debug)]pubenumBusinessError{#[error("User not found: {user_id}")]UserNotFound{user_id:u64},#[error("Insufficient permissions for user: {user_id}")]InsufficientPermissions{user_id:u64},#[error("Resource already exists: {resource_name}")]ResourceExists{resource_name:String},#[error("Business rule violation: {rule}")]BusinessRuleViolation{rule:String},#[error("External service error: {service} - {message}")]ExternalService{service:String,message:String},}/// Custom error type for API operations.#[derive(Error, Debug)]pubenumApiError{#[error("Bad request: {0}")]BadRequest(String),#[error("Unauthorized: {0}")]Unauthorized(String),#[error("Forbidden: {0}")]Forbidden(String),#[error("Not found: {0}")]NotFound(String),#[error("Internal server error: {0}")]InternalServerError(String),#[error("Service unavailable: {0}")]ServiceUnavailable(String),}implApiError{/// Get HTTP status code for the error.pubfnstatus_code(&self)->u16{matchself{ApiError::BadRequest(_)=>400,ApiError::Unauthorized(_)=>401,ApiError::Forbidden(_)=>403,ApiError::NotFound(_)=>404,ApiError::InternalServerError(_)=>500,ApiError::ServiceUnavailable(_)=>503,}}}/// Demonstrates custom error handling.pubstructCustomErrorDemo{data:Vec<String>,}implCustomErrorDemo{pubfnnew()->Self{Self{data:Vec::new()}}/// Processes data with custom error handling.pubfnprocess_data(&mutself,input:&str)->Result<usize,DataProcessingError>{ifinput.is_empty(){returnErr(DataProcessingError::Validation("Input cannot be empty".to_string()));}ifinput.len()>100{returnErr(DataProcessingError::Validation("Input too long".to_string()));}letprocessed=input.to_uppercase();self.data.push(processed);Ok(self.data.len())}/// Processes data with business error handling.pubfnprocess_business_data(&self,user_id:u64,data:&str)->Result<String,BusinessError>{ifuser_id==0{returnErr(BusinessError::UserNotFound{user_id});}ifuser_id<1000{returnErr(BusinessError::InsufficientPermissions{user_id});}ifdata.is_empty(){returnErr(BusinessError::BusinessRuleViolation{rule:"Data cannot be empty".to_string(),});}Ok(data.to_uppercase())}/// Processes data with API error handling.pubfnprocess_api_data(&self,data:&str)->Result<String,ApiError>{ifdata.is_empty(){returnErr(ApiError::BadRequest("Data cannot be empty".to_string()));}ifdata.len()>1000{returnErr(ApiError::BadRequest("Data too long".to_string()));}ifdata.contains("error"){returnErr(ApiError::InternalServerError("Data contains error".to_string()));}Ok(data.to_uppercase())}/// Processes data with error chaining.pubfnprocess_data_with_chain(&mutself,input:&str)->Result<usize,DataProcessingError>{letprocessed=self.process_data(input)?;Ok(processed)}/// Processes data with error mapping.pubfnprocess_data_with_mapping(&mutself,input:&str)->Result<usize,String>{self.process_data(input).map_err(|e|format!("Failed to process data: {}",e))}}/// Demonstrates error recovery patterns.pubstructErrorRecoveryDemo{data:Vec<String>,retry_count:u32,max_retries:u32,}implErrorRecoveryDemo{pubfnnew(max_retries:u32)->Self{Self{data:Vec::new(),retry_count:0,max_retries,}}/// Processes data with retry logic.pubfnprocess_data_with_retry(&mutself,input:&str)->Result<usize,String>{self.retry_count=0;loop{matchself.process_data_internal(input){Ok(result)=>returnOk(result),Err(error)=>{self.retry_count+=1;ifself.retry_count>=self.max_retries{returnErr(format!("Max retries exceeded: {}",error));}}}}}/// Internal processing method.fnprocess_data_internal(&mutself,input:&str)->Result<usize,String>{ifinput.is_empty(){returnErr("Input cannot be empty".to_string());}ifinput.len()>100{returnErr("Input too long".to_string());}letprocessed=input.to_uppercase();self.data.push(processed);Ok(self.data.len())}/// Processes data with fallback.pubfnprocess_data_with_fallback(&mutself,input:&str)->Result<usize,String>{matchself.process_data_internal(input){Ok(result)=>Ok(result),Err(_)=>{// Fallback to default processingself.data.push("default".to_string());Ok(self.data.len())}}}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_custom_error_demo(){letmutdemo=CustomErrorDemo::new();letresult=demo.process_data("hello");assert!(result.is_ok());assert_eq!(result.unwrap(),1);letresult=demo.process_data("");assert!(result.is_err());matchresult.unwrap_err(){DataProcessingError::Validation(msg)=>assert_eq!(msg,"Input cannot be empty"),_=>panic!("Expected Validation error"),}}#[test]fntest_business_error_handling(){letdemo=CustomErrorDemo::new();letresult=demo.process_business_data(1001,"hello");assert!(result.is_ok());assert_eq!(result.unwrap(),"HELLO");letresult=demo.process_business_data(0,"hello");assert!(result.is_err());matchresult.unwrap_err(){BusinessError::UserNotFound{user_id}=>assert_eq!(user_id,0),_=>panic!("Expected UserNotFound error"),}}#[test]fntest_api_error_handling(){letdemo=CustomErrorDemo::new();letresult=demo.process_api_data("hello");assert!(result.is_ok());assert_eq!(result.unwrap(),"HELLO");letresult=demo.process_api_data("");assert!(result.is_err());matchresult.unwrap_err(){ApiError::BadRequest(msg)=>assert_eq!(msg,"Data cannot be empty"),_=>panic!("Expected BadRequest error"),}}#[test]fntest_error_recovery(){letmutdemo=ErrorRecoveryDemo::new(3);letresult=demo.process_data_with_retry("hello");assert!(result.is_ok());assert_eq!(result.unwrap(),1);letresult=demo.process_data_with_fallback("");assert!(result.is_ok());assert_eq!(result.unwrap(),2);}}
// rust/03-error-propagation.rs/*Error propagation patterns and best practices*/usestd::fs::File;usestd::io::{self,Read,Write};usestd::path::Path;useanyhow::{Context,ResultasAnyhowResult};usethiserror::Error;/// Custom error type for file operations.#[derive(Error, Debug)]pubenumFileError{#[error("File not found: {path}")]NotFound{path:String},#[error("Permission denied: {path}")]PermissionDenied{path:String},#[error("IO error: {0}")]Io(#[from]io::Error),#[error("Invalid file format: {0}")]InvalidFormat(String),}/// Demonstrates error propagation with ? operator.pubstructErrorPropagationDemo{data:Vec<String>,}implErrorPropagationDemo{pubfnnew()->Self{Self{data:Vec::new()}}/// Processes file with error propagation.pubfnprocess_file(&mutself,filename:&str)->Result<usize,FileError>{letcontent=self.read_file(filename)?;letprocessed=self.process_content(&content)?;self.data.push(processed);Ok(self.data.len())}/// Reads file with error propagation.fnread_file(&self,filename:&str)->Result<String,FileError>{letpath=Path::new(filename);if!path.exists(){returnErr(FileError::NotFound{path:filename.to_string(),});}letmutfile=File::open(filename)?;letmutcontent=String::new();file.read_to_string(&mutcontent)?;Ok(content)}/// Processes content with error propagation.fnprocess_content(&self,content:&str)->Result<String,FileError>{ifcontent.is_empty(){returnErr(FileError::InvalidFormat("Content is empty".to_string()));}ifcontent.len()>10000{returnErr(FileError::InvalidFormat("Content too long".to_string()));}Ok(content.to_uppercase())}/// Processes multiple files with error propagation.pubfnprocess_multiple_files(&mutself,filenames:&[&str])->Result<Vec<usize>,FileError>{letmutresults=Vec::new();forfilenameinfilenames{letresult=self.process_file(filename)?;results.push(result);}Ok(results)}}/// Demonstrates error propagation with anyhow.pubstructAnyhowErrorDemo{data:Vec<String>,}implAnyhowErrorDemo{pubfnnew()->Self{Self{data:Vec::new()}}/// Processes data with anyhow error handling.pubfnprocess_data(&mutself,input:&str)->AnyhowResult<usize>{letprocessed=self.validate_input(input).context("Failed to validate input")?;letresult=self.process_content(&processed).context("Failed to process content")?;self.data.push(result);Ok(self.data.len())}/// Validates input with context.fnvalidate_input(&self,input:&str)->AnyhowResult<String>{ifinput.is_empty(){anyhow::bail!("Input cannot be empty");}ifinput.len()>100{anyhow::bail!("Input too long: {} characters",input.len());}Ok(input.to_string())}/// Processes content with context.fnprocess_content(&self,content:&str)->AnyhowResult<String>{ifcontent.contains("error"){anyhow::bail!("Content contains error keyword");}Ok(content.to_uppercase())}/// Processes data with error chaining.pubfnprocess_data_with_chain(&mutself,input:&str)->AnyhowResult<usize>{letprocessed=self.process_data(input)?;Ok(processed)}}/// Demonstrates error propagation with custom error types.pubstructCustomErrorPropagationDemo{data:Vec<String>,}implCustomErrorPropagationDemo{pubfnnew()->Self{Self{data:Vec::new()}}/// Processes data with custom error propagation.pubfnprocess_data(&mutself,input:&str)->Result<usize,FileError>{letvalidated=self.validate_input(input)?;letprocessed=self.process_content(&validated)?;self.data.push(processed);Ok(self.data.len())}/// Validates input with custom error.fnvalidate_input(&self,input:&str)->Result<String,FileError>{ifinput.is_empty(){returnErr(FileError::InvalidFormat("Input cannot be empty".to_string()));}ifinput.len()>100{returnErr(FileError::InvalidFormat("Input too long".to_string()));}Ok(input.to_string())}/// Processes content with custom error.fnprocess_content(&self,content:&str)->Result<String,FileError>{ifcontent.contains("error"){returnErr(FileError::InvalidFormat("Content contains error keyword".to_string()));}Ok(content.to_uppercase())}/// Processes data with error mapping.pubfnprocess_data_with_mapping(&mutself,input:&str)->Result<usize,String>{self.process_data(input).map_err(|e|format!("Failed to process data: {}",e))}}/// Demonstrates error propagation with async code.pubstructAsyncErrorPropagationDemo{data:Vec<String>,}implAsyncErrorPropagationDemo{pubfnnew()->Self{Self{data:Vec::new()}}/// Processes data asynchronously with error propagation.pubasyncfnprocess_data_async(&mutself,input:&str)->Result<usize,FileError>{letvalidated=self.validate_input_async(input).await?;letprocessed=self.process_content_async(&validated).await?;self.data.push(processed);Ok(self.data.len())}/// Validates input asynchronously.asyncfnvalidate_input_async(&self,input:&str)->Result<String,FileError>{// Simulate async worktokio::time::sleep(tokio::time::Duration::from_millis(100)).await;ifinput.is_empty(){returnErr(FileError::InvalidFormat("Input cannot be empty".to_string()));}ifinput.len()>100{returnErr(FileError::InvalidFormat("Input too long".to_string()));}Ok(input.to_string())}/// Processes content asynchronously.asyncfnprocess_content_async(&self,content:&str)->Result<String,FileError>{// Simulate async worktokio::time::sleep(tokio::time::Duration::from_millis(100)).await;ifcontent.contains("error"){returnErr(FileError::InvalidFormat("Content contains error keyword".to_string()));}Ok(content.to_uppercase())}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_error_propagation_demo(){letmutdemo=ErrorPropagationDemo::new();// This will fail because the file doesn't existletresult=demo.process_file("nonexistent.txt");assert!(result.is_err());matchresult.unwrap_err(){FileError::NotFound{path}=>assert_eq!(path,"nonexistent.txt"),_=>panic!("Expected NotFound error"),}}#[test]fntest_anyhow_error_demo(){letmutdemo=AnyhowErrorDemo::new();letresult=demo.process_data("hello");assert!(result.is_ok());assert_eq!(result.unwrap(),1);letresult=demo.process_data("");assert!(result.is_err());assert!(result.unwrap_err().to_string().contains("Input cannot be empty"));}#[test]fntest_custom_error_propagation_demo(){letmutdemo=CustomErrorPropagationDemo::new();letresult=demo.process_data("hello");assert!(result.is_ok());assert_eq!(result.unwrap(),1);letresult=demo.process_data("");assert!(result.is_err());matchresult.unwrap_err(){FileError::InvalidFormat(msg)=>assert_eq!(msg,"Input cannot be empty"),_=>panic!("Expected InvalidFormat error"),}}#[tokio::test]asyncfntest_async_error_propagation_demo(){letmutdemo=AsyncErrorPropagationDemo::new();letresult=demo.process_data_async("hello").await;assert!(result.is_ok());assert_eq!(result.unwrap(),1);letresult=demo.process_data_async("").await;assert!(result.is_err());matchresult.unwrap_err(){FileError::InvalidFormat(msg)=>assert_eq!(msg,"Input cannot be empty"),_=>panic!("Expected InvalidFormat error"),}}}