use crate::DbError;
use crate::DbId;
use crate::DbValue;
use crate::StorageData;
use crate::collections::multi_map::MultiMapStorage;
use crate::collections::vec::DbVec;
use crate::collections::vec::VecValue;
use crate::db::db_value_index::DbValueIndex;
use crate::storage::Storage;
use crate::storage::StorageIndex;
use crate::utilities::serialize::Serialize;
use crate::utilities::serialize::SerializeStatic;
#[derive(Copy, Clone)]
pub struct DbIndexStorageIndex {
key_index: DbValueIndex,
ids_index: StorageIndex,
}
pub struct DbIndex<D>
where
D: StorageData,
{
key: DbValue,
key_index: DbValueIndex,
ids: MultiMapStorage<DbValue, DbId, D>,
}
pub struct DbIndexes<D>
where
D: StorageData,
{
indexes: Vec<DbIndex<D>>,
storage_indexes: DbVec<DbIndexStorageIndex, D>,
}
impl<D> DbIndex<D>
where
D: StorageData,
{
pub fn from_storage(storage: &Storage<D>, index: DbIndexStorageIndex) -> Result<Self, DbError> {
let key_index = index.key_index;
let key = DbValue::load_db_value(key_index, storage)?;
let ids = MultiMapStorage::from_storage(storage, index.ids_index)?;
Ok(Self {
key_index,
key,
ids,
})
}
pub fn ids(&self) -> &MultiMapStorage<DbValue, DbId, D> {
&self.ids
}
pub fn ids_mut(&mut self) -> &mut MultiMapStorage<DbValue, DbId, D> {
&mut self.ids
}
pub fn key(&self) -> &DbValue {
&self.key
}
pub fn new(key: DbValue, storage: &mut Storage<D>) -> Result<Self, DbError> {
let key_index = key.store_db_value(storage)?;
let ids = MultiMapStorage::new(storage)?;
Ok(Self {
key,
key_index,
ids,
})
}
pub fn remove_from_storage(self, storage: &mut Storage<D>) -> Result<(), DbError> {
let id = storage.transaction();
DbValue::remove(storage, &self.key_index.data())?;
self.ids.remove_from_storage(storage)?;
storage.commit(id)
}
pub fn shrink_to_fit(&mut self, storage: &mut Storage<D>) -> Result<(), DbError> {
self.ids.shrink_to_fit(storage)
}
pub fn storage_index(&self) -> DbIndexStorageIndex {
DbIndexStorageIndex {
key_index: self.key_index,
ids_index: self.ids.storage_index(),
}
}
}
impl<D> DbIndexes<D>
where
D: StorageData,
{
pub fn from_storage(storage: &Storage<D>, index: StorageIndex) -> Result<Self, DbError> {
let storage_indexes: DbVec<DbIndexStorageIndex, D> = DbVec::from_storage(storage, index)?;
let mut indexes = vec![];
for storage_index in storage_indexes.iter(storage) {
let index = DbIndex::from_storage(storage, storage_index)?;
indexes.push(index);
}
Ok(Self {
indexes,
storage_indexes,
})
}
pub fn index(&self, key: &DbValue) -> Option<&DbIndex<D>> {
self.indexes.iter().find(|index| index.key() == key)
}
pub fn index_mut(&mut self, key: &DbValue) -> Option<&mut DbIndex<D>> {
self.indexes.iter_mut().find(|index| index.key() == key)
}
pub fn indexes(&self) -> &[DbIndex<D>] {
self.indexes.as_slice()
}
pub fn insert(
&mut self,
storage: &mut Storage<D>,
key: DbValue,
) -> Result<&mut DbIndex<D>, DbError> {
let index = DbIndex::new(key, storage)?;
self.storage_indexes.push(storage, &index.storage_index())?;
self.indexes.push(index);
Ok(self.indexes.last_mut().unwrap())
}
pub fn new(storage: &mut Storage<D>) -> Result<Self, DbError> {
Ok(Self {
indexes: vec![],
storage_indexes: DbVec::new(storage)?,
})
}
pub fn remove(&mut self, storage: &mut Storage<D>, key: &DbValue) -> Result<(), DbError> {
if let Some(pos) = self.indexes.iter().position(|index| index.key() == key) {
self.storage_indexes.remove(storage, pos as u64)?;
let index = self.indexes.remove(pos);
index.remove_from_storage(storage)?;
}
Ok(())
}
pub fn shrink_to_fit(&mut self, storage: &mut Storage<D>) -> Result<(), DbError> {
for index in &mut self.indexes {
index.shrink_to_fit(storage)?;
}
self.indexes.shrink_to_fit();
self.storage_indexes.shrink_to_fit(storage)
}
pub fn storage_index(&self) -> StorageIndex {
self.storage_indexes.storage_index()
}
}
impl<D: StorageData> VecValue<D> for DbValue {
fn store(&self, storage: &mut crate::storage::Storage<D>) -> Result<Vec<u8>, crate::DbError> {
let index = self.store_db_value(storage)?;
Ok(index.data().to_vec())
}
fn load(storage: &crate::storage::Storage<D>, bytes: &[u8]) -> Result<Self, crate::DbError> {
let index = DbValueIndex::deserialize(bytes)?;
DbValue::load_db_value(index, storage)
}
fn remove(
storage: &mut crate::storage::Storage<D>,
bytes: &[u8],
) -> Result<(), crate::DbError> {
let index = DbValueIndex::deserialize(bytes)?;
if !index.is_value() {
storage.remove(StorageIndex(index.index()))?;
}
Ok(())
}
fn storage_len() -> u64 {
DbValueIndex::serialized_size_static()
}
}
impl<D: StorageData> VecValue<D> for DbIndexStorageIndex {
fn store(&self, _storage: &mut Storage<D>) -> Result<Vec<u8>, DbError> {
let key_index = self.key_index.serialize();
let ids_index = self.ids_index.serialize();
Ok([key_index, ids_index].concat())
}
fn load(_storage: &Storage<D>, bytes: &[u8]) -> Result<Self, DbError> {
let key_index = DbValueIndex::deserialize(bytes)?;
let ids_index = StorageIndex::deserialize(&bytes[key_index.serialized_size() as usize..])?;
Ok(Self {
key_index,
ids_index,
})
}
fn remove(_storage: &mut Storage<D>, _bytes: &[u8]) -> Result<(), DbError> {
Ok(())
}
fn storage_len() -> u64 {
DbValueIndex::serialized_size_static() + StorageIndex::serialized_size_static()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MemoryStorage;
#[test]
#[allow(clippy::clone_on_copy)]
fn derived_from_clone() {
let left = DbIndexStorageIndex {
key_index: DbValueIndex::new(),
ids_index: StorageIndex::from(1),
};
let other = left.clone();
assert_eq!(left.key_index, other.key_index);
assert_eq!(left.ids_index, other.ids_index);
}
#[test]
fn from_storage() {
let mut storage = Storage::<MemoryStorage>::new("test").unwrap();
let index;
{
let mut indexes = DbIndexes::new(&mut storage).unwrap();
indexes.insert(&mut storage, "username".into()).unwrap();
indexes.insert(&mut storage, "token".into()).unwrap();
let username_index = indexes.index_mut(&"username".into()).unwrap();
username_index
.ids_mut()
.insert(&mut storage, &"user1".into(), &DbId(5))
.unwrap();
index = indexes.storage_index();
}
let indexes = DbIndexes::from_storage(&storage, index).unwrap();
assert_eq!(
indexes
.index(&"username".into())
.unwrap()
.ids()
.value(&storage, &"user1".into())
.unwrap(),
Some(DbId(5))
);
}
#[test]
fn index() {
let mut storage = Storage::<MemoryStorage>::new("test").unwrap();
let mut indexes = DbIndexes::new(&mut storage).unwrap();
indexes.insert(&mut storage, "username".into()).unwrap();
indexes.insert(&mut storage, "token".into()).unwrap();
assert_eq!(
indexes.index(&"username".into()).unwrap().key,
"username".into()
);
assert_eq!(indexes.index(&"token".into()).unwrap().key, "token".into());
}
#[test]
fn index_missing() {
let mut storage = Storage::<MemoryStorage>::new("test").unwrap();
let mut indexes = DbIndexes::new(&mut storage).unwrap();
indexes.insert(&mut storage, "username".into()).unwrap();
assert!(indexes.index(&"token".into()).is_none());
}
#[test]
fn index_mut() {
let mut storage = Storage::<MemoryStorage>::new("test").unwrap();
let mut indexes = DbIndexes::new(&mut storage).unwrap();
indexes.insert(&mut storage, "username".into()).unwrap();
indexes.insert(&mut storage, "token".into()).unwrap();
assert_eq!(
indexes.index_mut(&"username".into()).unwrap().key,
"username".into()
);
assert_eq!(
indexes.index_mut(&"token".into()).unwrap().key,
"token".into()
);
}
#[test]
fn index_mut_missing() {
let mut storage = Storage::<MemoryStorage>::new("test").unwrap();
let mut indexes = DbIndexes::new(&mut storage).unwrap();
indexes.insert(&mut storage, "username".into()).unwrap();
assert!(indexes.index_mut(&"token".into()).is_none());
}
#[test]
fn insert() {
let mut storage = Storage::<MemoryStorage>::new("test").unwrap();
let mut indexes = DbIndexes::new(&mut storage).unwrap();
let index = indexes.insert(&mut storage, "username".into()).unwrap();
index
.ids_mut()
.insert(&mut storage, &"user1".into(), &DbId(1))
.unwrap();
let id = index
.ids()
.value(&storage, &"user1".into())
.unwrap()
.unwrap();
assert_eq!(id, DbId(1));
}
#[test]
fn remove() {
let mut storage = Storage::<MemoryStorage>::new("test").unwrap();
let mut indexes = DbIndexes::new(&mut storage).unwrap();
indexes
.insert(&mut storage, "username_which_is_long".into())
.unwrap()
.ids_mut()
.insert(&mut storage, &"".into(), &DbId(0))
.unwrap();
indexes
.remove(&mut storage, &"username_which_is_long".into())
.unwrap();
assert!(indexes.index(&"username_which_is_long".into()).is_none());
}
#[test]
fn remove_from_storage_db_index() {
let mut storage: Storage<MemoryStorage> = Storage::new("test").unwrap();
let mut index =
DbIndex::new("username which is not exactly short".into(), &mut storage).unwrap();
index
.ids_mut()
.insert(
&mut storage,
&"user some really long username".into(),
&DbId(1),
)
.unwrap();
index.remove_from_storage(&mut storage).unwrap();
let len = storage.len();
storage.optimize_storage().unwrap();
assert!(storage.len() < len);
}
#[test]
fn remove_missing() {
let mut storage = Storage::<MemoryStorage>::new("test").unwrap();
let mut indexes = DbIndexes::new(&mut storage).unwrap();
indexes.remove(&mut storage, &"username".into()).unwrap();
assert!(indexes.index(&"username".into()).is_none());
}
}