Skip to content

Commit

Permalink
Simplify storage traits with std::borrow::Cow (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
vlopes11 authored and xgreenx committed Dec 20, 2022
1 parent fa8cf73 commit bfc8bdf
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 45 deletions.
2 changes: 1 addition & 1 deletion fuel-types/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The traits `Storage` and `MerkleStorage` will be used as base in fuel-vm to defi

# Features

* `default/std` - Enable `libstd` functionalities.
* `default/std` - Enable `libstd` functionalities with `Storage` and `MerkleStorage`.
* `random` - Enable `std` and create random generator implementations for the provided types.
* `serde-types` - Enable `serde::{serialize, deserialize}` for the provided types
* `serde-types-minimal` - Enable `no-std` `serde::{serialize, deserialize}` for the provided types
75 changes: 33 additions & 42 deletions fuel-types/src/data.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
use crate::*;
use core::borrow::Borrow;
use core::fmt::Display;
use core::ops::DerefMut;

use std::borrow::Cow;
use std::error::Error;
use std::ops::{Deref, DerefMut};

/// Base map trait for Fuel infrastructure
///
/// Generics:
///
/// - K: Key that maps to a value
/// - V: Stored value
/// - R: Wrapper type that borrows V. V can be used as blanket implementation `Borrow<V> for V`
/// - E: Error type that implements Display
pub trait Storage<K, V, R, E>
pub trait Storage<K, V, E>
where
R: Borrow<V>,
E: Display,
V: Clone,
E: Error,
{
/// Append `K->V` mapping to the storage.
///
Expand All @@ -28,37 +28,33 @@ where
/// `Ok(None)`.
fn remove(&mut self, key: &K) -> Result<Option<V>, E>;

/// Retrieve `R` such as `K->V, R: Borrow<V>`.
///
/// `R` is used instead of `V` to allow reference to inlined values in the storage
/// implementation instead of copying them.
fn get(&self, key: &K) -> Result<Option<R>, E>;
/// Retrieve `Cow<V>` such as `K->V`.
fn get<'a>(&'a self, key: &K) -> Result<Option<Cow<'a, V>>, E>;

/// Return `true` if there is a `K` mapping to a value in the storage.
fn contains_key(&self, key: &K) -> Result<bool, E>;
}

impl<K, V, R, S, I, E> Storage<K, V, R, E> for I
impl<K, V, E, S> Storage<K, V, E> for &mut S
where
R: Borrow<V>,
E: Display,
S: Storage<K, V, R, E>,
I: DerefMut<Target = S>,
V: Clone,
E: Error,
S: Storage<K, V, E>,
{
fn insert(&mut self, key: &K, value: &V) -> Result<Option<V>, E> {
<S as Storage<K, V, R, E>>::insert(self.deref_mut(), key, value)
<S as Storage<K, V, E>>::insert(self.deref_mut(), key, value)
}

fn remove(&mut self, key: &K) -> Result<Option<V>, E> {
<S as Storage<K, V, R, E>>::remove(self.deref_mut(), key)
<S as Storage<K, V, E>>::remove(self.deref_mut(), key)
}

fn get(&self, key: &K) -> Result<Option<R>, E> {
<S as Storage<K, V, R, E>>::get(self.deref(), key)
fn get(&self, key: &K) -> Result<Option<Cow<'_, V>>, E> {
<S as Storage<K, V, E>>::get(self.deref(), key)
}

fn contains_key(&self, key: &K) -> Result<bool, E> {
<S as Storage<K, V, R, E>>::contains_key(self.deref(), key)
<S as Storage<K, V, E>>::contains_key(self.deref(), key)
}
}

Expand All @@ -69,12 +65,11 @@ where
/// - P: Domain of the merkle tree
/// - K: Key that maps to a value
/// - V: Stored value
/// - R: Wrapper type that borrows V. V can be used as blanket implementation `Borrow<V> for V`
/// - E: Error type that implements Display
pub trait MerkleStorage<P, K, V, R, E>
pub trait MerkleStorage<P, K, V, E>
where
R: Borrow<V>,
E: Display,
V: Clone,
E: Error,
{
/// Append `P->K->V` mapping to the storage.
///
Expand All @@ -88,11 +83,8 @@ where
/// `Ok(None)`.
fn remove(&mut self, parent: &P, key: &K) -> Result<Option<V>, E>;

/// Retrieve `R` such as `P->K->V, R: Borrow<V>`.
///
/// `R` is used instead of `V` to allow reference to inlined values in the storage
/// implementation instead of copying them.
fn get(&self, parent: &P, key: &K) -> Result<Option<R>, E>;
/// Retrieve `Cow<V>` such as `P->K->V`.
fn get<'a>(&'a self, parent: &P, key: &K) -> Result<Option<Cow<'a, V>>, E>;

/// Return `true` if there is a `P->K` mapping to a value in the storage.
fn contains_key(&self, parent: &P, key: &K) -> Result<bool, E>;
Expand All @@ -104,30 +96,29 @@ where
fn root(&mut self, parent: &P) -> Result<Bytes32, E>;
}

impl<P, K, V, R, X, I, E> MerkleStorage<P, K, V, R, E> for I
impl<P, K, V, E, S> MerkleStorage<P, K, V, E> for &mut S
where
R: Borrow<V>,
E: Display,
X: MerkleStorage<P, K, V, R, E>,
I: DerefMut<Target = X>,
V: Clone,
E: Error,
S: MerkleStorage<P, K, V, E>,
{
fn insert(&mut self, parent: &P, key: &K, value: &V) -> Result<Option<V>, E> {
<X as MerkleStorage<P, K, V, R, E>>::insert(self.deref_mut(), parent, key, value)
<S as MerkleStorage<P, K, V, E>>::insert(self.deref_mut(), parent, key, value)
}

fn remove(&mut self, parent: &P, key: &K) -> Result<Option<V>, E> {
<X as MerkleStorage<P, K, V, R, E>>::remove(self.deref_mut(), parent, key)
<S as MerkleStorage<P, K, V, E>>::remove(self.deref_mut(), parent, key)
}

fn get(&self, parent: &P, key: &K) -> Result<Option<R>, E> {
<X as MerkleStorage<P, K, V, R, E>>::get(self.deref(), parent, key)
fn get(&self, parent: &P, key: &K) -> Result<Option<Cow<'_, V>>, E> {
<S as MerkleStorage<P, K, V, E>>::get(self.deref(), parent, key)
}

fn contains_key(&self, parent: &P, key: &K) -> Result<bool, E> {
<X as MerkleStorage<P, K, V, R, E>>::contains_key(self.deref(), parent, key)
<S as MerkleStorage<P, K, V, E>>::contains_key(self.deref(), parent, key)
}

fn root(&mut self, parent: &P) -> Result<Bytes32, E> {
<X as MerkleStorage<P, K, V, R, E>>::root(self.deref_mut(), parent)
<S as MerkleStorage<P, K, V, E>>::root(self.deref_mut(), parent)
}
}
8 changes: 6 additions & 2 deletions fuel-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

pub mod bytes;

mod data;
mod types;

pub use data::*;
pub use types::*;

#[cfg(feature = "std")]
mod data;

#[cfg(feature = "std")]
pub use data::*;

/// Register ID type
pub type RegisterId = usize;

Expand Down

0 comments on commit bfc8bdf

Please sign in to comment.