1 use std::collections::HashMap;
2 use std::sync::{Arc, Mutex};
3
4 #[derive(Debug, Clone)]
5 pub struct Pop3Message {
6 pub id: usize,
7 pub content: String,
8 pub size: usize,
9 pub deleted: bool,
10 }
11
12 impl Pop3Message {
13 pub fn new(id: usize, content: String) -> Self {
14 let size = content.len();
15 Self {
16 id,
17 content,
18 size,
19 deleted: false,
20 }
21 }
22 }
23
24 #[derive(Debug, Clone)]
25 pub struct Pop3Mailbox {
26 messages: Arc<Mutex<HashMap<String, Vec<Pop3Message>>>>,
27 next_id: Arc<Mutex<HashMap<String, usize>>>,
28 }
29
30 impl Pop3Mailbox {
31 pub fn new() -> Self {
32 Self {
33 messages: Arc::new(Mutex::new(HashMap::new())),
34 next_id: Arc::new(Mutex::new(HashMap::new())),
35 }
36 }
37
38 pub fn add_message(&self, username: &str, content: String) {
39 let mut messages = self.messages.lock().unwrap();
40 let mut next_id = self.next_id.lock().unwrap();
41
42 let user_messages = messages.entry(username.to_string()).or_insert_with(Vec::new);
43 let id_counter = next_id.entry(username.to_string()).or_insert(1);
44 let id = *id_counter;
45 *id_counter += 1;
46
47 user_messages.push(Pop3Message::new(id, content));
48 }
49
50 pub fn get_messages(&self, username: &str) -> Vec<Pop3Message> {
51 let messages = self.messages.lock().unwrap();
52 messages
53 .get(username)
54 .map(|m| m.clone())
55 .unwrap_or_default()
56 }
57
58 pub fn mark_deleted(&self, username: &str, msg_id: usize) -> bool {
59 let mut messages = self.messages.lock().unwrap();
60 if let Some(user_messages) = messages.get_mut(username) {
61 if let Some(msg) = user_messages.iter_mut().find(|m| m.id == msg_id) {
62 msg.deleted = true;
63 return true;
64 }
65 }
66 false
67 }
68
69 pub fn reset_deleted(&self, username: &str) {
70 let mut messages = self.messages.lock().unwrap();
71 if let Some(user_messages) = messages.get_mut(username) {
72 for msg in user_messages.iter_mut() {
73 msg.deleted = false;
74 }
75 }
76 }
77
78 pub fn delete_marked(&self, username: &str) {
79 let mut messages = self.messages.lock().unwrap();
80 if let Some(user_messages) = messages.get_mut(username) {
81 // Delete marked messages without re-indexing
82 // This preserves message IDs for any remaining messages
83 user_messages.retain(|m| !m.deleted);
84 }
85 }
86
87 pub fn get_stats(&self, username: &str) -> (usize, usize) {
88 let messages = self.messages.lock().unwrap();
89 if let Some(user_messages) = messages.get(username) {
90 let non_deleted: Vec<_> = user_messages.iter().filter(|m| !m.deleted).collect();
91 let count = non_deleted.len();
92 let total_size = non_deleted.iter().map(|m| m.size).sum();
93 (count, total_size)
94 } else {
95 (0, 0)
96 }
97 }
98 }
99
100 impl Default for Pop3Mailbox {
101 fn default() -> Self {
102 Self::new()
103 }
104 }