Skip to content

Commit

Permalink
[storage] Allow one variant enum to derive SpreadLayout (#942)
Browse files Browse the repository at this point in the history
* [storage] Allow one variant enum to derive SpreadLayout

I have an enum that has only one variant, and I want to store the enum value in the storage. I might add new variants later in development, so the enum is not useless.

The current implementation doesn't allow to derive the `SpreadLayout` trait for one variant enums, and I fixed it on this PR.

# Sample code

```rust
#![cfg_attr(not(feature = "std"), no_std)]

use ink_lang as ink;

#[derive(
    Copy,
    Clone,
    scale::Encode,
    scale::Decode,
    ink_storage::traits::SpreadLayout,
    ink_storage::traits::PackedLayout,
)]
#[cfg_attr(
    feature = "std",
    derive(scale_info::TypeInfo, ink_storage::traits::StorageLayout)
)]
pub enum MyEnum {
    A,
}

#[ink::contract]
mod enum_test {
    use super::MyEnum;

    #[ink(storage)]
    pub struct EnumTest {
        value: MyEnum,
    }

    impl EnumTest {
        #[ink(constructor)]
        pub fn new() -> Self {
            Self { value: MyEnum::A }
        }

        #[ink(message)]
        pub fn get(&self) -> MyEnum {
            self.value
        }
    }
}
```

Without this change, I get this error.

```
$ cargo +nightly contract build
 [1/5] Building cargo project
    Updating crates.io index
   Compiling enum_test v0.1.0 (/private/var/folders/zn/l2f569z56vnghtt524x1mv6w0000gn/T/cargo-contract_FM50JF)
error: proc-macro derive panicked
  --> /snip/enum_test/lib.rs:10:5
   |
10 |     ink_storage::traits::SpreadLayout,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: message: can only operate on enums
```

* Update crates/storage/derive/src/spread_layout.rs

Co-authored-by: Robin Freyler <robbepop@web.de>

* cargo fmt

Co-authored-by: Robin Freyler <robbepop@web.de>
  • Loading branch information
2 people authored and ascjones committed Oct 1, 2021
1 parent c18b1a4 commit 51372f2
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
5 changes: 4 additions & 1 deletion crates/storage/derive/src/spread_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@ fn spread_layout_struct_derive(s: &synstructure::Structure) -> TokenStream2 {

/// `SpreadLayout` derive implementation for `enum` types.
fn spread_layout_enum_derive(s: &synstructure::Structure) -> TokenStream2 {
assert!(s.variants().len() >= 2, "can only operate on enums");
assert!(
!s.variants().is_empty(),
"encountered invalid empty enum type deriving SpreadLayout trait"
);
let footprint_body = footprint(s);
let requires_deep_clean_up_body = requires_deep_clean_up(s);
let pull_body = s
Expand Down
48 changes: 48 additions & 0 deletions crates/storage/derive/src/tests/spread_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,54 @@ fn struct_works() {
}
}

#[test]
fn one_variant_enum_works() {
synstructure::test_derive! {
spread_layout_derive {
enum OneVariantEnum {
A,
}
}
expands to {
const _: () = {
impl ::ink_storage::traits::SpreadLayout for OneVariantEnum {
#[allow(unused_comparisons)]
const FOOTPRINT : ::core::primitive::u64 = 1 + [0u64, 0u64][(0u64 < 0u64) as ::core::primitive::usize];

const REQUIRES_DEEP_CLEAN_UP : ::core::primitive::bool = (false || false);

fn pull_spread(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> Self {
match <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::pull_spread(__key_ptr)
{
0u8 => OneVariantEnum::A,
_ => unreachable!("encountered invalid enum discriminant"),
}
}

fn push_spread(&self, __key_ptr: &mut ::ink_storage::traits::KeyPtr) {
match self {
OneVariantEnum::A => {
{
<::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::push_spread(
&0u8,
__key_ptr
);
}
}
}
}

fn clear_spread(&self, __key_ptr: &mut ::ink_storage::traits::KeyPtr) {
match self {
OneVariantEnum::A => {}
}
}
}
};
}
}
}

#[test]
fn enum_works() {
synstructure::test_derive! {
Expand Down

0 comments on commit 51372f2

Please sign in to comment.