allow storage value build to put no value (#4319)

This commit is contained in:
thiolliere
2019-12-07 15:30:57 +01:00
committed by Gavin Wood
parent cbd85e65b6
commit b8ac094649
2 changed files with 75 additions and 10 deletions
@@ -44,32 +44,55 @@ impl BuilderDef {
let storage_trait = &line.storage_trait;
let value_type = &line.value_type;
// Contains the data to inset at genesis either from build or config.
// Defines the data variable to use for insert at genesis either from build or config.
let mut data = None;
if let Some(builder) = &line.build {
is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic);
is_generic |= line.is_generic;
data = Some(quote_spanned!(builder.span() => &(#builder)(self)));
data = Some(match &line.storage_type {
StorageLineTypeDef::Simple(_) if line.is_option =>
quote_spanned!(builder.span() =>
let data = (#builder)(self);
let data = Option::as_ref(&data);
),
_ => quote_spanned!(builder.span() => let data = &(#builder)(self); ),
});
} else if let Some(config) = &line.config {
is_generic |= line.is_generic;
data = Some(quote!(&self.#config;));
data = Some(match &line.storage_type {
StorageLineTypeDef::Simple(_) if line.is_option =>
quote!( let data = Some(&self.#config); ),
_ => quote!( let data = &self.#config; ),
});
};
if let Some(data) = data {
blocks.push(match &line.storage_type {
StorageLineTypeDef::Simple(_) => {
StorageLineTypeDef::Simple(_) if line.is_option => {
quote!{{
let v: &#value_type = #data;
#data
let v: Option<&#value_type>= data;
if let Some(v) = v {
<#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v);
}
}}
},
StorageLineTypeDef::Simple(_) if !line.is_option => {
quote!{{
#data
let v: &#value_type = data;
<#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v);
}}
},
StorageLineTypeDef::Simple(_) => unreachable!(),
StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => {
let key = &map.key;
quote!{{
let data: &#scrate::rstd::vec::Vec<(#key, #value_type)> = #data;
#data
let data: &#scrate::rstd::vec::Vec<(#key, #value_type)> = data;
data.iter().for_each(|(k, v)| {
<#storage_struct as #scrate::#storage_trait>::insert::<
&#key, &#value_type
@@ -81,7 +104,8 @@ impl BuilderDef {
let key1 = &map.key1;
let key2 = &map.key2;
quote!{{
let data: &#scrate::rstd::vec::Vec<(#key1, #key2, #value_type)> = #data;
#data
let data: &#scrate::rstd::vec::Vec<(#key1, #key2, #value_type)> = data;
data.iter().for_each(|(k1, k2, v)| {
<#storage_struct as #scrate::#storage_trait>::insert::<
&#key1, &#key2, &#value_type
@@ -19,6 +19,7 @@
#[allow(dead_code)]
mod tests {
use support::metadata::*;
use runtime_io::TestExternalities;
use std::marker::PhantomData;
use codec::{Encode, Decode, EncodeLike};
@@ -44,7 +45,7 @@ mod tests {
// getters: pub / $default
// we need at least one type which uses T, otherwise GenesisConfig will complain.
GETU32 get(fn u32_getter): T::Origin;
pub PUBGETU32 get(fn pub_u32_getter) build(|config: &GenesisConfig| config.u32_getter_with_config): u32;
pub PUBGETU32 get(fn pub_u32_getter): u32;
GETU32WITHCONFIG get(fn u32_getter_with_config) config(): u32;
pub PUBGETU32WITHCONFIG get(fn pub_u32_getter_with_config) config(): u32;
GETU32MYDEF get(fn u32_getter_mydef): Option<u32>;
@@ -53,6 +54,10 @@ mod tests {
pub PUBGETU32WITHCONFIGMYDEF get(fn pub_u32_getter_with_config_mydef) config(): u32 = 1;
PUBGETU32WITHCONFIGMYDEFOPT get(fn pub_u32_getter_with_config_mydef_opt) config(): Option<u32>;
GetU32WithBuilder get(fn u32_with_builder) build(|_| 1): u32;
GetOptU32WithBuilderSome get(fn opt_u32_with_builder_some) build(|_| Some(1)): Option<u32>;
GetOptU32WithBuilderNone get(fn opt_u32_with_builder_none) build(|_| None): Option<u32>;
// map non-getters: pub / $default
MAPU32 : map u32 => Option<String>;
pub PUBMAPU32 : map u32 => Option<String>;
@@ -209,7 +214,33 @@ mod tests {
),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GetU32WithBuilder"),
modifier: StorageEntryModifier::Default,
ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructGetU32WithBuilder(PhantomData::<TraitImpl>))
),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GetOptU32WithBuilderSome"),
modifier: StorageEntryModifier::Optional,
ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructGetOptU32WithBuilderSome(PhantomData::<TraitImpl>))
),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("GetOptU32WithBuilderNone"),
modifier: StorageEntryModifier::Optional,
ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")),
default: DecodeDifferent::Encode(
DefaultByteGetter(&__GetByteStructGetOptU32WithBuilderNone(PhantomData::<TraitImpl>))
),
documentation: DecodeDifferent::Encode(&[]),
},
StorageEntryMetadata {
name: DecodeDifferent::Encode("MAPU32"),
modifier: StorageEntryModifier::Optional,
@@ -412,7 +443,7 @@ mod tests {
#[test]
fn store_metadata() {
let metadata = Module::<TraitImpl>::storage_metadata();
assert_eq!(EXPECTED_METADATA, metadata);
pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata);
}
#[test]
@@ -427,6 +458,16 @@ mod tests {
assert_eq!(config.pub_u32_getter_with_config_mydef_opt, 0u32);
}
#[test]
fn check_builder_config() {
let config = GenesisConfig::default();
let storage = config.build_storage().unwrap();
TestExternalities::from(storage).execute_with(|| {
assert_eq!(Module::<TraitImpl>::u32_with_builder(), 1);
assert_eq!(Module::<TraitImpl>::opt_u32_with_builder_some(), Some(1));
assert_eq!(Module::<TraitImpl>::opt_u32_with_builder_none(), None);
})
}
}
#[cfg(test)]