Unverified Commit 4b5d91a8 authored by Robin Freyler's avatar Robin Freyler Committed by GitHub
Browse files

Add SpreadAllocate and PackedAllocate traits and impls (#978)

* improve docs of PackedLayout methods

* add SpreadAllocate trait

Note: We cannot add allocate_spread to SpreadLayout trait since certain types (such as Result<T, E>) that implement SpreadLayout cannot implement SpreadAllocate; OR certain types can trivially implement SpreadLayout but are constraint with respect to SpreadAllocate and vice versa.

* add PackedAllocate trait

* add utility methods for SpreadAllocate and PackedAllocate traits

* improve macro hygiene of some trait impl code dupe macros

* normalize some import statement

* apply rustfmt

* implement {Spread,Packed}Allocate traits for primitive and prelude types

* implement {Packed,Spread}Allocate for std collections

* implement {Packed,Spread}Allocate for array primitives

* improve Codec impl for ink_storage::Pack<T>

* add {Packed,Spread}Allocate impl for ink_storage::Pack<T>

* add {Packed,Spread}Allocate impl for ink_storage::Memory

* add missing #[inline] annotations to ink_storage::Memory<T>

* implement {Packed,Spread}Allocate for tuple types

* add {Spread,Packed}Allocate impl for lazy storage abstractions

* add some #[inline] annotations

* add SpreadAllocate impl for Lazy<T>

* add SpreadAllocate impl for StorageVec

* add SpreadAllocate impl for StorageStash

* derive Default for Header

* remove unused import

* implement SpreadAllocate for the rest of the ink! storage collections
parent 4534c4a1
Pipeline #163474 failed with stages
in 12 minutes and 50 seconds
......@@ -26,6 +26,7 @@ use crate::{
traits::{
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
},
Lazy,
......@@ -307,6 +308,18 @@ where
}
}
impl<T> SpreadAllocate for ChildrenVec<T>
where
T: SpreadLayout + Ord + PackedLayout,
{
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self {
len: SpreadAllocate::allocate_spread(ptr),
children: SpreadAllocate::allocate_spread(ptr),
}
}
}
/// An iterator over shared references to the elements of the `BinaryHeap`.
#[derive(Debug, Clone, Copy)]
pub struct Iter<'a, T>
......
......@@ -21,6 +21,7 @@ use super::{
use crate::traits::{
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
};
......@@ -98,3 +99,14 @@ where
SpreadLayout::clear_spread(&self.elements, ptr);
}
}
impl<T> SpreadAllocate for BinaryHeap<T>
where
T: PackedLayout + Ord,
{
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self {
elements: SpreadAllocate::allocate_spread(ptr),
}
}
}
......@@ -27,6 +27,7 @@ use crate::{
forward_push_packed,
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
},
};
......@@ -101,3 +102,12 @@ impl SpreadLayout for BitStash {
SpreadLayout::clear_spread(&self.free, ptr);
}
}
impl SpreadAllocate for BitStash {
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self {
counts: SpreadAllocate::allocate_spread(ptr),
free: SpreadAllocate::allocate_spread(ptr),
}
}
}
......@@ -23,6 +23,7 @@ use crate::{
forward_push_packed,
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
},
Pack,
......@@ -98,3 +99,12 @@ impl SpreadLayout for StorageBitvec {
SpreadLayout::clear_spread(&self.bits, ptr);
}
}
impl SpreadAllocate for StorageBitvec {
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self {
len: SpreadAllocate::allocate_spread(ptr),
bits: SpreadAllocate::allocate_spread(ptr),
}
}
}
......@@ -26,6 +26,7 @@ use crate::{
forward_push_packed,
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
},
};
......@@ -137,3 +138,18 @@ where
SpreadLayout::clear_spread(&self.values, ptr);
}
}
impl<K, V, H> SpreadAllocate for StorageHashMap<K, V, H>
where
K: Ord + Clone + PackedLayout,
V: PackedLayout,
H: CryptoHash,
Key: From<<H as HashOutput>::Type>,
{
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self {
keys: SpreadAllocate::allocate_spread(ptr),
values: SpreadAllocate::allocate_spread(ptr),
}
}
}
......@@ -16,6 +16,7 @@ use super::SmallVec;
use crate::traits::{
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
};
......@@ -72,3 +73,15 @@ where
SpreadLayout::clear_spread(&self.elems, ptr);
}
}
impl<T, const N: usize> SpreadAllocate for SmallVec<T, N>
where
T: PackedLayout,
{
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self {
len: SpreadAllocate::allocate_spread(ptr),
elems: SpreadAllocate::allocate_spread(ptr),
}
}
}
......@@ -53,7 +53,7 @@ where
}
/// Stores general commonly required information about the storage stash.
#[derive(Debug, scale::Encode, scale::Decode)]
#[derive(Debug, Default, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
struct Header {
/// The latest vacant index.
......
......@@ -22,11 +22,14 @@ use super::{
use crate::{
lazy::LazyIndexMap,
traits::{
forward_allocate_packed,
forward_clear_packed,
forward_pull_packed,
forward_push_packed,
KeyPtr,
PackedAllocate,
PackedLayout,
SpreadAllocate,
SpreadLayout,
},
};
......@@ -88,12 +91,26 @@ impl SpreadLayout for Header {
}
}
impl SpreadAllocate for Header {
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
forward_allocate_packed::<Self>(ptr)
}
}
impl PackedLayout for Header {
#[inline(always)]
fn pull_packed(&mut self, _at: &Key) {}
#[inline(always)]
fn push_packed(&self, _at: &Key) {}
#[inline(always)]
fn clear_packed(&self, _at: &Key) {}
}
impl PackedAllocate for Header {
#[inline(always)]
fn allocate_packed(&mut self, _at: &Key) {}
}
impl<T> SpreadLayout for Entry<T>
where
T: PackedLayout,
......@@ -161,3 +178,15 @@ where
SpreadLayout::clear_spread(&self.entries, ptr);
}
}
impl<T> SpreadAllocate for StorageStash<T>
where
T: PackedLayout,
{
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self {
header: SpreadAllocate::allocate_spread(ptr),
entries: SpreadAllocate::allocate_spread(ptr),
}
}
}
......@@ -20,6 +20,7 @@ use crate::{
traits::{
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
},
};
......@@ -77,3 +78,15 @@ where
SpreadLayout::clear_spread(&self.elems, ptr);
}
}
impl<T> SpreadAllocate for StorageVec<T>
where
T: PackedLayout,
{
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self {
len: SpreadAllocate::allocate_spread(ptr),
elems: SpreadAllocate::allocate_spread(ptr),
}
}
}
......@@ -31,6 +31,7 @@ pub struct CacheCell<T: ?Sized> {
impl<T> CacheCell<T> {
/// Creates a new cache cell from the given value.
#[inline]
pub fn new(value: T) -> Self {
Self {
inner: UnsafeCell::new(value),
......@@ -54,6 +55,7 @@ where
}
impl<T> From<T> for CacheCell<T> {
#[inline]
fn from(value: T) -> Self {
Self::new(value)
}
......@@ -63,6 +65,7 @@ impl<T> Default for CacheCell<T>
where
T: Default,
{
#[inline]
fn default() -> Self {
Self::new(<T as Default>::default())
}
......@@ -73,6 +76,7 @@ where
T: ?Sized,
{
/// Returns a shared reference to the inner value.
#[inline]
pub fn as_inner(&self) -> &T {
// SAFETY: This is safe since we are returning a shared reference back
// to the caller while this method itself accesses `self` as
......@@ -81,6 +85,7 @@ where
}
/// Returns an exclusive reference to the inner value.
#[inline]
pub fn as_inner_mut(&mut self) -> &mut T {
// SAFETY: This is safe since we are returning the exclusive reference
// of the inner value through the `get_mut` API which itself
......@@ -90,6 +95,7 @@ where
}
/// Returns a mutable pointer to the inner value.
#[inline]
pub fn get_ptr(&self) -> NonNull<T> {
// SAFETY: The inner `T` of the internal `UnsafeCell` exists and thus
// the pointer that we get returned to it via `UnsafeCell::get`
......
......@@ -21,7 +21,9 @@ use crate::traits::{
push_spread_root_opt,
ExtKeyPtr,
KeyPtr,
PackedAllocate,
PackedLayout,
SpreadAllocate,
SpreadLayout,
};
use core::{
......@@ -100,22 +102,36 @@ where
{
const FOOTPRINT: u64 = <T as SpreadLayout>::FOOTPRINT;
#[inline]
fn pull_spread(ptr: &mut KeyPtr) -> Self {
let root_key = ExtKeyPtr::next_for::<Self>(ptr);
Self::pull_spread_root(root_key)
}
#[inline]
fn push_spread(&self, ptr: &mut KeyPtr) {
let root_key = ExtKeyPtr::next_for::<Self>(ptr);
self.push_spread_root(root_key)
}
#[inline]
fn clear_spread(&self, ptr: &mut KeyPtr) {
let root_key = ExtKeyPtr::next_for::<Self>(ptr);
self.clear_spread_root(root_key)
}
}
impl<T> SpreadAllocate for StorageEntry<T>
where
T: SpreadLayout,
{
#[inline]
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
let root_key = ExtKeyPtr::next_for::<Self>(ptr);
Self::pull_spread_root(root_key)
}
}
impl<T> scale::Encode for StorageEntry<T>
where
T: scale::Encode,
......@@ -173,6 +189,16 @@ where
}
}
impl<T> PackedAllocate for StorageEntry<T>
where
T: PackedAllocate,
{
#[inline]
fn allocate_packed(&mut self, at: &Key) {
PackedAllocate::allocate_packed(&mut self.value, at)
}
}
impl<T> StorageEntry<T>
where
T: SpreadLayout,
......
......@@ -23,6 +23,7 @@ use crate::traits::{
ExtKeyPtr,
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
};
use core::{
......@@ -375,6 +376,7 @@ where
{
const FOOTPRINT: u64 = N as u64;
#[inline]
fn pull_spread(ptr: &mut KeyPtr) -> Self {
Self::lazy(*ExtKeyPtr::next_for::<Self>(ptr))
}
......@@ -399,6 +401,16 @@ where
}
}
impl<T, const N: usize> SpreadAllocate for LazyArray<T, N>
where
T: PackedLayout,
{
#[inline]
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self::lazy(*ExtKeyPtr::next_for::<Self>(ptr))
}
}
impl<T, const N: usize> LazyArray<T, N> {
/// Returns the offset key for the given index if not out of bounds.
pub fn key_at(&self, at: Index) -> Option<Key> {
......
......@@ -22,6 +22,7 @@ use crate::traits::{
pull_spread_root_opt,
ExtKeyPtr,
KeyPtr,
SpreadAllocate,
SpreadLayout,
};
use core::{
......@@ -164,8 +165,7 @@ where
const FOOTPRINT: u64 = <T as SpreadLayout>::FOOTPRINT;
fn pull_spread(ptr: &mut KeyPtr) -> Self {
let root_key = ExtKeyPtr::next_for::<Self>(ptr);
Self::lazy(*root_key)
Self::lazy(*ExtKeyPtr::next_for::<Self>(ptr))
}
fn push_spread(&self, ptr: &mut KeyPtr) {
......@@ -197,6 +197,16 @@ where
}
}
impl<T> SpreadAllocate for LazyCell<T>
where
T: SpreadLayout,
{
#[inline]
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self::lazy(*ExtKeyPtr::next_for::<Self>(ptr))
}
}
// # Developer Note
//
// Implementing PackedLayout for LazyCell is not useful since that would
......
......@@ -25,6 +25,7 @@ use crate::traits::{
ExtKeyPtr,
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
};
use core::{
......@@ -264,6 +265,7 @@ where
{
const FOOTPRINT: u64 = 1;
#[inline]
fn pull_spread(ptr: &mut KeyPtr) -> Self {
Self::lazy(*ExtKeyPtr::next_for::<Self>(ptr))
}
......@@ -285,6 +287,19 @@ where
}
}
impl<K, V, H> SpreadAllocate for LazyHashMap<K, V, H>
where
K: Ord + scale::Encode,
V: PackedLayout,
H: CryptoHash,
Key: From<<H as HashOutput>::Type>,
{
#[inline]
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self::lazy(*ExtKeyPtr::next_for::<Self>(ptr))
}
}
// # Developer Note
//
// Even thought `LazyHashMap` would require storing just a single key a thus
......
......@@ -23,6 +23,7 @@ use crate::traits::{
ExtKeyPtr,
KeyPtr,
PackedLayout,
SpreadAllocate,
SpreadLayout,
};
use core::{
......@@ -242,6 +243,7 @@ where
{
const FOOTPRINT: u64 = 1_u64 << 32;
#[inline]
fn pull_spread(ptr: &mut KeyPtr) -> Self {
Self::lazy(*ExtKeyPtr::next_for::<Self>(ptr))
}
......@@ -264,6 +266,16 @@ where
}
}
impl<V> SpreadAllocate for LazyIndexMap<V>
where
V: PackedLayout,
{
#[inline]
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self::lazy(*ExtKeyPtr::next_for::<Self>(ptr))
}
}
impl<V> LazyIndexMap<V>
where
V: PackedLayout,
......
......@@ -49,6 +49,7 @@ pub use self::{
};
use crate::traits::{
KeyPtr,
SpreadAllocate,
SpreadLayout,
};
use ink_primitives::Key;
......@@ -104,6 +105,17 @@ where
}
}
impl<T> SpreadAllocate for Lazy<T>
where
T: SpreadLayout,
{
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
Self {
cell: <LazyCell<T> as SpreadAllocate>::allocate_spread(ptr),
}
}
}
impl<T> Lazy<T>
where
T: SpreadLayout,
......
......@@ -14,6 +14,7 @@
use crate::traits::{
KeyPtr,
SpreadAllocate,
SpreadLayout,
};
use core::{
......@@ -74,32 +75,50 @@ where
{
const FOOTPRINT: u64 = 0;
#[inline]
fn pull_spread(_ptr: &mut KeyPtr) -> Self {
Default::default()
}
#[inline(always)]
fn push_spread(&self, _ptr: &mut KeyPtr) {}
#[inline(always)]
fn clear_spread(&self, _ptr: &mut KeyPtr) {}
}
impl<T> SpreadAllocate for Memory<T>
where
T: Default,
{
#[inline]
fn allocate_spread(_ptr: &mut KeyPtr) -> Self {
Default::default()
}
}
impl<T> Memory<T> {
/// Creates a new memory instance.
#[inline]
pub fn new(inner: T) -> Self {
Self { inner }
}
/// Returns a shared reference to the inner `T`.
#[inline]
pub fn get(memory: &Self) -> &T {
&memory.inner
}
/// Returns an exclusive reference to the inner `T`.
#[inline]
pub fn get_mut(memory: &mut Self) -> &mut T {
&mut memory.inner
}
}
impl<T> From<T> for Memory<T> {
#[inline]
fn from(inner: T) -> Self {
Self::new(inner)
}
......@@ -109,6 +128,7 @@ impl<T> Default for Memory<T>
where
T: Default,
{
#[inline]
fn default() -> Self {
Self::new(<T as Default>::default())
}
......@@ -126,12 +146,14 @@ where
impl<T> Deref for Memory<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
Self::get(self)
}
}
impl<T> DerefMut for Memory<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
Self::get_mut(self)
}
......@@ -141,6 +163,7 @@ impl<T> AsRef<T> for Memory<T>
where
T: SpreadLayout,
{
#[inline]
fn as_ref(&self) -> &T {
Self::get(self)
}
......@@ -150,6 +173,7 @@ impl<T> convert::AsMut<T> for Memory<T>
where
T: SpreadLayout,
{
#[inline]
fn as_mut(&mut self) -> &mut T {
Self::get_mut(self)
}
......@@ -159,6 +183,7 @@ impl<T> Borrow<T> for Memory<T>
where
T: SpreadLayout,
{
#[inline]
fn borrow(&self) -> &T {
Self::get(self)
}
......@@ -168,6 +193,7 @@ impl<T> BorrowMut<T> for Memory<T>
where
T: SpreadLayout,
{
#[inline]