2026-03-25 16:14:33 +02:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
|
|
use borsh::{BorshDeserialize, BorshSerialize};
|
|
|
|
|
use rocksdb::{BoundColumnFamily, DBWithThreadMode, MultiThreaded, WriteBatch};
|
|
|
|
|
|
|
|
|
|
use crate::{DbResult, error::DbError};
|
|
|
|
|
|
|
|
|
|
pub mod cells;
|
|
|
|
|
|
2026-03-26 13:10:31 +02:00
|
|
|
pub trait SimpleStorableCell {
|
2026-03-25 16:14:33 +02:00
|
|
|
const CF_NAME: &'static str;
|
|
|
|
|
const CELL_NAME: &'static str;
|
2026-03-26 13:10:31 +02:00
|
|
|
type KeyParams;
|
2026-03-25 16:14:33 +02:00
|
|
|
|
2026-03-31 09:08:40 +03:00
|
|
|
fn key_constructor(_params: Self::KeyParams) -> DbResult<Vec<u8>> {
|
|
|
|
|
borsh::to_vec(&Self::CELL_NAME).map_err(|err| {
|
|
|
|
|
DbError::borsh_cast_message(
|
|
|
|
|
err,
|
|
|
|
|
Some(format!("Failed to serialize {:?}", Self::CELL_NAME)),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
2026-03-25 16:14:33 +02:00
|
|
|
|
|
|
|
|
fn column_ref(db: &DBWithThreadMode<MultiThreaded>) -> Arc<BoundColumnFamily<'_>> {
|
|
|
|
|
db.cf_handle(Self::CF_NAME)
|
|
|
|
|
.unwrap_or_else(|| panic!("Column family {:?} must be present", Self::CF_NAME))
|
|
|
|
|
}
|
2026-03-26 13:10:31 +02:00
|
|
|
}
|
2026-03-25 16:14:33 +02:00
|
|
|
|
2026-03-26 13:10:31 +02:00
|
|
|
pub trait SimpleReadableCell: SimpleStorableCell + BorshDeserialize {
|
|
|
|
|
fn get(db: &DBWithThreadMode<MultiThreaded>, params: Self::KeyParams) -> DbResult<Self> {
|
2026-03-31 09:08:40 +03:00
|
|
|
let res = Self::get_opt(db, params)?;
|
2026-03-25 16:14:33 +02:00
|
|
|
|
2026-03-31 09:08:40 +03:00
|
|
|
res.map_or_else(
|
|
|
|
|
|| {
|
|
|
|
|
Err(DbError::db_interaction_error(format!(
|
|
|
|
|
"{:?} not found",
|
|
|
|
|
Self::CELL_NAME
|
|
|
|
|
)))
|
|
|
|
|
},
|
|
|
|
|
|data| Ok(data),
|
|
|
|
|
)
|
2026-03-25 16:14:33 +02:00
|
|
|
}
|
|
|
|
|
|
2026-03-26 13:10:31 +02:00
|
|
|
fn get_opt(
|
|
|
|
|
db: &DBWithThreadMode<MultiThreaded>,
|
|
|
|
|
params: Self::KeyParams,
|
|
|
|
|
) -> DbResult<Option<Self>> {
|
2026-03-25 16:14:33 +02:00
|
|
|
let cf_ref = Self::column_ref(db);
|
|
|
|
|
let res = db
|
2026-03-26 13:10:31 +02:00
|
|
|
.get_cf(&cf_ref, Self::key_constructor(params)?)
|
2026-03-25 16:14:33 +02:00
|
|
|
.map_err(|rerr| {
|
|
|
|
|
DbError::rocksdb_cast_message(
|
|
|
|
|
rerr,
|
|
|
|
|
Some(format!("Failed to read {:?}", Self::CELL_NAME)),
|
|
|
|
|
)
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
res.map(|data| {
|
|
|
|
|
borsh::from_slice::<Self>(&data).map_err(|err| {
|
|
|
|
|
DbError::borsh_cast_message(
|
|
|
|
|
err,
|
|
|
|
|
Some(format!("Failed to deserialize {:?}", Self::CELL_NAME)),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
.transpose()
|
|
|
|
|
}
|
2026-03-26 13:10:31 +02:00
|
|
|
}
|
2026-03-25 16:14:33 +02:00
|
|
|
|
2026-03-26 13:10:31 +02:00
|
|
|
pub trait SimpleWritableCell: SimpleStorableCell + BorshSerialize {
|
2026-03-31 09:08:40 +03:00
|
|
|
fn value_constructor(&self) -> DbResult<Vec<u8>>;
|
|
|
|
|
|
2026-03-26 13:10:31 +02:00
|
|
|
fn put(&self, db: &DBWithThreadMode<MultiThreaded>, params: Self::KeyParams) -> DbResult<()> {
|
2026-03-25 16:14:33 +02:00
|
|
|
let cf_ref = Self::column_ref(db);
|
2026-03-26 13:10:31 +02:00
|
|
|
db.put_cf(
|
|
|
|
|
&cf_ref,
|
|
|
|
|
Self::key_constructor(params)?,
|
|
|
|
|
self.value_constructor()?,
|
|
|
|
|
)
|
|
|
|
|
.map_err(|rerr| {
|
|
|
|
|
DbError::rocksdb_cast_message(
|
|
|
|
|
rerr,
|
|
|
|
|
Some(format!("Failed to write {:?}", Self::CELL_NAME)),
|
|
|
|
|
)
|
|
|
|
|
})?;
|
2026-03-25 16:14:33 +02:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn put_batch(
|
|
|
|
|
&self,
|
|
|
|
|
db: &DBWithThreadMode<MultiThreaded>,
|
2026-03-26 13:10:31 +02:00
|
|
|
params: Self::KeyParams,
|
2026-03-25 16:14:33 +02:00
|
|
|
write_batch: &mut WriteBatch,
|
|
|
|
|
) -> DbResult<()> {
|
|
|
|
|
let cf_ref = Self::column_ref(db);
|
2026-03-26 13:10:31 +02:00
|
|
|
write_batch.put_cf(
|
|
|
|
|
&cf_ref,
|
|
|
|
|
Self::key_constructor(params)?,
|
|
|
|
|
self.value_constructor()?,
|
|
|
|
|
);
|
2026-03-25 16:14:33 +02:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|