add AccountCache

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-06-25 20:56:13 -04:00
parent f318bbb19a
commit 9cacb6bb69
2 changed files with 103 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
use enostr::Pubkey;
use hashbrown::{hash_map::OccupiedEntry, HashMap};
use crate::{SingleUnkIdAction, UserAccount};
pub struct AccountCache {
selected: Pubkey,
fallback: Pubkey,
// never empty at rest
accounts: HashMap<Pubkey, UserAccount>,
}
impl AccountCache {
pub(super) fn new(fallback: UserAccount) -> (Self, SingleUnkIdAction) {
let mut accounts = HashMap::with_capacity(1);
let pk = fallback.key.pubkey;
accounts.insert(pk, fallback);
(
Self {
selected: pk,
fallback: pk,
accounts,
},
SingleUnkIdAction::pubkey(pk),
)
}
pub fn get(&self, pk: &Pubkey) -> Option<&UserAccount> {
self.accounts.get(pk)
}
pub fn get_bytes(&self, pk: &[u8; 32]) -> Option<&UserAccount> {
self.accounts.get(pk)
}
pub(super) fn get_mut(&mut self, pk: &Pubkey) -> Option<&mut UserAccount> {
self.accounts.get_mut(pk)
}
pub(super) fn add<'a>(
&'a mut self,
account: UserAccount,
) -> OccupiedEntry<'a, Pubkey, UserAccount> {
let pk = account.key.pubkey;
self.accounts.entry(pk).insert(account)
}
pub(super) fn remove(&mut self, pk: &Pubkey) -> Option<UserAccount> {
// fallback account should never be removed
if *pk == self.fallback {
return None;
}
let removed = self.accounts.remove(pk);
if removed.is_some() && self.selected == *pk {
// TODO(kernelkind): choose next better
let (next, _) = self
.accounts
.iter()
.next()
.expect("accounts can never be empty");
self.selected = *next;
}
removed
}
/// guarenteed that all selected exist in accounts
pub(super) fn select(&mut self, pk: Pubkey) -> bool {
if !self.accounts.contains_key(&pk) {
return false;
}
self.selected = pk;
true
}
pub fn selected(&self) -> &UserAccount {
self.accounts
.get(&self.selected)
.expect("guarenteed that selected exists in accounts")
}
pub(super) fn selected_mut(&mut self) -> &mut UserAccount {
self.accounts
.get_mut(&self.selected)
.expect("guarenteed that selected exists in accounts")
}
}
impl<'a> IntoIterator for &'a AccountCache {
type Item = (&'a Pubkey, &'a UserAccount);
type IntoIter = hashbrown::hash_map::Iter<'a, Pubkey, UserAccount>;
fn into_iter(self) -> Self::IntoIter {
self.accounts.iter()
}
}

View File

@@ -1,4 +1,5 @@
pub mod accounts;
pub mod cache;
pub mod mute;
pub mod relay;