Rust Snippets
Modern Rust programming patterns and features
Ownership and Borrowing
rustRust's memory safety principles
fn main() {
// Ownership
let s1 = String::from("hello");
let s2 = s1; // s1 is moved to s2
// println!("{}", s1); // Error: s1 is moved
println!("{}", s2); // OK
// Borrowing
let s3 = String::from("world");
print_string(&s3); // Immutable borrow
println!("{}", s3); // OK: s3 is still valid
let mut s4 = String::from("hello");
change_string(&mut s4); // Mutable borrow
println!("{}", s4);
}
fn print_string(s: &String) {
println!("{}", s);
}
fn change_string(s: &mut String) {
s.push_str(", world");
}Traits and Generics
rustRust's approach to polymorphism
// Define a trait
trait Animal {
fn make_sound(&self) -> String;
fn get_name(&self) -> &str;
}
// Implement for specific types
struct Dog {
name: String
}
impl Animal for Dog {
fn make_sound(&self) -> String {
String::from("Woof!")
}
fn get_name(&self) -> &str {
&self.name
}
}
struct Cat {
name: String
}
impl Animal for Cat {
fn make_sound(&self) -> String {
String::from("Meow!")
}
fn get_name(&self) -> &str {
&self.name
}
}
// Generic function using trait bounds
fn animal_sounds<T: Animal>(animal: &T) {
println!("{} says {}",
animal.get_name(),
animal.make_sound()
);
}
fn main() {
let dog = Dog { name: String::from("Rover") };
let cat = Cat { name: String::from("Whiskers") };
animal_sounds(&dog);
animal_sounds(&cat);
}Error Handling
rustResult and Option types
use std::fs::File;
use std::io::{self, Read};
// Using Result for fallible operations
fn read_file(path: &str) -> Result<String, io::Error> {
let mut file = File::open(path)?;
let mut content = String::new();
file.read_to_string(&mut content)?;
Ok(content)
}
// Using Option for nullable values
fn find_user(id: u32) -> Option<User> {
if id == 0 {
None
} else {
Some(User { id })
}
}
fn main() -> Result<(), io::Error> {
// Using ? operator with Result
let content = read_file("example.txt")?;
println!("{}", content);
// Pattern matching with Option
match find_user(1) {
Some(user) => println!("Found user {}", user.id),
None => println!("User not found")
}
// Using combinators
let user_id = find_user(2)
.map(|user| user.id)
.unwrap_or(0);
Ok(())
}Concurrency
rustSafe concurrent programming
use std::thread;
use std::sync::{Arc, Mutex};
// Shared state between threads
fn shared_state() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
// Message passing between threads
use std::sync::mpsc;
fn message_passing() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hello");
tx.send(val).unwrap();
});
let received = rx.recv().unwrap();
println!("Got: {}", received);
}