Now that you understand the ownership model and data types in Rust, it's time to go deeper into how Rust lets us organize, abstract, and structure logic.
In this episode, you’ll learn:
✅ How to define and use structs
✅ How to model data with enums
✅ How to apply pattern matching
✅ How to write functions and traits
✅ How to organize your code with modules
These tools are the foundation for building scalable Solana smart contracts and apps in Rust.
🧱 Part 1: Structs in Rust
A struct
in Rust is used to group related data.
✨ Defining and Instantiating Structs
struct User {
username: String,
age: u8,
}
fn main() {
let user = User {
username: String::from("alice"),
age: 30,
};
println!("User: {} is {} years old", user.username, user.age);
}
✨ Struct with Associated Function
impl User {
fn is_adult(&self) -> bool {
self.age >= 18
}
}
🔀 Part 2: Enums in Rust
Enums allow you to define a type by enumerating possible variants.
✨ Example: Message Enum
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
}
Each variant can carry data or none at all.
✨ Matching Enums
fn process(msg: Message) {
match msg {
Message::Quit => println!("Quit"),
Message::Move { x, y } => println!("Move to ({x}, {y})"),
Message::Write(text) => println!("Write: {text}"),
}
}
Enums are powerful for representing state, commands, or network messages — perfect for smart contracts.
🎭 Part 3: Pattern Matching
match
lets you run code based on pattern logic. It works with enums, primitives, tuples, structs, and more.
✨ Match with Option<T>
fn maybe_double(val: Option<i32>) -> i32 {
match val {
Some(x) => x * 2,
None => 0,
}
}
✨ Match with Structs
let user = User {
username: "Bob".into(),
age: 25,
};
match user {
User { age, .. } if age >= 18 => println!("Adult"),
_ => println!("Minor"),
}
You can destructure values inside match
, if let
, and while let
for expressive flow control.
🧮 Part 4: Functions in Rust
Functions are reusable blocks of code defined using the fn
keyword.
fn greet(name: &str) -> String {
format!("Hello, {name}!")
}
✨ Key Points
- All parameters must have types.
- Return type is defined using
->
. - The last expression (without a
;
) is returned.
fn add(a: i32, b: i32) -> i32 {
a + b
}
🔌 Part 5: Traits in Rust
Traits define shared behavior that types can implement.
✨ Define a Trait
trait Summary {
fn summarize(&self) -> String;
}
✨ Implement for Struct
impl Summary for User {
fn summarize(&self) -> String {
format!("{} ({})", self.username, self.age)
}
}
✨ Use Traits in Functions
fn notify(item: &impl Summary) {
println!("Notification: {}", item.summarize());
}
Traits give Rust powerful polymorphism without runtime overhead.
📦 Part 6: Modules in Rust
Modules let you split your code into organized files and control visibility.
✨ Inline Module
mod greetings {
pub fn hello() {
println!("Hello!");
}
}
fn main() {
greetings::hello();
}
✨ File-based Modules
src/
├── main.rs
└── utils.rs
main.rs
mod utils;
fn main() {
utils::welcome();
}
utils.rs
pub fn welcome() {
println!("Welcome to Rust for Solana!");
}
📚 Summary Table
Concept | Description |
---|---|
struct |
Group related data into one logical unit |
enum |
Represent multiple related variants |
match |
Exhaustive pattern matching for control flow |
fn |
Reusable functions with static typing |
trait |
Define and share behavior across types |
mod |
Organize and encapsulate logic across files |
🧪 Practice Exercises
1. Define a Struct
Create a struct Product
with name
, price
, and stock
. Implement a method is_in_stock()
.
2. Enum Challenge
Create an enum OrderStatus
with Pending
, Shipped
, Delivered
. Match and print their status.
3. Trait Implementation
Define a Displayable
trait with display(&self) -> String
. Implement it for Product
.
4. Module Exercise
Create a math
module with add
, subtract
, multiply
, and divide
functions. Use them in main
.