use crate::contacts_service::{
error::ContactsServiceStorageError,
storage::database::{Contact, ContactsBackend, DbKey, DbKeyValuePair, DbValue, WriteOperation},
};
use std::sync::{Arc, RwLock};
#[derive(Default)]
pub struct InnerDatabase {
contacts: Vec<Contact>,
}
impl InnerDatabase {
pub fn new() -> Self {
Self { contacts: Vec::new() }
}
}
#[derive(Default, Clone)]
pub struct ContactsServiceMemoryDatabase {
db: Arc<RwLock<InnerDatabase>>,
}
impl ContactsServiceMemoryDatabase {
pub fn new() -> Self {
Self {
db: Arc::new(RwLock::new(InnerDatabase::new())),
}
}
}
impl ContactsBackend for ContactsServiceMemoryDatabase {
fn fetch(&self, key: &DbKey) -> Result<Option<DbValue>, ContactsServiceStorageError> {
let db = acquire_read_lock!(self.db);
let result = match key {
DbKey::Contact(pk) => db
.contacts
.iter()
.find(|v| &v.public_key == pk)
.map(|c| DbValue::Contact(Box::new(c.clone()))),
DbKey::Contacts => Some(DbValue::Contacts(db.contacts.clone())),
};
Ok(result)
}
fn write(&self, op: WriteOperation) -> Result<Option<DbValue>, ContactsServiceStorageError> {
let mut db = acquire_write_lock!(self.db);
match op {
WriteOperation::Upsert(kvp) => match kvp {
DbKeyValuePair::Contact(pk, c) => match db.contacts.iter_mut().find(|i| i.public_key == pk) {
None => db.contacts.push(c),
Some(existing_contact) => existing_contact.alias = c.alias,
},
},
WriteOperation::Remove(k) => match k {
DbKey::Contact(pk) => match db.contacts.iter().position(|c| c.public_key == pk) {
None => return Err(ContactsServiceStorageError::ValueNotFound(DbKey::Contact(pk))),
Some(pos) => return Ok(Some(DbValue::Contact(Box::new(db.contacts.remove(pos))))),
},
DbKey::Contacts => {
return Err(ContactsServiceStorageError::OperationNotSupported);
},
},
}
Ok(None)
}
}