pub use self::model::*;
use data_encoding::HEXLOWER;
use sha2::{Digest, Sha256};
use std::sync::Arc;
use url::Url;
#[cfg(feature = "dropbox")]
pub mod dropbox;
mod error;
mod local_dir;
mod memory;
mod model;
#[cfg(feature = "sled")]
mod sled;
pub mod sync;
#[cfg(test)]
mod tests;
pub use self::error::{StoreError, StoreResult};
use crate::memguard::weak::ZeroingWords;
type RingId = (String, u64);
type RingContent = (u64, ZeroingWords);
pub trait BlockStore: std::fmt::Debug + Send + Sync {
fn node_id(&self) -> &str;
fn list_ring_ids(&self) -> StoreResult<Vec<RingId>>;
fn get_ring(&self, ring_id: &str) -> StoreResult<RingContent>;
fn store_ring(&self, ring_id: &str, version: u64, raw: &[u8]) -> StoreResult<()>;
fn change_logs(&self) -> StoreResult<Vec<ChangeLog>>;
fn get_index(&self, index_id: &str) -> StoreResult<Option<ZeroingWords>>;
fn store_index(&self, index_id: &str, raw: &[u8]) -> StoreResult<()>;
fn add_block(&self, raw: &[u8]) -> StoreResult<String>;
fn get_block(&self, block: &str) -> StoreResult<ZeroingWords>;
fn commit(&self, changes: &[Change]) -> StoreResult<()>;
fn update_change_log(&self, change_log: ChangeLog) -> StoreResult<()>;
}
pub fn open_block_store(url: &str, node_id: &str) -> StoreResult<Arc<dyn BlockStore>> {
let store_url = Url::parse(url)?;
match store_url.scheme() {
"file" => Ok(Arc::new(local_dir::LocalDirBlockStore::new(
store_url.to_file_path().unwrap(),
node_id,
)?)),
"memory" => Ok(Arc::new(memory::MemoryBlockStore::new(node_id))),
#[cfg(feature = "sled")]
"sled" => Ok(Arc::new(sled::SledBlockStore::new(
store_url.to_file_path().unwrap(),
node_id,
)?)),
#[cfg(feature = "dropbox")]
"dropbox" => Ok(Arc::new(dropbox::DropboxBlockStore::new(
store_url.username(),
store_url.host_str().unwrap(),
node_id,
)?)),
_ => Err(StoreError::InvalidStoreUrl(url.to_string())),
}
}
pub fn generate_block_id(data: &[u8]) -> String {
let mut hasher = Sha256::new();
hasher.update(data);
HEXLOWER.encode(&hasher.finalize())
}