Skip to content

Commit 16acbff

Browse files
authored
Merge pull request #139 from cowlicks/type-erase
Remove generic parameters from `Hypercore` and `Storage`
2 parents 8a97ff4 + 44eb767 commit 16acbff

File tree

8 files changed

+70
-75
lines changed

8 files changed

+70
-75
lines changed

benches/disk.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::time::{Duration, Instant};
44
use criterion::async_executor::AsyncStdExecutor;
55
use criterion::{black_box, criterion_group, criterion_main, Criterion};
66
use hypercore::{Hypercore, HypercoreBuilder, HypercoreError, Storage};
7-
use random_access_disk::RandomAccessDisk;
87
use tempfile::Builder as TempfileBuilder;
98

109
fn bench_create_disk(c: &mut Criterion) {
@@ -24,7 +23,7 @@ fn bench_create_disk(c: &mut Criterion) {
2423
}
2524

2625
#[cfg(feature = "cache")]
27-
async fn create_hypercore(name: &str) -> Result<Hypercore<RandomAccessDisk>, HypercoreError> {
26+
async fn create_hypercore(name: &str) -> Result<Hypercore, HypercoreError> {
2827
let dir = TempfileBuilder::new()
2928
.prefix(name)
3029
.tempdir()
@@ -38,7 +37,7 @@ async fn create_hypercore(name: &str) -> Result<Hypercore<RandomAccessDisk>, Hyp
3837
}
3938

4039
#[cfg(not(feature = "cache"))]
41-
async fn create_hypercore(name: &str) -> Result<Hypercore<RandomAccessDisk>, HypercoreError> {
40+
async fn create_hypercore(name: &str) -> Result<Hypercore, HypercoreError> {
4241
let dir = TempfileBuilder::new()
4342
.prefix(name)
4443
.tempdir()

benches/memory.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ fn bench_create_memory(c: &mut Criterion) {
1919
}
2020

2121
#[cfg(feature = "cache")]
22-
async fn create_hypercore(
23-
page_size: usize,
24-
) -> Result<Hypercore<RandomAccessMemory>, HypercoreError> {
22+
async fn create_hypercore(page_size: usize) -> Result<Hypercore, HypercoreError> {
23+
use hypercore::StorageTraits;
24+
2525
let storage = Storage::open(
26-
|_| Box::pin(async move { Ok(RandomAccessMemory::new(page_size)) }),
26+
|_| {
27+
Box::pin(async move {
28+
Ok(Box::new(RandomAccessMemory::new(page_size)) as Box<dyn StorageTraits>)
29+
})
30+
},
2731
false,
2832
)
2933
.await?;
@@ -34,11 +38,15 @@ async fn create_hypercore(
3438
}
3539

3640
#[cfg(not(feature = "cache"))]
37-
async fn create_hypercore(
38-
page_size: usize,
39-
) -> Result<Hypercore<RandomAccessMemory>, HypercoreError> {
41+
async fn create_hypercore(page_size: usize) -> Result<Hypercore, HypercoreError> {
42+
use hypercore::StorageTraits;
43+
4044
let storage = Storage::open(
41-
|_| Box::pin(async move { Ok(RandomAccessMemory::new(page_size)) }),
45+
|_| {
46+
Box::pin(async move {
47+
Ok(Box::new(RandomAccessMemory::new(page_size)) as Box<dyn StorageTraits>)
48+
})
49+
},
4250
false,
4351
)
4452
.await?;

examples/replication.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ use hypercore::{
44
Hypercore, HypercoreBuilder, HypercoreError, PartialKeypair, RequestBlock, RequestUpgrade,
55
Storage,
66
};
7-
use random_access_disk::RandomAccessDisk;
8-
use random_access_memory::RandomAccessMemory;
97
use tempfile::Builder;
108
#[cfg(feature = "tokio")]
119
use tokio::main as async_main;
@@ -73,8 +71,8 @@ async fn main() {
7371
}
7472

7573
async fn replicate_index(
76-
origin_hypercore: &mut Hypercore<RandomAccessDisk>,
77-
replicated_hypercore: &mut Hypercore<RandomAccessMemory>,
74+
origin_hypercore: &mut Hypercore,
75+
replicated_hypercore: &mut Hypercore,
7876
request_index: u64,
7977
) {
8078
let missing_nodes = origin_hypercore

src/builder.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use random_access_storage::RandomAccess;
21
use std::fmt::Debug;
32
#[cfg(feature = "cache")]
43
use std::time::Duration;
@@ -53,20 +52,14 @@ impl CacheOptionsBuilder {
5352

5453
/// Build a Hypercore instance with options.
5554
#[derive(Debug)]
56-
pub struct HypercoreBuilder<T>
57-
where
58-
T: RandomAccess + Debug + Send,
59-
{
60-
storage: Storage<T>,
55+
pub struct HypercoreBuilder {
56+
storage: Storage,
6157
options: HypercoreOptions,
6258
}
6359

64-
impl<T> HypercoreBuilder<T>
65-
where
66-
T: RandomAccess + Debug + Send,
67-
{
60+
impl HypercoreBuilder {
6861
/// Create a hypercore builder with a given storage
69-
pub fn new(storage: Storage<T>) -> Self {
62+
pub fn new(storage: Storage) -> Self {
7063
Self {
7164
storage,
7265
options: HypercoreOptions::new(),
@@ -94,7 +87,7 @@ where
9487

9588
/// Build a new Hypercore.
9689
#[instrument(err, skip_all)]
97-
pub async fn build(self) -> Result<Hypercore<T>, HypercoreError> {
90+
pub async fn build(self) -> Result<Hypercore, HypercoreError> {
9891
Hypercore::new(self.storage, self.options).await
9992
}
10093
}

src/core.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Hypercore's main abstraction. Exposes an append-only, secure log structure.
22
use ed25519_dalek::Signature;
33
use futures::future::Either;
4-
use random_access_storage::RandomAccess;
54
use std::convert::TryFrom;
65
use std::fmt::Debug;
76
use tracing::instrument;
@@ -40,12 +39,9 @@ impl HypercoreOptions {
4039

4140
/// Hypercore is an append-only log structure.
4241
#[derive(Debug)]
43-
pub struct Hypercore<T>
44-
where
45-
T: RandomAccess + Debug,
46-
{
42+
pub struct Hypercore {
4743
pub(crate) key_pair: PartialKeypair,
48-
pub(crate) storage: Storage<T>,
44+
pub(crate) storage: Storage,
4945
pub(crate) oplog: Oplog,
5046
pub(crate) tree: MerkleTree,
5147
pub(crate) block_store: BlockStore,
@@ -79,15 +75,12 @@ pub struct Info {
7975
pub writeable: bool,
8076
}
8177

82-
impl<T> Hypercore<T>
83-
where
84-
T: RandomAccess + Debug + Send,
85-
{
78+
impl Hypercore {
8679
/// Creates/opens new hypercore using given storage and options
8780
pub(crate) async fn new(
88-
mut storage: Storage<T>,
81+
mut storage: Storage,
8982
mut options: HypercoreOptions,
90-
) -> Result<Hypercore<T>, HypercoreError> {
83+
) -> Result<Hypercore, HypercoreError> {
9184
let key_pair: Option<PartialKeypair> = if options.open {
9285
if options.key_pair.is_some() {
9386
return Err(HypercoreError::BadArgument {
@@ -734,7 +727,6 @@ fn update_contiguous_length(
734727
#[cfg(test)]
735728
mod tests {
736729
use super::*;
737-
use random_access_memory::RandomAccessMemory;
738730

739731
#[async_std::test]
740732
async fn core_create_proof_block_only() -> Result<(), HypercoreError> {
@@ -1099,9 +1091,7 @@ mod tests {
10991091
Ok(())
11001092
}
11011093

1102-
async fn create_hypercore_with_data(
1103-
length: u64,
1104-
) -> Result<Hypercore<RandomAccessMemory>, HypercoreError> {
1094+
async fn create_hypercore_with_data(length: u64) -> Result<Hypercore, HypercoreError> {
11051095
let signing_key = generate_signing_key();
11061096
create_hypercore_with_data_and_key_pair(
11071097
length,
@@ -1116,7 +1106,7 @@ mod tests {
11161106
async fn create_hypercore_with_data_and_key_pair(
11171107
length: u64,
11181108
key_pair: PartialKeypair,
1119-
) -> Result<Hypercore<RandomAccessMemory>, HypercoreError> {
1109+
) -> Result<Hypercore, HypercoreError> {
11201110
let storage = Storage::new_memory().await?;
11211111
let mut hypercore = Hypercore::new(
11221112
storage,

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub use crate::common::{
9494
};
9595
pub use crate::core::{AppendOutcome, Hypercore, Info};
9696
pub use crate::crypto::{generate_signing_key, sign, verify, PartialKeypair};
97-
pub use crate::storage::Storage;
97+
pub use crate::storage::{Storage, StorageTraits};
9898
pub use ed25519_dalek::{
9999
SecretKey, Signature, SigningKey, VerifyingKey, KEYPAIR_LENGTH, PUBLIC_KEY_LENGTH,
100100
SECRET_KEY_LENGTH,

src/storage/mod.rs

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@ use crate::{
1515
HypercoreError,
1616
};
1717

18+
/// Supertrait for Storage
19+
pub trait StorageTraits: RandomAccess + Debug {}
20+
impl<T: RandomAccess + Debug> StorageTraits for T {}
21+
1822
/// Save data to a desired storage backend.
1923
#[derive(Debug)]
20-
pub struct Storage<T>
21-
where
22-
T: RandomAccess + Debug,
23-
{
24-
tree: T,
25-
data: T,
26-
bitfield: T,
27-
oplog: T,
24+
pub struct Storage {
25+
tree: Box<dyn StorageTraits + Send>,
26+
data: Box<dyn StorageTraits + Send>,
27+
bitfield: Box<dyn StorageTraits + Send>,
28+
oplog: Box<dyn StorageTraits + Send>,
2829
}
2930

3031
pub(crate) fn map_random_access_err(err: RandomAccessError) -> HypercoreError {
@@ -51,17 +52,18 @@ pub(crate) fn map_random_access_err(err: RandomAccessError) -> HypercoreError {
5152
}
5253
}
5354

54-
impl<T> Storage<T>
55-
where
56-
T: RandomAccess + Debug + Send,
57-
{
55+
impl Storage {
5856
/// Create a new instance. Takes a callback to create new storage instances and overwrite flag.
5957
pub async fn open<Cb>(create: Cb, overwrite: bool) -> Result<Self, HypercoreError>
6058
where
6159
Cb: Fn(
6260
Store,
6361
) -> std::pin::Pin<
64-
Box<dyn std::future::Future<Output = Result<T, RandomAccessError>> + Send>,
62+
Box<
63+
dyn std::future::Future<
64+
Output = Result<Box<dyn StorageTraits + Send>, RandomAccessError>,
65+
> + Send,
66+
>,
6567
>,
6668
{
6769
let mut tree = create(Store::Tree).await.map_err(map_random_access_err)?;
@@ -235,39 +237,45 @@ where
235237
Ok(())
236238
}
237239

238-
fn get_random_access(&mut self, store: &Store) -> &mut T {
240+
fn get_random_access(&mut self, store: &Store) -> &mut Box<dyn StorageTraits + Send> {
239241
match store {
240242
Store::Tree => &mut self.tree,
241243
Store::Data => &mut self.data,
242244
Store::Bitfield => &mut self.bitfield,
243245
Store::Oplog => &mut self.oplog,
244246
}
245247
}
246-
}
247248

248-
impl Storage<RandomAccessMemory> {
249249
/// New storage backed by a `RandomAccessMemory` instance.
250250
#[instrument(err)]
251251
pub async fn new_memory() -> Result<Self, HypercoreError> {
252-
let create = |_| async { Ok(RandomAccessMemory::default()) }.boxed();
252+
let create = |_| {
253+
async { Ok(Box::new(RandomAccessMemory::default()) as Box<dyn StorageTraits + Send>) }
254+
.boxed()
255+
};
253256
// No reason to overwrite, as this is a new memory segment
254257
Self::open(create, false).await
255258
}
256-
}
257259

258-
#[cfg(not(target_arch = "wasm32"))]
259-
impl Storage<RandomAccessDisk> {
260260
/// New storage backed by a `RandomAccessDisk` instance.
261+
#[cfg(not(target_arch = "wasm32"))]
261262
#[instrument(err)]
262263
pub async fn new_disk(dir: &PathBuf, overwrite: bool) -> Result<Self, HypercoreError> {
263264
let storage = |store: Store| {
264-
let name = match store {
265-
Store::Tree => "tree",
266-
Store::Data => "data",
267-
Store::Bitfield => "bitfield",
268-
Store::Oplog => "oplog",
269-
};
270-
RandomAccessDisk::open(dir.as_path().join(name)).boxed()
265+
let dir = dir.clone();
266+
async move {
267+
let name = match store {
268+
Store::Tree => "tree",
269+
Store::Data => "data",
270+
Store::Bitfield => "bitfield",
271+
Store::Oplog => "oplog",
272+
};
273+
Ok(
274+
Box::new(RandomAccessDisk::open(dir.as_path().join(name)).await?)
275+
as Box<dyn StorageTraits + Send>,
276+
)
277+
}
278+
.boxed()
271279
};
272280
Self::open(storage, overwrite).await
273281
}

tests/common/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use anyhow::Result;
22
use ed25519_dalek::{SigningKey, VerifyingKey, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH};
3-
use random_access_disk::RandomAccessDisk;
43
use sha2::{Digest, Sha256};
54
use std::io::prelude::*;
65
use std::path::Path;
@@ -35,7 +34,7 @@ pub fn get_test_key_pair() -> PartialKeypair {
3534
PartialKeypair { public, secret }
3635
}
3736

38-
pub async fn create_hypercore(work_dir: &str) -> Result<Hypercore<RandomAccessDisk>> {
37+
pub async fn create_hypercore(work_dir: &str) -> Result<Hypercore> {
3938
let path = Path::new(work_dir).to_owned();
4039
let key_pair = get_test_key_pair();
4140
let storage = Storage::new_disk(&path, true).await?;
@@ -45,7 +44,7 @@ pub async fn create_hypercore(work_dir: &str) -> Result<Hypercore<RandomAccessDi
4544
.await?)
4645
}
4746

48-
pub async fn open_hypercore(work_dir: &str) -> Result<Hypercore<RandomAccessDisk>> {
47+
pub async fn open_hypercore(work_dir: &str) -> Result<Hypercore> {
4948
let path = Path::new(work_dir).to_owned();
5049
let storage = Storage::new_disk(&path, false).await?;
5150
Ok(HypercoreBuilder::new(storage).open(true).build().await?)

0 commit comments

Comments
 (0)