Skip to content

Commit

Permalink
Refactor: Remove ReferencableStore Referencable and `private/link…
Browse files Browse the repository at this point in the history
….rs` (#62)

* Refactor: Remove referencable (& private/link for now)

* Simlify wasm build script #61

* Fix needles borrow
  • Loading branch information
matheus23 authored Sep 26, 2022
1 parent 2b8f60a commit 0228c17
Show file tree
Hide file tree
Showing 14 changed files with 183 additions and 497 deletions.
31 changes: 10 additions & 21 deletions crates/fs/common/async_serialize.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
use std::rc::Rc;

use async_trait::async_trait;
use libipld::{error::SerdeError, serde as ipld_serde, Cid, Ipld};
use libipld::{error::SerdeError, serde as ipld_serde, Ipld};
use serde::Serialize;
use serde::Serializer;

use super::ReferenceableStore;
use crate::BlockStore;

//--------------------------------------------------------------------------------------------------
// Macros
//--------------------------------------------------------------------------------------------------

// NOTE: For now, we only implement AsyncSerialize<StoreRef = Cid>.
macro_rules! impl_async_serialize {
( $( $ty:ty $( : < $( $generics:ident ),+ > )? ),+ ) => {
$(
#[async_trait(?Send)]
impl $( < $( $generics ),+ > )? AsyncSerialize for $ty $( where $( $generics: Serialize ),+ )? {
type StoreRef = Cid;

async fn async_serialize<S: Serializer, RS: ReferenceableStore<Ref = Self::StoreRef> + ?Sized>(
async fn async_serialize<S: Serializer, BS: BlockStore + ?Sized>(
&self,
serializer: S,
_: &mut RS,
_: &mut BS,
) -> Result<S::Ok, S::Error> {
self.serialize(serializer)
}
Expand All @@ -46,22 +43,16 @@ macro_rules! impl_async_serialize {
/// These links need to be resolved to Cids during serialization if they aren't already.
#[async_trait(?Send)]
pub trait AsyncSerialize {
type StoreRef;

/// Serializes the type.
async fn async_serialize<S, RS>(
&self,
serializer: S,
store: &mut RS,
) -> Result<S::Ok, S::Error>
async fn async_serialize<S, B>(&self, serializer: S, store: &mut B) -> Result<S::Ok, S::Error>
where
S: Serializer,
RS: ReferenceableStore<Ref = Self::StoreRef> + ?Sized;
B: BlockStore + ?Sized;

/// Serialize with an IPLD serializer.
async fn async_serialize_ipld<RS>(&self, store: &mut RS) -> Result<Ipld, SerdeError>
async fn async_serialize_ipld<B>(&self, store: &mut B) -> Result<Ipld, SerdeError>
where
RS: ReferenceableStore<Ref = Self::StoreRef> + ?Sized,
B: BlockStore + ?Sized,
{
self.async_serialize(ipld_serde::Serializer, store).await
}
Expand All @@ -73,12 +64,10 @@ pub trait AsyncSerialize {

#[async_trait(?Send)]
impl<T: AsyncSerialize> AsyncSerialize for Rc<T> {
type StoreRef = T::StoreRef;

async fn async_serialize<S, RS>(&self, serializer: S, store: &mut RS) -> Result<S::Ok, S::Error>
async fn async_serialize<S, B>(&self, serializer: S, store: &mut B) -> Result<S::Ok, S::Error>
where
S: Serializer,
RS: ReferenceableStore<Ref = Self::StoreRef> + ?Sized,
B: BlockStore + ?Sized,
{
self.as_ref().async_serialize(serializer, store).await
}
Expand Down
25 changes: 3 additions & 22 deletions crates/fs/common/blockstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use serde::{de::DeserializeOwned, Serialize};

use crate::{
private::{Key, Rng, NONCE_SIZE},
AsyncSerialize, ReferenceableStore,
AsyncSerialize,
};

use super::FsError;
Expand Down Expand Up @@ -57,10 +57,7 @@ pub trait BlockStore {
self.put_block(enc_bytes, IpldCodec::DagCbor).await
}

async fn put_async_serializable<V: AsyncSerialize<StoreRef = Cid>>(
&mut self,
value: &V,
) -> Result<Cid> {
async fn put_async_serializable<V: AsyncSerialize>(&mut self, value: &V) -> Result<Cid> {
let ipld = value.async_serialize_ipld(self).await?;

let mut bytes = Vec::new();
Expand Down Expand Up @@ -111,7 +108,7 @@ impl BlockStore for MemoryBlockStore {
let hash = Code::Sha2_256.digest(&bytes);
let cid = Cid::new(Version::V1, codec.into(), hash)?;

self.0.insert((&cid).to_string(), bytes);
self.0.insert(cid.to_string(), bytes);

Ok(cid)
}
Expand All @@ -127,22 +124,6 @@ impl BlockStore for MemoryBlockStore {
}
}

#[async_trait(?Send)]
impl<T: BlockStore + ?Sized> ReferenceableStore for T {
type Ref = Cid;

async fn get_value<V: DeserializeOwned>(&self, reference: &Self::Ref) -> Result<V> {
self.get_deserializable(reference).await
}

async fn put_value<V: AsyncSerialize<StoreRef = Self::Ref>>(
&mut self,
value: &V,
) -> Result<Self::Ref> {
self.put_async_serializable(value).await
}
}

//--------------------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions crates/fs/common/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod dagcbor {
use libipld::{
cbor::DagCborCodec,
codec::{Decode, Encode},
serde as ipld_serde, Cid, Ipld,
serde as ipld_serde, Ipld,
};
use serde::{de::DeserializeOwned, Serialize};

Expand All @@ -22,7 +22,7 @@ pub mod dagcbor {
}

/// Encodes an async serializable value into DagCbor bytes.
pub async fn async_encode<V: AsyncSerialize<StoreRef = Cid>, B: BlockStore>(
pub async fn async_encode<V: AsyncSerialize, B: BlockStore>(
value: &V,
store: &mut B,
) -> Result<Vec<u8>> {
Expand Down
164 changes: 146 additions & 18 deletions crates/fs/common/link.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use anyhow::Result;
use async_once_cell::OnceCell;
use async_trait::async_trait;
use libipld::Cid;
use serde::de::DeserializeOwned;

use crate::{AsyncSerialize, Referenceable, ReferenceableStore};
use crate::AsyncSerialize;
use crate::{BlockStore, IpldEq};

//--------------------------------------------------------------------------------------------------
Expand All @@ -14,49 +16,118 @@ use crate::{BlockStore, IpldEq};
/// It supports representing the "link" with a Cid or the deserialized value itself.
///
/// Link needs a `BlockStore` to be able to resolve Cids to corresponding values of `T` and vice versa.
pub type Link<T> = Referenceable<Cid, T>;
#[derive(Debug)]
pub enum Link<T> {
/// A variant of `Link` that started out as a `Cid`.
/// If the decoded value is resolved using `resolve_value`, then the `value_cache` gets populated and
/// further calls to `resolve_value` will just return from that cache.
Encoded { cid: Cid, value_cache: OnceCell<T> },
/// A variant of `Link` that started out as a deserialized value `T`.
/// If the cid is resolved using `resolve_cid`, then the `cid_cache` gets populated and further calls
/// to `resolve_cid` will just return from that cache.
Decoded { value: T, cid_cache: OnceCell<Cid> },
}

//--------------------------------------------------------------------------------------------------
// Implementations
//--------------------------------------------------------------------------------------------------

impl<T> Link<T> {
/// Creates a new `Link` that starts out as a Cid.
#[inline]
pub fn from_cid(cid: Cid) -> Self {
Self::from_reference(cid)
Self::Encoded {
cid,
value_cache: OnceCell::new(),
}
}

/// Gets the Cid stored in type. It attempts to get it from the store if it is not present in type.
#[inline]
pub async fn resolve_cid<'a, RS: ReferenceableStore<Ref = Cid> + ?Sized>(
&'a self,
store: &mut RS,
) -> Result<&'a Cid>
pub async fn resolve_cid<'a, B: BlockStore + ?Sized>(&'a self, store: &mut B) -> Result<&'a Cid>
where
T: AsyncSerialize<StoreRef = Cid>,
T: AsyncSerialize,
{
self.resolve_reference(store).await
match self {
Self::Encoded { cid, .. } => Ok(cid),
Self::Decoded { value, cid_cache } => {
cid_cache
.get_or_try_init(async { store.put_async_serializable(value).await })
.await
}
}
}

/// Gets the value stored in link. It attempts to get it from the store if it is not present in link.
pub async fn resolve_value<'a, B: BlockStore>(&'a self, store: &B) -> Result<&'a T>
where
T: DeserializeOwned,
{
match self {
Self::Encoded { cid, value_cache } => {
value_cache
.get_or_try_init(async { store.get_deserializable(cid).await })
.await
}
Self::Decoded { value, .. } => Ok(value),
}
}

/// Gets the cid data stored in type.
///
/// NOTE: This does not attempt to get it from the store if it does not exist..
#[inline]
pub fn get_cid(&self) -> Option<&Cid> {
self.get_reference()
match self {
Self::Encoded { cid, .. } => Some(cid),
Self::Decoded { cid_cache, .. } => cid_cache.get(),
}
}

/// Gets the value stored in type.
///
/// NOTE: This does not attempt to get it from the store if it does not exist.
pub fn get_value(&self) -> Option<&T> {
match self {
Self::Encoded { value_cache, .. } => value_cache.get(),
Self::Decoded { value, .. } => Some(value),
}
}

/// Gets an owned value from type. It attempts to it get from the store if it is not present in type.
pub async fn get_owned_value<B: BlockStore>(self, store: &B) -> Result<T>
where
T: DeserializeOwned,
{
match self {
Self::Encoded {
ref cid,
value_cache,
} => match value_cache.into_inner() {
Some(cached) => Ok(cached),
None => store.get_deserializable(cid).await,
},
Self::Decoded { value, .. } => Ok(value),
}
}

/// Checks if there is a Cid stored in link.
#[inline]
/// Checks if there is a Cid cached in link.
pub fn has_cid(&self) -> bool {
self.has_reference()
match self {
Self::Decoded { cid_cache, .. } => cid_cache.get().is_some(),
_ => true,
}
}

/// Checks if there is a value stored in link.
pub fn has_value(&self) -> bool {
match self {
Self::Encoded { value_cache, .. } => value_cache.get().is_some(),
_ => true,
}
}

/// Compares two links for equality. Attempts to get them from store if they are not already cached.
pub async fn deep_eq<B: BlockStore>(&self, other: &Link<T>, store: &mut B) -> Result<bool>
where
T: PartialEq + AsyncSerialize<StoreRef = Cid>,
T: PartialEq + AsyncSerialize,
{
if self == other {
return Ok(true);
Expand All @@ -67,7 +138,7 @@ impl<T> Link<T> {
}

#[async_trait(?Send)]
impl<T: PartialEq + AsyncSerialize<StoreRef = Cid>> IpldEq for Link<T> {
impl<T: PartialEq + AsyncSerialize> IpldEq for Link<T> {
async fn eq<B: BlockStore>(&self, other: &Link<T>, store: &mut B) -> Result<bool> {
if self == other {
return Ok(true);
Expand All @@ -77,6 +148,63 @@ impl<T: PartialEq + AsyncSerialize<StoreRef = Cid>> IpldEq for Link<T> {
}
}

impl<T> From<T> for Link<T> {
fn from(value: T) -> Self {
Self::Decoded {
value,
cid_cache: OnceCell::new(),
}
}
}

impl<T> Clone for Link<T>
where
T: Clone,
{
fn clone(&self) -> Self {
match self {
Self::Encoded { cid, value_cache } => Self::Encoded {
cid: *cid,
value_cache: OnceCell::new_with(value_cache.get().cloned()),
},
Self::Decoded { value, cid_cache } => Self::Decoded {
value: value.clone(),
cid_cache: OnceCell::new_with(cid_cache.get().cloned()),
},
}
}
}

impl<T> PartialEq for Link<T>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Encoded { cid, .. }, Self::Encoded { cid: cid2, .. }) => cid == cid2,
(Self::Decoded { value, .. }, Self::Decoded { value: value2, .. }) => value == value2,
(Self::Encoded { cid, .. }, Self::Decoded { value: value2, .. }) => {
if let Some(cid2) = other.get_cid() {
cid == cid2
} else if let Some(value) = self.get_value() {
value == value2
} else {
false
}
}
(Self::Decoded { value, .. }, Self::Encoded { cid: cid2, .. }) => {
if let Some(cid) = self.get_cid() {
cid == cid2
} else if let Some(value2) = other.get_value() {
value == value2
} else {
false
}
}
}
}
}

//--------------------------------------------------------------------------------------------------
// Tests
//--------------------------------------------------------------------------------------------------
Expand Down
2 changes: 0 additions & 2 deletions crates/fs/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ mod error;
mod link;
mod metadata;
mod pathnodes;
mod referenceable;
pub mod utils;

pub use async_serialize::*;
Expand All @@ -15,7 +14,6 @@ pub use error::*;
pub use link::*;
pub use metadata::*;
pub use pathnodes::*;
pub use referenceable::*;

//--------------------------------------------------------------------------------------------------
// Type Definitions
Expand Down
Loading

0 comments on commit 0228c17

Please sign in to comment.