diff --git a/benches/disk.rs b/benches/disk.rs index 326f57b..a1ad5b7 100644 --- a/benches/disk.rs +++ b/benches/disk.rs @@ -4,7 +4,6 @@ use std::time::{Duration, Instant}; use criterion::async_executor::AsyncStdExecutor; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use hypercore::{Hypercore, HypercoreBuilder, HypercoreError, Storage}; -use random_access_disk::RandomAccessDisk; use tempfile::Builder as TempfileBuilder; fn bench_create_disk(c: &mut Criterion) { @@ -24,7 +23,7 @@ fn bench_create_disk(c: &mut Criterion) { } #[cfg(feature = "cache")] -async fn create_hypercore(name: &str) -> Result, HypercoreError> { +async fn create_hypercore(name: &str) -> Result { let dir = TempfileBuilder::new() .prefix(name) .tempdir() @@ -38,7 +37,7 @@ async fn create_hypercore(name: &str) -> Result, Hyp } #[cfg(not(feature = "cache"))] -async fn create_hypercore(name: &str) -> Result, HypercoreError> { +async fn create_hypercore(name: &str) -> Result { let dir = TempfileBuilder::new() .prefix(name) .tempdir() diff --git a/benches/memory.rs b/benches/memory.rs index b439b1e..bb97685 100644 --- a/benches/memory.rs +++ b/benches/memory.rs @@ -19,11 +19,15 @@ fn bench_create_memory(c: &mut Criterion) { } #[cfg(feature = "cache")] -async fn create_hypercore( - page_size: usize, -) -> Result, HypercoreError> { +async fn create_hypercore(page_size: usize) -> Result { + use hypercore::StorageTraits; + let storage = Storage::open( - |_| Box::pin(async move { Ok(RandomAccessMemory::new(page_size)) }), + |_| { + Box::pin(async move { + Ok(Box::new(RandomAccessMemory::new(page_size)) as Box) + }) + }, false, ) .await?; @@ -34,11 +38,15 @@ async fn create_hypercore( } #[cfg(not(feature = "cache"))] -async fn create_hypercore( - page_size: usize, -) -> Result, HypercoreError> { +async fn create_hypercore(page_size: usize) -> Result { + use hypercore::StorageTraits; + let storage = Storage::open( - |_| Box::pin(async move { Ok(RandomAccessMemory::new(page_size)) }), + |_| { + Box::pin(async move { + Ok(Box::new(RandomAccessMemory::new(page_size)) as Box) + }) + }, false, ) .await?; diff --git a/examples/replication.rs b/examples/replication.rs index 52c205a..0e658cd 100644 --- a/examples/replication.rs +++ b/examples/replication.rs @@ -4,8 +4,6 @@ use hypercore::{ Hypercore, HypercoreBuilder, HypercoreError, PartialKeypair, RequestBlock, RequestUpgrade, Storage, }; -use random_access_disk::RandomAccessDisk; -use random_access_memory::RandomAccessMemory; use tempfile::Builder; #[cfg(feature = "tokio")] use tokio::main as async_main; @@ -73,8 +71,8 @@ async fn main() { } async fn replicate_index( - origin_hypercore: &mut Hypercore, - replicated_hypercore: &mut Hypercore, + origin_hypercore: &mut Hypercore, + replicated_hypercore: &mut Hypercore, request_index: u64, ) { let missing_nodes = origin_hypercore diff --git a/src/builder.rs b/src/builder.rs index 4e18dad..37af78e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,4 +1,3 @@ -use random_access_storage::RandomAccess; use std::fmt::Debug; #[cfg(feature = "cache")] use std::time::Duration; @@ -53,20 +52,14 @@ impl CacheOptionsBuilder { /// Build a Hypercore instance with options. #[derive(Debug)] -pub struct HypercoreBuilder -where - T: RandomAccess + Debug + Send, -{ - storage: Storage, +pub struct HypercoreBuilder { + storage: Storage, options: HypercoreOptions, } -impl HypercoreBuilder -where - T: RandomAccess + Debug + Send, -{ +impl HypercoreBuilder { /// Create a hypercore builder with a given storage - pub fn new(storage: Storage) -> Self { + pub fn new(storage: Storage) -> Self { Self { storage, options: HypercoreOptions::new(), @@ -94,7 +87,7 @@ where /// Build a new Hypercore. #[instrument(err, skip_all)] - pub async fn build(self) -> Result, HypercoreError> { + pub async fn build(self) -> Result { Hypercore::new(self.storage, self.options).await } } diff --git a/src/core.rs b/src/core.rs index fe49e9a..886ff98 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,7 +1,6 @@ //! Hypercore's main abstraction. Exposes an append-only, secure log structure. use ed25519_dalek::Signature; use futures::future::Either; -use random_access_storage::RandomAccess; use std::convert::TryFrom; use std::fmt::Debug; use tracing::instrument; @@ -40,12 +39,9 @@ impl HypercoreOptions { /// Hypercore is an append-only log structure. #[derive(Debug)] -pub struct Hypercore -where - T: RandomAccess + Debug, -{ +pub struct Hypercore { pub(crate) key_pair: PartialKeypair, - pub(crate) storage: Storage, + pub(crate) storage: Storage, pub(crate) oplog: Oplog, pub(crate) tree: MerkleTree, pub(crate) block_store: BlockStore, @@ -79,15 +75,12 @@ pub struct Info { pub writeable: bool, } -impl Hypercore -where - T: RandomAccess + Debug + Send, -{ +impl Hypercore { /// Creates/opens new hypercore using given storage and options pub(crate) async fn new( - mut storage: Storage, + mut storage: Storage, mut options: HypercoreOptions, - ) -> Result, HypercoreError> { + ) -> Result { let key_pair: Option = if options.open { if options.key_pair.is_some() { return Err(HypercoreError::BadArgument { @@ -734,7 +727,6 @@ fn update_contiguous_length( #[cfg(test)] mod tests { use super::*; - use random_access_memory::RandomAccessMemory; #[async_std::test] async fn core_create_proof_block_only() -> Result<(), HypercoreError> { @@ -1099,9 +1091,7 @@ mod tests { Ok(()) } - async fn create_hypercore_with_data( - length: u64, - ) -> Result, HypercoreError> { + async fn create_hypercore_with_data(length: u64) -> Result { let signing_key = generate_signing_key(); create_hypercore_with_data_and_key_pair( length, @@ -1116,7 +1106,7 @@ mod tests { async fn create_hypercore_with_data_and_key_pair( length: u64, key_pair: PartialKeypair, - ) -> Result, HypercoreError> { + ) -> Result { let storage = Storage::new_memory().await?; let mut hypercore = Hypercore::new( storage, diff --git a/src/lib.rs b/src/lib.rs index a403e38..24d8627 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ pub use crate::common::{ }; pub use crate::core::{AppendOutcome, Hypercore, Info}; pub use crate::crypto::{generate_signing_key, sign, verify, PartialKeypair}; -pub use crate::storage::Storage; +pub use crate::storage::{Storage, StorageTraits}; pub use ed25519_dalek::{ SecretKey, Signature, SigningKey, VerifyingKey, KEYPAIR_LENGTH, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 7eb3776..46268ba 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -15,16 +15,17 @@ use crate::{ HypercoreError, }; +/// Supertrait for Storage +pub trait StorageTraits: RandomAccess + Debug {} +impl StorageTraits for T {} + /// Save data to a desired storage backend. #[derive(Debug)] -pub struct Storage -where - T: RandomAccess + Debug, -{ - tree: T, - data: T, - bitfield: T, - oplog: T, +pub struct Storage { + tree: Box, + data: Box, + bitfield: Box, + oplog: Box, } pub(crate) fn map_random_access_err(err: RandomAccessError) -> HypercoreError { @@ -51,17 +52,18 @@ pub(crate) fn map_random_access_err(err: RandomAccessError) -> HypercoreError { } } -impl Storage -where - T: RandomAccess + Debug + Send, -{ +impl Storage { /// Create a new instance. Takes a callback to create new storage instances and overwrite flag. pub async fn open(create: Cb, overwrite: bool) -> Result where Cb: Fn( Store, ) -> std::pin::Pin< - Box> + Send>, + Box< + dyn std::future::Future< + Output = Result, RandomAccessError>, + > + Send, + >, >, { let mut tree = create(Store::Tree).await.map_err(map_random_access_err)?; @@ -235,7 +237,7 @@ where Ok(()) } - fn get_random_access(&mut self, store: &Store) -> &mut T { + fn get_random_access(&mut self, store: &Store) -> &mut Box { match store { Store::Tree => &mut self.tree, Store::Data => &mut self.data, @@ -243,31 +245,37 @@ where Store::Oplog => &mut self.oplog, } } -} -impl Storage { /// New storage backed by a `RandomAccessMemory` instance. #[instrument(err)] pub async fn new_memory() -> Result { - let create = |_| async { Ok(RandomAccessMemory::default()) }.boxed(); + let create = |_| { + async { Ok(Box::new(RandomAccessMemory::default()) as Box) } + .boxed() + }; // No reason to overwrite, as this is a new memory segment Self::open(create, false).await } -} -#[cfg(not(target_arch = "wasm32"))] -impl Storage { /// New storage backed by a `RandomAccessDisk` instance. + #[cfg(not(target_arch = "wasm32"))] #[instrument(err)] pub async fn new_disk(dir: &PathBuf, overwrite: bool) -> Result { let storage = |store: Store| { - let name = match store { - Store::Tree => "tree", - Store::Data => "data", - Store::Bitfield => "bitfield", - Store::Oplog => "oplog", - }; - RandomAccessDisk::open(dir.as_path().join(name)).boxed() + let dir = dir.clone(); + async move { + let name = match store { + Store::Tree => "tree", + Store::Data => "data", + Store::Bitfield => "bitfield", + Store::Oplog => "oplog", + }; + Ok( + Box::new(RandomAccessDisk::open(dir.as_path().join(name)).await?) + as Box, + ) + } + .boxed() }; Self::open(storage, overwrite).await } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index fbe8616..247b13c 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,6 +1,5 @@ use anyhow::Result; use ed25519_dalek::{SigningKey, VerifyingKey, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH}; -use random_access_disk::RandomAccessDisk; use sha2::{Digest, Sha256}; use std::io::prelude::*; use std::path::Path; @@ -35,7 +34,7 @@ pub fn get_test_key_pair() -> PartialKeypair { PartialKeypair { public, secret } } -pub async fn create_hypercore(work_dir: &str) -> Result> { +pub async fn create_hypercore(work_dir: &str) -> Result { let path = Path::new(work_dir).to_owned(); let key_pair = get_test_key_pair(); let storage = Storage::new_disk(&path, true).await?; @@ -45,7 +44,7 @@ pub async fn create_hypercore(work_dir: &str) -> Result Result> { +pub async fn open_hypercore(work_dir: &str) -> Result { let path = Path::new(work_dir).to_owned(); let storage = Storage::new_disk(&path, false).await?; Ok(HypercoreBuilder::new(storage).open(true).build().await?)