crew_rs/
credential_source.rs1use std::{
2 cell::RefCell,
3 collections::{hash_map::DefaultHasher, HashMap},
4 hash::{Hash, Hasher},
5 pin::Pin,
6 rc::Rc,
7};
8
9use futures::{future, Future, FutureExt};
10
11use crate::crew::CrewID;
12use crate::member::MemberCredential;
13
14#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
15pub struct CredentialSourceHash(u64);
16
17impl CredentialSourceHash {
18 pub fn from_hashable<H: Hash>(hashable: H) -> Self {
19 let mut s = DefaultHasher::new();
20 hashable.hash(&mut s);
21 CredentialSourceHash(s.finish())
22 }
23}
24
25pub trait CredentialSource {
26 fn add_credential<'a>(
27 &'a self,
28 crew_id: CrewID,
29 credential: MemberCredential,
30 ) -> Pin<Box<dyn Future<Output = ()> + 'a>>;
31
32 fn current_credentials_for<'a>(&'a self, crew_id: &'a CrewID) -> Vec<MemberCredential>;
33
34 fn id_hash(&self) -> CredentialSourceHash;
35
36 fn clone_ref(&self) -> Box<dyn CredentialSource>;
37
38 fn current_state(&self) -> HashMap<CrewID, Vec<MemberCredential>>;
39}
40
41#[derive(Clone)]
42pub struct SimpleCredentialSource {
43 id: u64,
44 credentials: Rc<RefCell<HashMap<CrewID, Vec<MemberCredential>>>>,
45}
46
47impl SimpleCredentialSource {
48 #[allow(clippy::new_without_default)]
49 pub fn new() -> Self {
50 Self {
51 id: rand::random(),
52 credentials: Rc::new(RefCell::new(HashMap::new())),
53 }
54 }
55}
56
57impl CredentialSource for SimpleCredentialSource {
58 fn add_credential<'a>(
59 &'a self,
60 crew_id: CrewID,
61 credential: MemberCredential,
62 ) -> Pin<Box<dyn Future<Output = ()> + 'a>> {
63 self.credentials
64 .borrow_mut()
65 .entry(crew_id)
66 .or_insert_with(Vec::new)
67 .push(credential);
68 future::ready(()).boxed_local()
69 }
70
71 fn current_credentials_for<'a>(&'a self, crew_id: &'a CrewID) -> Vec<MemberCredential> {
72 self.credentials
73 .borrow()
74 .get(crew_id)
75 .cloned()
76 .unwrap_or_default()
77 }
78
79 fn id_hash(&self) -> CredentialSourceHash {
80 CredentialSourceHash(self.id)
81 }
82
83 fn clone_ref(&self) -> Box<dyn CredentialSource> {
84 Box::new(self.clone())
85 }
86
87 fn current_state(&self) -> HashMap<CrewID, Vec<MemberCredential>> {
88 self.credentials.borrow().clone()
89 }
90}
91
92impl CredentialSource for Box<dyn CredentialSource> {
93 fn add_credential<'a>(
94 &'a self,
95 crew_id: CrewID,
96 credential: MemberCredential,
97 ) -> Pin<Box<dyn Future<Output = ()> + 'a>> {
98 (**self).add_credential(crew_id, credential)
99 }
100
101 fn current_credentials_for<'a>(&'a self, crew_id: &'a CrewID) -> Vec<MemberCredential> {
102 (**self).current_credentials_for(crew_id)
103 }
104
105 fn id_hash(&self) -> CredentialSourceHash {
106 (**self).id_hash()
107 }
108
109 fn clone_ref(&self) -> Box<dyn CredentialSource> {
110 (**self).clone_ref()
111 }
112
113 fn current_state(&self) -> HashMap<CrewID, Vec<MemberCredential>> {
114 (**self).current_state()
115 }
116}