// rust/01-actix-patterns.rs/*Actix Web patterns and best practices for Rust*/useactix_web::{web,App,HttpServer,HttpResponse,Result,middleware};useserde::{Deserialize,Serialize};usestd::sync::Mutex;/// User data structure.#[derive(Debug, Clone, Serialize, Deserialize)]pubstructUser{pubid:u64,pubname:String,pubemail:String,}/// User service for managing users.pubstructUserService{users:Mutex<Vec<User>>,next_id:Mutex<u64>,}implUserService{pubfnnew()->Self{Self{users:Mutex::new(Vec::new()),next_id:Mutex::new(1),}}pubfncreate_user(&self,name:String,email:String)->Result<User,String>{letmutusers=self.users.lock().unwrap();letmutnext_id=self.next_id.lock().unwrap();letuser=User{id:*next_id,name,email,};*next_id+=1;users.push(user.clone());Ok(user)}pubfnget_user(&self,id:u64)->Result<Option<User>,String>{letusers=self.users.lock().unwrap();Ok(users.iter().find(|u|u.id==id).cloned())}pubfnget_all_users(&self)->Result<Vec<User>,String>{letusers=self.users.lock().unwrap();Ok(users.clone())}pubfnupdate_user(&self,id:u64,name:Option<String>,email:Option<String>)->Result<Option<User>,String>{letmutusers=self.users.lock().unwrap();ifletSome(user)=users.iter_mut().find(|u|u.id==id){ifletSome(name)=name{user.name=name;}ifletSome(email)=email{user.email=email;}Ok(Some(user.clone()))}else{Ok(None)}}pubfndelete_user(&self,id:u64)->Result<bool,String>{letmutusers=self.users.lock().unwrap();letinitial_len=users.len();users.retain(|u|u.id!=id);Ok(users.len()<initial_len)}}/// Request/Response structures.#[derive(Deserialize)]pubstructCreateUserRequest{pubname:String,pubemail:String,}#[derive(Deserialize)]pubstructUpdateUserRequest{pubname:Option<String>,pubemail:Option<String>,}/// Handler functions.pubasyncfncreate_user(data:web::Data<UserService>,req:web::Json<CreateUserRequest>,)->Result<HttpResponse,actix_web::Error>{letuser=data.create_user(req.name.clone(),req.email.clone()).map_err(|e|actix_web::error::ErrorBadRequest(e))?;Ok(HttpResponse::Created().json(user))}pubasyncfnget_user(data:web::Data<UserService>,path:web::Path<u64>,)->Result<HttpResponse,actix_web::Error>{letuser=data.get_user(path.into_inner()).map_err(|e|actix_web::error::ErrorInternalServerError(e))?;matchuser{Some(user)=>Ok(HttpResponse::Ok().json(user)),None=>Ok(HttpResponse::NotFound().json("User not found")),}}pubasyncfnget_all_users(data:web::Data<UserService>,)->Result<HttpResponse,actix_web::Error>{letusers=data.get_all_users().map_err(|e|actix_web::error::ErrorInternalServerError(e))?;Ok(HttpResponse::Ok().json(users))}pubasyncfnupdate_user(data:web::Data<UserService>,path:web::Path<u64>,req:web::Json<UpdateUserRequest>,)->Result<HttpResponse,actix_web::Error>{letuser=data.update_user(path.into_inner(),req.name.clone(),req.email.clone()).map_err(|e|actix_web::error::ErrorInternalServerError(e))?;matchuser{Some(user)=>Ok(HttpResponse::Ok().json(user)),None=>Ok(HttpResponse::NotFound().json("User not found")),}}pubasyncfndelete_user(data:web::Data<UserService>,path:web::Path<u64>,)->Result<HttpResponse,actix_web::Error>{letdeleted=data.delete_user(path.into_inner()).map_err(|e|actix_web::error::ErrorInternalServerError(e))?;ifdeleted{Ok(HttpResponse::NoContent().finish())}else{Ok(HttpResponse::NotFound().json("User not found"))}}/// Application configuration.pubfnconfigure_app(cfg:&mutweb::ServiceConfig){cfg.service(web::scope("/api/v1").service(web::resource("/users").route(web::get().to(get_all_users)).route(web::post().to(create_user))).service(web::resource("/users/{id}").route(web::get().to(get_user)).route(web::put().to(update_user)).route(web::delete().to(delete_user))));}/// Main application setup.pubasyncfncreate_app()->std::io::Result<()>{letuser_service=web::Data::new(UserService::new());HttpServer::new(move||{App::new().app_data(user_service.clone()).wrap(middleware::Logger::default()).wrap(middleware::DefaultHeaders::new().header("X-Version","1.0")).configure(configure_app)}).bind("127.0.0.1:8080")?.run().await}#[cfg(test)]modtests{usesuper::*;#[test]fntest_user_service(){letservice=UserService::new();letuser=service.create_user("John".to_string(),"john@example.com".to_string()).unwrap();assert_eq!(user.name,"John");assert_eq!(user.email,"john@example.com");letretrieved=service.get_user(user.id).unwrap().unwrap();assert_eq!(retrieved.name,"John");}}
// rust/02-axum-patterns.rs/*Axum patterns and best practices for Rust*/useaxum::{extract::{Path,Query,State},http::StatusCode,response::Json,routing::{get,post,put,delete},Router,};useserde::{Deserialize,Serialize};usestd::sync::Arc;usetokio::sync::Mutex;/// User data structure.#[derive(Debug, Clone, Serialize, Deserialize)]pubstructUser{pubid:u64,pubname:String,pubemail:String,}/// Application state.pubstructAppState{pubusers:Mutex<Vec<User>>,pubnext_id:Mutex<u64>,}implAppState{pubfnnew()->Self{Self{users:Mutex::new(Vec::new()),next_id:Mutex::new(1),}}}/// Request/Response structures.#[derive(Deserialize)]pubstructCreateUserRequest{pubname:String,pubemail:String,}#[derive(Deserialize)]pubstructUpdateUserRequest{pubname:Option<String>,pubemail:Option<String>,}#[derive(Deserialize)]pubstructUserQuery{publimit:Option<usize>,puboffset:Option<usize>,}/// Handler functions.pubasyncfncreate_user(State(state):State<Arc<AppState>>,Json(req):Json<CreateUserRequest>,)->Result<Json<User>,StatusCode>{letmutusers=state.users.lock().await;letmutnext_id=state.next_id.lock().await;letuser=User{id:*next_id,name:req.name,email:req.email,};*next_id+=1;users.push(user.clone());Ok(Json(user))}pubasyncfnget_user(State(state):State<Arc<AppState>>,Path(id):Path<u64>,)->Result<Json<User>,StatusCode>{letusers=state.users.lock().await;matchusers.iter().find(|u|u.id==id){Some(user)=>Ok(Json(user.clone())),None=>Err(StatusCode::NOT_FOUND),}}pubasyncfnget_all_users(State(state):State<Arc<AppState>>,Query(query):Query<UserQuery>,)->Result<Json<Vec<User>>,StatusCode>{letusers=state.users.lock().await;letmutresult=users.clone();ifletSome(offset)=query.offset{result=result.into_iter().skip(offset).collect();}ifletSome(limit)=query.limit{result=result.into_iter().take(limit).collect();}Ok(Json(result))}pubasyncfnupdate_user(State(state):State<Arc<AppState>>,Path(id):Path<u64>,Json(req):Json<UpdateUserRequest>,)->Result<Json<User>,StatusCode>{letmutusers=state.users.lock().await;matchusers.iter_mut().find(|u|u.id==id){Some(user)=>{ifletSome(name)=req.name{user.name=name;}ifletSome(email)=req.email{user.email=email;}Ok(Json(user.clone()))}None=>Err(StatusCode::NOT_FOUND),}}pubasyncfndelete_user(State(state):State<Arc<AppState>>,Path(id):Path<u64>,)->Result<StatusCode,StatusCode>{letmutusers=state.users.lock().await;letinitial_len=users.len();users.retain(|u|u.id!=id);ifusers.len()<initial_len{Ok(StatusCode::NO_CONTENT)}else{Err(StatusCode::NOT_FOUND)}}/// Application setup.pubfncreate_app()->Router{letstate=Arc::new(AppState::new());Router::new().route("/api/v1/users",get(get_all_users).post(create_user)).route("/api/v1/users/:id",get(get_user).put(update_user).delete(delete_user)).with_state(state)}#[cfg(test)]modtests{usesuper::*;#[tokio::test]asyncfntest_app_state(){letstate=Arc::new(AppState::new());letreq=CreateUserRequest{name:"John".to_string(),email:"john@example.com".to_string(),};letresult=create_user(State(state),Json(req)).await;assert!(result.is_ok());}}