use std::collections::HashMap; use std::fmt::{Debug, Display}; use std::str::FromStr; #[derive(Debug, Clone, PartialEq, Eq)] pub struct User { pub id: u64, pub name: String, pub email: String, pub active: bool, pub tags: Vec, } impl User { pub fn new(id: u64, name: &str, email: &str) -> Self { Self { id, name: name.to_string(), email: email.to_string(), active: true, tags: Vec::new(), } } pub fn deactivate(&mut self) { self.active = false; } pub fn add_tag(&mut self, tag: &str) { self.tags.push(tag.to_string()); } } impl Display for User { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} <{}> [{}]", self.name, self.email, self.id) } } pub enum ApiError { NotFound(String), Unauthorized, Internal(String), } impl Debug for ApiError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ApiError::NotFound(msg) => write!(f, "NotFound({})", msg), ApiError::Unauthorized => write!(f, "Unauthorized"), ApiError::Internal(msg) => write!(f, "Internal({})", msg), } } } pub type Result = std::result::Result; pub trait Repository { fn find_by_id(&self, id: u64) -> Result; fn save(&mut self, item: T) -> Result<()>; fn delete(&mut self, id: u64) -> Result<()>; } pub struct UserRepository { users: HashMap, } impl UserRepository { pub fn new() -> Self { Self { users: HashMap::new(), } } } impl Repository for UserRepository { fn find_by_id(&self, id: u64) -> Result { self.users .get(&id) .cloned() .ok_or_else(|| ApiError::NotFound(format!("User {}", id))) } fn save(&mut self, user: User) -> Result<()> { let id = user.id; self.users.insert(id, user); Ok(()) } fn delete(&mut self, id: u64) -> Result<()> { self.users.remove(&id); Ok(()) } } fn process_users(repo: &UserRepository) -> Result> { let names: Vec = repo .users .values() .filter(|u| u.active) .map(|u| u.name.clone()) .collect(); Ok(names) } fn main() -> Result<()> { let mut repo = UserRepository::new(); repo.save(User::new(1, "Alice", "alice@example.com"))?; let names = process_users(&repo)?; println!("{:?}", names); Ok(()) }