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<String>,
}
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<T> = std::result::Result<T, ApiError>;
pub trait Repository<T> {
fn find_by_id(&self, id: u64) -> Result<T>;
fn save(&mut self, item: T) -> Result<()>;
fn delete(&mut self, id: u64) -> Result<()>;
}
pub struct UserRepository {
users: HashMap<u64, User>,
}
impl UserRepository {
pub fn new() -> Self {
Self {
users: HashMap::new(),
}
}
}
impl Repository<User> for UserRepository {
fn find_by_id(&self, id: u64) -> Result<User> {
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<Vec<String>> {
let names: Vec<String> = 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(())
}