Ejemplos Rust

Ejemplos de código Rust esenciales featuring ownership, concurrencia, y programación de sistemas

💻 Hola Mundo Rust rust

🟢 simple ⭐⭐

Programa Hola Mundo básico y sintaxis fundamental con conceptos de ownership

⏱️ 15 min 🏷️ rust, systems programming, ownership
Prerequisites: Basic programming concepts
// Rust Hello World Examples

// 1. Basic Hello World
fn main() {
    println!("Hello, World!");
}

// 2. Hello World with variable binding
fn main() {
    let message = "Hello, World!";
    println!("{}", message);
}

// 3. Hello World with function
fn say_hello() -> &'static str {
    "Hello, World!"
}

fn main() {
    println!("{}", say_hello());
}

// 4. Hello World with ownership demonstration
fn main() {
    let s1 = String::from("Hello");
    let s2 = s1; // s1 is moved to s2
    // println!("{}", s1); // This would cause a compile error
    println!("{} World!", s2);
}

// 5. Hello World with borrowing
fn main() {
    let s1 = String::from("Hello");
    let len = calculate_length(&s1); // borrow s1
    println!("Length of '{}' is {}.", s1, len); // s1 is still valid
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

// 6. Hello World with mutable borrowing
fn main() {
    let mut s = String::from("Hello");
    change(&mut s);
    println!("{}", s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", World!");
}

// 7. Hello World with struct
struct Greeting {
    message: String,
}

impl Greeting {
    fn new(message: &str) -> Greeting {
        Greeting {
            message: message.to_string(),
        }
    }

    fn display(&self) {
        println!("{}", self.message);
    }
}

fn main() {
    let greeting = Greeting::new("Hello, World!");
    greeting.display();
}

// 8. Hello World with enum
enum Status {
    Connected,
    Disconnected,
}

fn main() {
    let status = Status::Connected;
    match status {
        Status::Connected => println!("Hello, Connected World!"),
        Status::Disconnected => println!("Goodbye, World!"),
    }
}

// 9. Hello World with error handling
use std::fs::File;

fn main() {
    match File::open("hello.txt") {
        Ok(_file) => println!("Hello, File World!"),
        Err(_error) => println!("Hello, Error World!"),
    }
}

// 10. Hello World with vectors and iteration
fn main() {
    let greetings = vec!["Hello", "Bonjour", "Hola", "Ciao"];

    for greeting in greetings {
        println!("{}, World!", greeting);
    }
}

// Basic data types
fn main() {
    // Scalar types
    let integer: i32 = 42;
    let float: f64 = 3.14;
    let boolean: bool = true;
    let character: char = '🦀';

    // Compound types
    let tuple: (i32, f64, bool) = (42, 3.14, true);
    let array: [i32; 5] = [1, 2, 3, 4, 5];

    println!("Integer: {}, Float: {}, Boolean: {}, Char: {}", integer, float, boolean, character);
    println!("Tuple: {:?}", tuple);
    println!("Array: {:?}", array);
}

// Control flow
fn main() {
    let number = 42;

    if number > 0 {
        println!("Positive number");
    } else {
        println!("Non-positive number");
    }

    // Match statement
    match number {
        0 => println!("Zero"),
        1..=9 => println!("Single digit"),
        _ => println!("Multiple digits"),
    }

    // Loops
    for i in 0..5 {
        println!("Iteration {}", i);
    }
}

💻 Patrones de Ownership Rust rust

🟡 intermediate ⭐⭐⭐

Conceptos avanzados de ownership, borrowing, y manejo de lifetimes

⏱️ 25 min 🏷️ rust, ownership, borrowing, memory management
Prerequisites: Basic Rust syntax, Memory concepts
// Rust Ownership Patterns Examples

// 1. Move semantics with vectors
fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec1; // vec1 is moved to vec2

    // println!("{:?}", vec1); // Error: value borrowed here after move
    println!("{:?}", vec2); // This works
}

// 2. Clone to create deep copy
fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec1.clone(); // Explicit cloning

    println!("{:?}", vec1); // This works
    println!("{:?}", vec2); // This also works
}

// 3. Copy types
fn main() {
    let x = 5;
    let y = x; // x is copied, not moved

    println!("x = {}, y = {}", x, y); // Both work
}

// 4. Borrowing with functions
fn take_ownership(some_string: String) {
    println!("I own: {}", some_string);
} // some_string goes out of scope and is dropped

fn borrow_string(some_string: &String) {
    println!("I'm borrowing: {}", some_string);
} // some_string is not dropped

fn main() {
    let s1 = String::from("hello");
    take_ownership(s1); // s1 is moved
    // println!("{}", s1); // Error: s1 was moved

    let s2 = String::from("world");
    borrow_string(&s2); // s2 is borrowed
    println!("{}", s2); // s2 is still valid
}

// 5. Mutable borrowing
fn change_string(some_string: &mut String) {
    some_string.push_str(" and more");
}

fn main() {
    let mut s = String::from("hello");
    change_string(&mut s);
    println!("{}", s);
}

// 6. Multiple immutable borrows
fn main() {
    let s = String::from("hello");

    let r1 = &s; // OK
    let r2 = &s; // OK
    let r3 = &s; // OK

    println!("{}, {}, {}", r1, r2, r3);
}

// 7. Dangling references (prevented by compiler)
// fn dangle() -> &String { // This would not compile
//     let s = String::from("hello");
//     &s // s goes out of scope, dangling reference
// }

fn no_dangle() -> String { // This works
    let s = String::from("hello");
    s // ownership is moved out
}

// 8. Struct lifetimes
struct ImportantExcerpt<'a> {
    part: &'a str,
}

impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        3
    }

    fn announce_and_return_part<'a>(&self, announcement: &str) -> &'a str {
        println!("Attention please: {}", announcement);
        self.part
    }
}

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");

    let i = ImportantExcerpt {
        part: first_sentence,
    };

    println!("Level: {}", i.level());
}

// 9. Slices
fn main() {
    let s = String::from("hello world");

    let hello = &s[0..5];
    let world = &s[6..11];

    println!("first word: {}, second word: {}", hello, world);

    let word = first_word(&s);
    println!("first word: {}", word);
}

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}

// 10. Smart pointers - Box<T>
fn main() {
    let b = Box::new(5);
    println!("b = {}", b);
}

#[derive(Debug)]
enum List {
    Cons(i32, Box<List>),
    Nil,
}

use List::{Cons, Nil};

fn main() {
    let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
    println!("{:?}", list);
}

💻 Patrones de Concurrencia Rust rust

🔴 complex ⭐⭐⭐⭐

Programación concurrente moderna con threads, async/await, y channels

⏱️ 30 min 🏷️ rust, concurrency, multithreading, async
Prerequisites: Rust ownership, Basic threading concepts
// Rust Concurrency Examples

use std::thread;
use std::sync::{Arc, Mutex};
use std::time::Duration;

// 1. Basic thread creation
fn main() {
    thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}

// 2. Joining threads
fn main() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }

    handle.join().unwrap();
}

// 3. Using move closures with threads
fn main() {
    let v = vec![1, 2, 3];

    let handle = thread::spawn(move || {
        println!("Here's a vector: {:?}", v);
    });

    handle.join().unwrap();
}

// 4. Shared state with Arc<Mutex<T>>
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    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());
}

// 5. Channels for message passing
use std::sync::mpsc;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("hi");
        tx.send(val).unwrap();
        println!("Sent: {}", val);
    });

    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}

// 6. Multiple producers
fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];

        for val in vals {
            tx.send(val).unwrap();
        }
    });

    for received in rx {
        println!("Got: {}", received);
    }
}

// 7. Async/Await with Tokio (requires tokio crate)
// Add to Cargo.toml: tokio = { version = "1", features = ["full"] }

/*
use tokio;

async fn hello_world() {
    println!("Hello, async world!");
}

#[tokio::main]
async fn main() {
    hello_world().await;
}
*/

// 8. Concurrent HTTP requests with async (requires reqwest and tokio)
/*
use reqwest;
use tokio;

async fn fetch_url(url: &str) -> Result<String, Box<dyn std::error::Error>> {
    let response = reqwest::get(url).await?;
    let body = response.text().await?;
    Ok(body)
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let urls = vec![
        "https://api.example.com/users",
        "https://api.example.com/posts",
        "https://api.example.com/comments",
    ];

    let mut handles = vec![];

    for url in urls {
        let handle = tokio::spawn(async move {
            fetch_url(url).await
        });
        handles.push(handle);
    }

    for handle in handles {
        let result = handle.await??;
        println!("Response length: {}", result.len());
    }

    Ok(())
}
*/

// 9. Barrier for thread synchronization
use std::sync::Barrier;
use std::thread;

fn main() {
    let mut handles = vec![];
    let barrier = Arc::new(Barrier::new(5));

    for i in 0..5 {
        let c = Arc::clone(&barrier);
        let handle = thread::spawn(move || {
            println!("before barrier in thread {}", i);
            c.wait();
            println!("after barrier in thread {}", i);
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }
}

// 10. Atomic operations
use std::sync::atomic::{AtomicUsize, Ordering};

fn main() {
    let counter = AtomicUsize::new(0);
    let mut handles = vec![];

    for _ in 0..10 {
        let handle = thread::spawn(|| {
            for _ in 0..1000 {
                counter.fetch_add(1, Ordering::Relaxed);
            }
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Final count: {}", counter.load(Ordering::Relaxed));
}