Skip to content

Commit

Permalink
refactor: Introduce Storable trait (#378)
Browse files Browse the repository at this point in the history
Main use case is allowing us to use `Link<UnixFsFile>` as a type in `PublicFile::userland`.
Other use case is allowing us to nest the WNFS Hamt: `Node<String, Node<String, String>>` is now possible (previously it required `K: Serialize` and `V: Serialize` (and we don't generally want to make both `K: AsyncSerialize` and `V: AsyncSerialize`.

Also:
- Remove `AsyncSerializable`
- Remove `RemembersCid` (both of these are now handled by `Storable`)
- Remove `TryFrom<Ipld>` instances that were used for deserialization of some types
- Remove `BlockStore::put_async_serializable` function (you can just use `Storable::store` instead)
- Introduce `NodeSerializable` and `HamtSerializable` for `wnfs-hamt` to follow the pattern used in `wnfs`.

---

* refactor: Absorb `RemembersCid` into `Storable`

This means `Storable` can do all of the logic for `store` and `load` appropriately.

* refactor: Remove empty `serializable.rs`

* refactor: Remove `AsyncSerialize`

* feat: `impl Storable for UnixFsFile`

* chore: Adjust comment

* refactor: Adjust wnfs-wasm code

* chore: Write some docs
  • Loading branch information
matheus23 authored Dec 5, 2023
1 parent 2b67800 commit 17c14c4
Show file tree
Hide file tree
Showing 39 changed files with 1,065 additions and 1,061 deletions.
42 changes: 18 additions & 24 deletions wnfs-bench/hamt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ use criterion::{
use proptest::{arbitrary::any, collection::vec, test_runner::TestRunner};
use std::cmp;
use wnfs_common::{
async_encode, decode,
libipld::cbor::DagCborCodec,
utils::{Arc, Sampleable},
BlockStore, Link, MemoryBlockStore,
BlockStore, Link, MemoryBlockStore, Storable, StoreIpld,
};
use wnfs_hamt::{
diff, merge,
Expand Down Expand Up @@ -82,17 +80,12 @@ fn node_load_get(c: &mut Criterion) {
node.set(i.to_string(), i, &store).await.unwrap();
}

let encoded_hamt = async_encode(&Hamt::with_root(node), &store, DagCborCodec)
.await
.unwrap();

store.put_serializable(&encoded_hamt).await.unwrap()
Hamt::with_root(node).store(&store).await.unwrap()
});

c.bench_function("node load and get", |b| {
b.to_async(AsyncStdExecutor).iter(|| async {
let encoded_hamt = store.get_deserializable::<Vec<u8>>(&cid).await.unwrap();
let hamt: Hamt<String, i32> = decode(encoded_hamt.as_ref(), DagCborCodec).unwrap();
let hamt = Hamt::<String, i32>::load(&cid, &store).await.unwrap();

for i in 0..50 {
assert!(hamt
Expand All @@ -114,18 +107,12 @@ fn node_load_remove(c: &mut Criterion) {
node.set(i.to_string(), i, &store).await.unwrap();
}

let encoded_hamt = async_encode(&Hamt::with_root(node), &store, DagCborCodec)
.await
.unwrap();

store.put_serializable(&encoded_hamt).await.unwrap()
Hamt::with_root(node).store(&store).await.unwrap()
});

c.bench_function("node load and remove", |b| {
b.to_async(AsyncStdExecutor).iter(|| async {
let encoded_hamt = store.get_deserializable::<Vec<u8>>(&cid).await.unwrap();
let mut hamt: Hamt<String, i32> =
black_box(decode(encoded_hamt.as_ref(), DagCborCodec).unwrap());
let mut hamt = black_box(Hamt::<String, i32>::load(&cid, &store).await.unwrap());

for i in 0..50 {
let value = hamt.root.remove(&i.to_string(), &store).await.unwrap();
Expand All @@ -143,11 +130,14 @@ fn hamt_load_decode(c: &mut Criterion) {
node.set(i.to_string(), i, &store).await.unwrap();
}

let encoded_hamt = async_encode(&Hamt::with_root(node), &store, DagCborCodec)
let (encoded_hamt, codec) = Hamt::with_root(node)
.to_serializable(&store)
.await
.unwrap()
.encode_ipld()
.unwrap();

let cid = store.put_serializable(&encoded_hamt).await.unwrap();
let cid = store.put_block(encoded_hamt.clone(), codec).await.unwrap();

(cid, encoded_hamt)
});
Expand All @@ -156,9 +146,7 @@ fn hamt_load_decode(c: &mut Criterion) {
group.throughput(Throughput::Bytes(bytes.len() as u64));
group.bench_function("0", |b| {
b.to_async(AsyncStdExecutor).iter(|| async {
let encoded_hamt = store.get_deserializable::<Vec<u8>>(&cid).await.unwrap();
let _: Hamt<String, i32> =
black_box(decode(encoded_hamt.as_ref(), DagCborCodec).unwrap());
black_box(Hamt::<String, i32>::load(&cid, &store).await.unwrap());
})
});
group.finish();
Expand All @@ -180,7 +168,13 @@ fn hamt_set_encode(c: &mut Criterion) {

let hamt = Hamt::with_root(node);

let _ = black_box(async_encode(&hamt, &store, DagCborCodec).await.unwrap());
black_box(
hamt.to_serializable(&store)
.await
.unwrap()
.encode_ipld()
.unwrap(),
);
},
BatchSize::SmallInput,
)
Expand Down
1 change: 1 addition & 0 deletions wnfs-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ parking_lot = "0.12"
proptest = { version = "1.1", optional = true }
rand_core = "0.6"
serde = { version = "1.0", features = ["rc"] }
serde_ipld_dagcbor = "0.4.2"
serde_json = { version = "1.0", optional = true }
thiserror = "1.0"

Expand Down
94 changes: 0 additions & 94 deletions wnfs-common/src/async_serialize.rs

This file was deleted.

11 changes: 1 addition & 10 deletions wnfs-common/src/blockstore.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
decode, encode,
utils::{Arc, CondSend, CondSync},
AsyncSerialize, BlockStoreError, MAX_BLOCK_SIZE,
BlockStoreError, MAX_BLOCK_SIZE,
};
use anyhow::{bail, Result};
use async_trait::async_trait;
Expand Down Expand Up @@ -72,15 +72,6 @@ pub trait BlockStore: Sized + CondSync {
self.put_block(bytes, CODEC_DAG_CBOR).await
}

async fn put_async_serializable<V>(&self, value: &V) -> Result<Cid>
where
V: AsyncSerialize + CondSync,
{
let ipld = value.async_serialize_ipld(self).await?;
let bytes = encode(&ipld, DagCborCodec)?;
self.put_block(bytes, CODEC_DAG_CBOR).await
}

// This should be the same in all implementations of BlockStore
fn create_cid(&self, bytes: &[u8], codec: u64) -> Result<Cid> {
// If there are too many bytes, abandon this task
Expand Down
14 changes: 0 additions & 14 deletions wnfs-common/src/encoding.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::{utils::CondSync, AsyncSerialize, BlockStore};
use anyhow::Result;
use libipld::{
codec::{Decode, Encode},
Expand All @@ -21,19 +20,6 @@ where
Ok(bytes)
}

/// Encodes an async serializable value into DagCbor bytes.
pub async fn async_encode<V, C>(value: &V, store: &impl BlockStore, codec: C) -> Result<Vec<u8>>
where
V: AsyncSerialize + CondSync,
C: Codec,
Ipld: Encode<C>,
{
let ipld = value.async_serialize_ipld(store).await?;
let mut bytes = Vec::new();
<Ipld as Encode<C>>::encode(&ipld, codec, &mut bytes)?;
Ok(bytes)
}

/// Decodes recieved DagCbor bytes into a deserializable value.
pub fn decode<D, C>(bytes: &[u8], codec: C) -> Result<D>
where
Expand Down
4 changes: 2 additions & 2 deletions wnfs-common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
//! This crate contains the common types and functions used by the WNFS crates.
mod async_serialize;
pub mod blockstore;
mod encoding;
mod error;
mod link;
mod metadata;
mod pathnodes;
mod storable;
mod traits;
pub mod utils;

pub use async_serialize::*;
pub use blockstore::*;
pub use encoding::*;
pub use error::*;
pub use link::*;
pub use metadata::*;
pub use pathnodes::*;
pub use storable::*;

//--------------------------------------------------------------------------------------------------
// Constants
Expand Down
Loading

0 comments on commit 17c14c4

Please sign in to comment.