Skip to content

Commit

Permalink
Merge ce51d79 into e1fdb55
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbepop committed Mar 29, 2020
2 parents e1fdb55 + ce51d79 commit 3fc5896
Show file tree
Hide file tree
Showing 31 changed files with 5,822 additions and 0 deletions.
3 changes: 3 additions & 0 deletions core/Cargo.toml
Expand Up @@ -26,6 +26,9 @@ derive_more = { version = "0.99", default-features = false, features = ["from",
smallvec = { version = "1.2", default-features = false, features = ["union"] }
cfg-if = "0.1"
num-traits = { version = "0.2", default-features = false, features = ["i128"] }
array-init = "0.1"
typenum = { version = "1.11", features = ["i128"] }
generic-array = "0.13"
paste = "0.1"

# Hashes for the off-chain environment.
Expand Down
2 changes: 2 additions & 0 deletions core/src/lib.rs
Expand Up @@ -21,6 +21,7 @@
//! emulator for simple off-chain testing.

#![cfg_attr(not(feature = "std"), no_std)]
#![feature(const_fn)]
#![deny(
bad_style,
const_err,
Expand Down Expand Up @@ -49,6 +50,7 @@ extern crate ink_alloc;
pub mod env;
pub mod hash;
pub mod storage;
pub mod storage2;

// Needed for derive macros of `core/derive` sub crate.
pub(crate) use crate as ink_core;
92 changes: 92 additions & 0 deletions core/src/storage2/collections/boxed/mod.rs
@@ -0,0 +1,92 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

mod traits;

use crate::storage2::{
ClearForward,
Lazy,
PullForward,
SaturatingStorage,
StorageFootprint,
};
use ink_primitives::Key;

/// Allocates a new storage key for the given `T` dynamically on the storage.
fn allocate_dynamically<T>() -> Key
where
T: StorageFootprint,
{
// TODO: Actual implementation is still missing!
Key([0x42; 32])
}

/// An indirection to some dynamically allocated storage entity.
pub struct Box<T>
where
T: ClearForward + SaturatingStorage,
{
/// The storage area where the boxed storage entity is stored.
key: Key,
/// The cache for the boxed storage entity.
value: Lazy<T>,
}

impl<T> Box<T>
where
T: ClearForward + StorageFootprint + SaturatingStorage,
{
/// Creates a new boxed entity.
pub fn new(value: T) -> Self {
Self {
key: allocate_dynamically::<T>(),
value: Lazy::new(value),
}
}
}

impl<T> Box<T>
where
T: ClearForward + StorageFootprint + PullForward + SaturatingStorage,
{
/// Returns a shared reference to the boxed value.
///
/// # Note
///
/// This loads the value from the pointed to contract storage
/// if this did not happed before.
///
/// # Panics
///
/// If loading from contract storage failed.
#[must_use]
pub fn get(&self) -> &T {
self.value.get()
}

/// Returns an exclusive reference to the boxed value.
///
/// # Note
///
/// This loads the value from the pointed to contract storage
/// if this did not happed before.
///
/// # Panics
///
/// If loading from contract storage failed.
#[must_use]
pub fn get_mut(&mut self) -> &mut T {
self.value.get_mut()
}
}
217 changes: 217 additions & 0 deletions core/src/storage2/collections/boxed/traits.rs
@@ -0,0 +1,217 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use super::Box as StorageBox;
use crate::{
storage2 as storage,
storage2::{
ClearForward,
KeyPtr,
PullForward,
PushForward,
SaturatingStorage,
StorageFootprint,
},
};
use ink_primitives::Key;

impl<T> StorageFootprint for StorageBox<T>
where
T: ClearForward + SaturatingStorage,
{
/// A boxed entity always uses exactly 1 cell for its storage.
///
/// The indirectly stored storage entity is not considered because the
/// `StorageSize` is only concerned with inplace storage usage.
type Value = typenum::U1;
}

impl<T> SaturatingStorage for StorageBox<T>
where
T: ClearForward + SaturatingStorage,
{
// A boxed entity always uses exactly 1 cell for its storage.
//
// Therefore the associated storage region is always saturated.
}

impl<T> PullForward for StorageBox<T>
where
T: ClearForward + SaturatingStorage,
{
fn pull_forward(ptr: &mut KeyPtr) -> Self {
let key = <Key as PullForward>::pull_forward(ptr);
Self {
key,
value: storage::Lazy::lazy(key),
}
}
}

impl<T> PushForward for StorageBox<T>
where
T: ClearForward + SaturatingStorage,
storage::Lazy<T>: PushForward,
{
fn push_forward(&self, ptr: &mut KeyPtr) {
PushForward::push_forward(&self.key, ptr);
PushForward::push_forward(&self.value, &mut KeyPtr::from(self.key));
}
}

impl<T> ClearForward for StorageBox<T>
where
T: ClearForward + SaturatingStorage,
storage::Lazy<T>: ClearForward,
{
fn clear_forward(&self, ptr: &mut KeyPtr) {
ClearForward::clear_forward(&self.key, ptr);
ClearForward::clear_forward(&self.value, &mut KeyPtr::from(self.key));
}
}

impl<T> Drop for StorageBox<T>
where
T: ClearForward + SaturatingStorage,
{
fn drop(&mut self) {
ClearForward::clear_forward(&self.value, &mut KeyPtr::from(self.key));
}
}

impl<T> core::cmp::PartialEq for StorageBox<T>
where
T: PartialEq + ClearForward + StorageFootprint + PullForward + SaturatingStorage,
{
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(self.get(), other.get())
}
}

impl<T> core::cmp::Eq for StorageBox<T> where
T: Eq + ClearForward + StorageFootprint + PullForward + SaturatingStorage
{
}

impl<T> core::cmp::PartialOrd for StorageBox<T>
where
T: PartialOrd + ClearForward + StorageFootprint + PullForward + SaturatingStorage,
{
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
PartialOrd::partial_cmp(self.get(), other.get())
}
fn lt(&self, other: &Self) -> bool {
PartialOrd::lt(self.get(), other.get())
}
fn le(&self, other: &Self) -> bool {
PartialOrd::le(self.get(), other.get())
}
fn ge(&self, other: &Self) -> bool {
PartialOrd::ge(self.get(), other.get())
}
fn gt(&self, other: &Self) -> bool {
PartialOrd::gt(self.get(), other.get())
}
}

impl<T> core::cmp::Ord for StorageBox<T>
where
T: core::cmp::Ord + ClearForward + StorageFootprint + PullForward + SaturatingStorage,
{
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
Ord::cmp(self.get(), other.get())
}
}

impl<T> core::fmt::Display for StorageBox<T>
where
T: core::fmt::Display
+ ClearForward
+ StorageFootprint
+ PullForward
+ SaturatingStorage,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
core::fmt::Display::fmt(self.get(), f)
}
}

impl<T> core::hash::Hash for StorageBox<T>
where
T: core::hash::Hash
+ ClearForward
+ StorageFootprint
+ PullForward
+ SaturatingStorage,
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.get().hash(state);
}
}

impl<T> core::convert::AsRef<T> for StorageBox<T>
where
T: StorageFootprint + ClearForward + PullForward + SaturatingStorage,
{
fn as_ref(&self) -> &T {
self.get()
}
}

impl<T> core::convert::AsMut<T> for StorageBox<T>
where
T: StorageFootprint + ClearForward + PullForward + SaturatingStorage,
{
fn as_mut(&mut self) -> &mut T {
self.get_mut()
}
}

impl<T> ink_prelude::borrow::Borrow<T> for StorageBox<T>
where
T: StorageFootprint + ClearForward + PullForward + SaturatingStorage,
{
fn borrow(&self) -> &T {
self.get()
}
}

impl<T> ink_prelude::borrow::BorrowMut<T> for StorageBox<T>
where
T: StorageFootprint + ClearForward + PullForward + SaturatingStorage,
{
fn borrow_mut(&mut self) -> &mut T {
self.get_mut()
}
}

impl<T> core::ops::Deref for StorageBox<T>
where
T: StorageFootprint + ClearForward + PullForward + SaturatingStorage,
{
type Target = T;

fn deref(&self) -> &Self::Target {
self.get()
}
}

impl<T> core::ops::DerefMut for StorageBox<T>
where
T: StorageFootprint + ClearForward + PullForward + SaturatingStorage,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.get_mut()
}
}
38 changes: 38 additions & 0 deletions core/src/storage2/collections/mod.rs
@@ -0,0 +1,38 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod boxed;
pub mod smallvec;
pub mod vec;
pub mod stash;

/// Extends the lifetime 'a to the outliving lifetime 'b for the given reference.
///
/// # Note
///
/// This interface is a bit more constraint than a simple
/// [transmut](`core::mem::transmute`) and therefore preferred
/// for extending lifetimes only.
///
/// # Safety
///
/// This function is `unsafe` because lifetimes can be extended beyond the
/// lifetimes of the objects they are referencing and thus potentially create
/// dangling references if not used carefully.
pub(crate) unsafe fn extend_lifetime<'a, 'b: 'a, T>(reference: &'a mut T) -> &'b mut T {
#[allow(unused_unsafe)]
unsafe {
core::mem::transmute::<&'a mut T, &'b mut T>(reference)
}
}

0 comments on commit 3fc5896

Please sign in to comment.