-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(enums): Enums in contract (#212)
* feat(enums): Enums in contract * fix: small fmt --------- Co-authored-by: julio4 <[email protected]>
- Loading branch information
Showing
4 changed files
with
112 additions
and
0 deletions.
There are no files selected for viewing
83 changes: 83 additions & 0 deletions
83
listings/getting-started/cairo_cheatsheet/src/enum_example.cairo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// ANCHOR: enums | ||
#[derive(Drop, Serde, Copy, starknet::Store)] | ||
struct Position { | ||
x: u32, | ||
y: u32, | ||
} | ||
|
||
#[derive(Drop, Serde, Copy, starknet::Store)] | ||
enum UserCommand { | ||
Login, | ||
UpdateProfile, | ||
Logout, | ||
} | ||
|
||
#[derive(Drop, Serde, Copy, starknet::Store)] | ||
enum Action { | ||
Quit, | ||
Move: Position, | ||
SendMessage: felt252, | ||
ChangeAvatarColor: (u8, u8, u8), | ||
ProfileState: UserCommand | ||
} | ||
// ANCHOR_END: enums | ||
|
||
// ANCHOR: enum_contract | ||
#[starknet::interface] | ||
trait IEnumContract<TContractState> { | ||
fn register_action(ref self: TContractState, action: Action); | ||
fn generate_default_actions_list(self: @TContractState) -> Array<Action>; | ||
} | ||
|
||
#[starknet::contract] | ||
mod EnumContract { | ||
use core::clone::Clone; | ||
use core::traits::Into; | ||
use super::IEnumContract; | ||
use super::{Action, Position, UserCommand}; | ||
|
||
#[storage] | ||
struct Storage { | ||
most_recent_action: Action, | ||
} | ||
|
||
#[abi(embed_v0)] | ||
impl IEnumContractImpl of IEnumContract<ContractState> { | ||
fn register_action(ref self: ContractState, action: Action) { | ||
// quick note: match takes ownership of variable (but enum Action implements Copy trait) | ||
match action { | ||
Action::Quit => { println!("Quit"); }, | ||
Action::Move(value) => { println!("Move with x: {} and y: {}", value.x, value.y); }, | ||
Action::SendMessage(msg) => { println!("Write with message: {}", msg); }, | ||
Action::ChangeAvatarColor(( | ||
r, g, b | ||
)) => { println!("Change color to r: {}, g: {}, b: {}", r, g, b); }, | ||
Action::ProfileState(state) => { | ||
let profile_state = match state { | ||
UserCommand::Login => 1, | ||
UserCommand::UpdateProfile => 2, | ||
UserCommand::Logout => 3, | ||
}; | ||
println!("profile_state: {}", profile_state); | ||
} | ||
}; | ||
|
||
self.most_recent_action.write(action); | ||
} | ||
|
||
fn generate_default_actions_list(self: @ContractState) -> Array<Action> { | ||
let actions = array![ | ||
Action::Quit, | ||
Action::Move(Position { x: 1, y: 2 }), | ||
Action::SendMessage('here is my message'), | ||
Action::ChangeAvatarColor((1, 2, 3)), | ||
Action::ProfileState(UserCommand::Login), | ||
]; | ||
|
||
actions | ||
} | ||
} | ||
} | ||
// ANCHOR_END: enum_contract | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Enums | ||
|
||
Just like other programming languages, enums (enumerations) are used in cairo to define variables that can only hold a set of predefined variants (= enum options), enhancing code readability and safety. They facilitate strong type checking and are ideal for organizing related options and supporting structured logic through pattern matching for example, which is also described in the next chapter. | ||
|
||
In cairo, `enum variants` can hold different data types (the unit type, structs, other enums, tuples, default core library types, arrays, dictionaries, ...), as shown in the code snippet below. Furthermore, as a quick reminder, enums are expressions, meaning they can return values. | ||
|
||
```rust | ||
{{#include ../../../listings/getting-started/cairo_cheatsheet/src/enum_example.cairo:enums}} | ||
``` | ||
|
||
Enums can be declared both inside and outside a contract. If declared outside, they need to be imported inside using the `use` keyword, just like other imports. | ||
|
||
1. Storing enums in contract | ||
|
||
- It is possible to store `enums` in the contract storage. But unlike most of the core library types which implement the `Store` trait, enums are custom types and therefore do not automatically implement the `Store` trait. The enum as well as all of its variants have to explicitly implement the `Store` trait in order for it to be stored inside a contract storage. | ||
|
||
- If all of its variants implement the `Store` trait, implementing the `Store` trait on the enum is as simple as deriving it, using `#[derive(starknet::Store)]` (as shown in example above). If not, the `Store` trait has to be manually implemented -- see an example of manually implementing the `Store` trait for a complex type in chapter [Storing Arrays](https://starknet-by-example.voyager.online/ch02/storing_arrays.html). | ||
|
||
2. Enums as parameters and return values to entrypoints | ||
|
||
- It is possible to pass `enums` to contract entrypoints as parameters, as well as return them from entrypoints. For that purpose, the enum needs to be serializable and dropable, hence the derivation of traits `Serde` and `Drop` in the above code snippet. | ||
|
||
Here is an example of a contract illustrating the above statements : | ||
|
||
```rust | ||
{{#include ../../../listings/getting-started/cairo_cheatsheet/src/enum_example.cairo:enum_contract}} | ||
``` |