use crate::{
Packed,
StorageLayout,
};
use ink_metadata::layout::{
ArrayLayout,
Discriminant,
EnumLayout,
FieldLayout,
Layout,
LayoutKey,
LeafLayout,
StructLayout,
};
use ink_prelude::{
boxed::Box,
collections::{
BTreeMap,
BTreeSet,
VecDeque,
},
string::String,
vec::Vec,
};
use ink_primitives::{
AccountId,
Hash,
Key,
};
use scale_info::TypeInfo;
macro_rules! impl_storage_layout_for_primitives {
( $($name:ty),* $(,)? ) => {
$(
impl StorageLayout for $name {
fn layout(key: &Key) -> Layout {
Layout::Leaf(LeafLayout::from_key::<$name>(LayoutKey::from(key)))
}
}
)*
};
}
#[rustfmt::skip]
impl_storage_layout_for_primitives!(
AccountId, Hash, String,
bool, char, (),
u8, u16, u32, u64, u128,
i8, i16, i32, i64, i128,
);
macro_rules! impl_layout_for_tuple {
( $(($frag:ident, $id:literal)),* $(,)? ) => {
const _: () = {
const TUPLE_NAME: &'static str = stringify!(($($frag),*));
impl<$($frag),*> StorageLayout for ($($frag),* ,)
where
$(
$frag: StorageLayout,
)*
{
fn layout(key: &Key) -> Layout {
Layout::Struct(
StructLayout::new(
TUPLE_NAME,
[
$(
FieldLayout::new(
::core::stringify!($id),
<$frag as StorageLayout>::layout(key)
),
)*
]
)
)
}
}
};
}
}
impl_layout_for_tuple!((A, 0));
impl_layout_for_tuple!((A, 0), (B, 1));
impl_layout_for_tuple!((A, 0), (B, 1), (C, 2));
impl_layout_for_tuple!((A, 0), (B, 1), (C, 2), (D, 3));
impl_layout_for_tuple!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4));
impl_layout_for_tuple!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5));
impl_layout_for_tuple!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5), (G, 6));
impl_layout_for_tuple!(
(A, 0),
(B, 1),
(C, 2),
(D, 3),
(E, 4),
(F, 5),
(G, 6),
(H, 7)
);
impl_layout_for_tuple!(
(A, 0),
(B, 1),
(C, 2),
(D, 3),
(E, 4),
(F, 5),
(G, 6),
(H, 7),
(I, 8)
);
impl_layout_for_tuple!(
(A, 0),
(B, 1),
(C, 2),
(D, 3),
(E, 4),
(F, 5),
(G, 6),
(H, 7),
(I, 8),
(J, 9)
);
impl<T, const N: usize> StorageLayout for [T; N]
where
T: StorageLayout + Packed,
{
fn layout(key: &Key) -> Layout {
let len: u32 = N as u32;
Layout::Array(ArrayLayout::new(
LayoutKey::from(key),
len,
<T as StorageLayout>::layout(key),
))
}
}
impl<T> StorageLayout for Box<T>
where
T: StorageLayout,
{
fn layout(key: &Key) -> Layout {
<T as StorageLayout>::layout(key)
}
}
impl<T> StorageLayout for Option<T>
where
T: StorageLayout,
{
fn layout(key: &Key) -> Layout {
Layout::Enum(EnumLayout::new(
"Option",
key,
[
(Discriminant::from(0), StructLayout::new("None", Vec::new())),
(
Discriminant::from(1),
StructLayout::new(
"Some",
[FieldLayout::new("0", <T as StorageLayout>::layout(key))],
),
),
],
))
}
}
impl<T, E> StorageLayout for Result<T, E>
where
T: StorageLayout,
E: StorageLayout,
{
fn layout(key: &Key) -> Layout {
Layout::Enum(EnumLayout::new(
"Result",
*key,
[
(
Discriminant::from(0),
StructLayout::new(
"Ok",
[FieldLayout::new("0", <T as StorageLayout>::layout(key))],
),
),
(
Discriminant::from(1),
StructLayout::new(
"Err",
[FieldLayout::new("1", <E as StorageLayout>::layout(key))],
),
),
],
))
}
}
impl<T> StorageLayout for Vec<T>
where
T: TypeInfo + 'static + Packed,
{
fn layout(key: &Key) -> Layout {
Layout::Leaf(LeafLayout::from_key::<Self>(LayoutKey::from(key)))
}
}
impl<K, V> StorageLayout for BTreeMap<K, V>
where
K: TypeInfo + 'static + Packed,
V: TypeInfo + 'static + Packed,
{
fn layout(key: &Key) -> Layout {
Layout::Leaf(LeafLayout::from_key::<Self>(LayoutKey::from(key)))
}
}
impl<T> StorageLayout for BTreeSet<T>
where
T: TypeInfo + 'static + Packed,
{
fn layout(key: &Key) -> Layout {
Layout::Leaf(LeafLayout::from_key::<Self>(LayoutKey::from(key)))
}
}
impl<T> StorageLayout for VecDeque<T>
where
T: TypeInfo + 'static + Packed,
{
fn layout(key: &Key) -> Layout {
Layout::Leaf(LeafLayout::from_key::<Self>(LayoutKey::from(key)))
}
}