1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::collections::{hash_map::Entry, HashMap};
use std::sync::{Arc, Mutex};
use crate::error::{InternalError, InvalidArgumentError, InvalidStateError};
use super::{error::UserProfileStoreError, Profile, ProfileBuilder, UserProfileStore};
#[derive(Default, Clone)]
pub struct MemoryUserProfileStore {
inner: Arc<Mutex<HashMap<String, Profile>>>,
}
impl MemoryUserProfileStore {
pub fn new() -> Self {
Self::default()
}
}
impl UserProfileStore for MemoryUserProfileStore {
fn add_profile(&self, profile: Profile) -> Result<(), UserProfileStoreError> {
let mut inner = self.inner.lock().map_err(|_| {
UserProfileStoreError::Internal(InternalError::with_message(
"Cannot access user profile store: mutex lock poisoned".to_string(),
))
})?;
inner.insert(profile.user_id.clone(), profile);
Ok(())
}
fn update_profile(&self, profile: Profile) -> Result<(), UserProfileStoreError> {
let mut inner = self.inner.lock().map_err(|_| {
UserProfileStoreError::Internal(InternalError::with_message(
"Cannot access user profile store: mutex lock poisoned".to_string(),
))
})?;
if let Entry::Occupied(mut entry) = inner.entry(profile.user_id.clone()) {
entry.insert(
ProfileBuilder::default()
.with_user_id(profile.user_id.clone())
.with_name(profile.name)
.with_given_name(profile.given_name)
.with_family_name(profile.family_name)
.with_email(profile.email)
.build()
.map_err(|_| {
UserProfileStoreError::Internal(InternalError::with_message(
"Failed to build profile with updated details".to_string(),
))
})?,
);
Ok(())
} else {
Err(UserProfileStoreError::InvalidArgument(
InvalidArgumentError::new(
"user_id".to_string(),
"A profile for the given user_id does not exist".to_string(),
),
))
}
}
fn remove_profile(&self, user_id: &str) -> Result<(), UserProfileStoreError> {
let mut inner = self.inner.lock().map_err(|_| {
UserProfileStoreError::Internal(InternalError::with_message(
"Cannot access user profile store: mutex lock poisoned".to_string(),
))
})?;
if inner.remove(user_id).is_some() {
Ok(())
} else {
Err(UserProfileStoreError::InvalidState(
InvalidStateError::with_message(
"A profile with the given user id does not exist".to_string(),
),
))
}
}
fn get_profile(&self, user_id: &str) -> Result<Profile, UserProfileStoreError> {
let inner = self.inner.lock().map_err(|_| {
UserProfileStoreError::Internal(InternalError::with_message(
"Cannot access user profile store: mutex lock poisoned".to_string(),
))
})?;
if let Some(profile) = inner.get(user_id) {
Ok(profile.clone())
} else {
Err(UserProfileStoreError::InvalidArgument(
InvalidArgumentError::new(
"user_id".to_string(),
"A profile for the given user_id does not exist".to_string(),
),
))
}
}
fn list_profiles(&self) -> Result<Option<Vec<Profile>>, UserProfileStoreError> {
let inner = self.inner.lock().map_err(|_| {
UserProfileStoreError::Internal(InternalError::with_message(
"Cannot access user profile store: mutex lock poisoned".to_string(),
))
})?;
Ok(Some(
inner.iter().map(|(_, profile)| profile.clone()).collect(),
))
}
fn clone_box(&self) -> Box<dyn UserProfileStore> {
Box::new(self.clone())
}
}