|
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(())
|
|
}
|