Rust Programming Basics
Learn Rust fundamentals for Solana development
Rust is the primary programming language for Solana development. Before diving into Solana programs, it's essential to understand Rust fundamentals. This guide covers the core concepts you need to know.
Why Rust?
- Memory safety without garbage collection
- Zero-cost abstractions
- Fearless concurrency
- Performance comparable to C/C++
Getting Started with Rust
Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
rustc --version
Core Concepts
1. Variables and Mutability
Variables in Rust are immutable by default. Use mut for mutable variables.
// Immutable variable
let x = 5;
// Mutable variable
let mut y = 10;
y = 15; // This is allowed
// Constants
const MAX_POINTS: u32 = 100_000;
2. Data Types
Scalar Types:
// Integers: i8, i16, i32, i64, i128, isize
let age: i32 = 30;
// Unsigned integers: u8, u16, u32, u64, u128, usize
let count: u64 = 1000;
// Floating point: f32, f64
let price: f64 = 19.99;
// Boolean
let is_active: bool = true;
// Character
let letter: char = 'A';
Compound Types:
// Tuples
let tup: (i32, f64, bool) = (500, 6.4, true);
let (x, y, z) = tup; // Destructuring
// Arrays
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
let first = numbers[0];
3. Functions
fn main() {
let result = add(5, 10);
println!("Result: {}", result);
}
fn add(x: i32, y: i32) -> i32 {
x + y // No semicolon = return value
}
// Function with multiple returns
fn calculate(x: i32) -> (i32, i32) {
(x * 2, x * 3)
}
4. Control Flow
If/Else:
let number = 7;
if number < 5 {
println!("Less than 5");
} else if number > 5 {
println!("Greater than 5");
} else {
println!("Equal to 5");
}
// If in a let statement
let result = if number > 5 { "big" } else { "small" };
Loops:
// Loop
let mut counter = 0;
loop {
counter += 1;
if counter == 10 {
break;
}
}
// While
let mut number = 3;
while number != 0 {
println!("{number}");
number -= 1;
}
// For
let arr = [10, 20, 30, 40, 50];
for element in arr {
println!("{element}");
}
// Range
for number in 1..4 {
println!("{number}");
}
5. Match Statement
Match is like switch but more powerful:
let number = 7;
match number {
1 => println!("One"),
2 | 3 => println!("Two or Three"),
4..=6 => println!("Four through Six"),
_ => println!("Something else"),
}
// Match with expressions
let result = match number {
1..=5 => "small",
6..=10 => "medium",
_ => "large",
};
Ownership & Borrowing
Ownership Rules
- Each value in Rust has an owner
- There can only be one owner at a time
- When the owner goes out of scope, the value is dropped
let s1 = String::from("hello");
let s2 = s1; // s1 is moved to s2
// println!("{}", s1); // Error! s1 no longer valid
// Use clone to copy
let s3 = String::from("hello");
let s4 = s3.clone();
println!("{} {}", s3, s4); // Works!
References & Borrowing
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1); // Borrow
println!("Length of '{}' is {}", s1, len); // s1 still valid
}
fn calculate_length(s: &String) -> usize {
s.len()
}
// Mutable references
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(s: &mut String) {
s.push_str(", world");
}
Structs & Enums
Structures
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
impl User {
fn new(username: String, email: String) -> User {
User {
username,
email,
sign_in_count: 0,
active: true,
}
}
fn deactivate(&mut self) {
self.active = false;
}
}
fn main() {
let mut user1 = User::new(
String::from("user123"),
String::from("user@example.com")
);
user1.deactivate();
}
Enumerations
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
impl Message {
fn call(&self) {
match self {
Message::Quit => println!("Quit"),
Message::Move { x, y } => println!("Move to {}, {}", x, y),
Message::Write(text) => println!("Write: {}", text),
Message::ChangeColor(r, g, b) => println!("Color: {}, {}, {}", r, g, b),
}
}
}
// Option and Result are built-in enums
let some_number: Option = Some(5);
let absent_number: Option = None;
Error Handling
use std::fs::File;
use std::io::Read;
// Using Result
fn read_file(filename: &str) -> Result {
let mut file = File::open(filename)?; // ? operator
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
fn main() {
match read_file("hello.txt") {
Ok(contents) => println!("{}", contents),
Err(error) => println!("Error: {}", error),
}
}
Modules & Testing
Modules:
mod math {
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
}
fn main() {
let result = math::add(5, 10);
println!("Result: {}", result);
}
Testing:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(math::add(2, 3), 5);
}
#[test]
fn test_multiply() {
assert_eq!(math::multiply(2, 3), 6);
}
}
Learning Resources
Next Steps
Now that you understand Rust basics, you're ready to learn Solana-specific concepts! Continue to Solana Basics to start building blockchain programs.