use serde::Deserialize;
use sled::{Db, IVec, Transactional, Tree, transaction::ConflictableTransactionResult};
use crate::{
database::{DatabaseEntry, DatabaseError, deserialize_from_ivec, serialize_to_ivec},
library::collection::{Collection, STATIC_COLLECTIONS, STATIC_COLLECTIONS_VERSION},
};
pub type DbKey = [u8; 32];
pub(crate) fn sled_clear(tree: &Tree, key: &DbKey) -> sled::Result<()> {
tree.remove(key).map(|_| ())
}
pub(crate) fn sled_get_raw(tree: &Tree, key: &DbKey) -> sled::Result<Option<IVec>> {
tree.get(key)
}
pub(crate) fn sled_get_all_raw(tree: &Tree) -> sled::Result<Vec<IVec>> {
tree.iter().values().collect()
}
pub(crate) fn sled_get_batch_raw<I>(tree: &Tree, keys: I) -> Result<Vec<IVec>, DatabaseError>
where
I: IntoIterator<Item = DbKey>,
{
keys.into_iter()
.map(|id| tree.get(id)?.ok_or(DatabaseError::MissingEntry))
.collect::<Result<Vec<IVec>, DatabaseError>>()
}
pub(crate) fn sled_version_from_raw(raw: IVec) -> u32 {
#[derive(Deserialize)]
struct Version {
version: u32,
}
deserialize_from_ivec::<Version>(raw).version
}
pub(crate) fn ensure_hardcoded_collections(db: &Db) -> Result<(), DatabaseError> {
const KEY: &[u8] = b"hardcoded_collections_version";
if db
.get(KEY)?
.is_none_or(|v| *v != STATIC_COLLECTIONS_VERSION.to_be_bytes())
{
let db_tree = &**db;
let collection_tree = Collection::tree(db);
(db_tree, &collection_tree).transaction(
|(db_tree, collection_tree)| -> ConflictableTransactionResult<(), DatabaseError> {
for collection in STATIC_COLLECTIONS.iter() {
let collection = *collection;
collection_tree
.insert(collection.id().as_bytes(), serialize_to_ivec(collection))?;
}
db_tree.insert(KEY, &STATIC_COLLECTIONS_VERSION.to_be_bytes())?;
Ok(())
},
)?;
}
Ok(())
}