Rust Error Handling and Concurrency

by mahidhar

Error Handling and Concurrency:

Error Handling:

Rust provides Result and Option types for handling errors in a safe and expressive way. Result represents either success with a value of type T or failure with an error of type E. Option represents either Some value of type T or None.

Simple Example:

code
fn parse_number(s: &str) -> Result<i32, std::num::ParseIntError> {
    s.parse()
}

fn main() {
    let number_str = "42";
    match parse_number(number_str) {
        Ok(number) => println!("Parsed number: {}", number),
        Err(err) => println!("Error parsing number: {}", err),
    }
}

Complex Example:

code
use std::fs::File;
use std::io::Read;

fn read_file_content(filename: &str) -> Result<String, std::io::Error> {
    let mut file = File::open(filename)?;
    let mut content = String::new();
    file.read_to_string(&mut content)?;
    Ok(content)
}

fn main() {
    match read_file_content("example.txt") {
        Ok(content) => println!("File content: {}", content),
        Err(err) => println!("Error reading file: {}", err),
    }
}
Concurrency:

Rust provides powerful concurrency primitives, including threads and message passing, for writing concurrent programs. Rust's ownership system and type system ensure memory safety and data race prevention.

Simple Example:

code
use std::thread;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..=5 {
            println!("Thread: {}", i);
        }
    });

    handle.join().unwrap();
    println!("Main thread");
}

Complex Example:

code
use std::sync::mpsc;
use std::thread;

fn main() {
    let (sender, receiver) = mpsc::channel();

    let sender_clone = sender.clone();
    thread::spawn(move || {
        sender_clone.send("Message from thread").unwrap();
    });

    let received = receiver.recv().unwrap();
    println!("Received message: {}", received);
}

Advanced Concepts:

Unsafe Rust:

Rust allows you to write unsafe code when necessary for low-level operations or interfacing with other languages. Unsafe code blocks are enclosed in unsafe { } and require manual adherence to safety guarantees.

Simple Example:

code
unsafe fn unsafe_function() {
    println!("This is an unsafe function");
}

fn main() {
    unsafe {
        unsafe_function();
    }
}

Complex Example:

code
use std::slice;

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    let pointer = numbers.as_ptr();
    let length = numbers.len();

    unsafe {
        let slice = slice::from_raw_parts(pointer, length);
        println!("Slice: {:?}", slice);
    }
}
Traits and Generics:

Traits allow you to define shared behavior across types, and generics enable writing code that can operate on different types. They are fundamental to Rust's approach to code reuse and abstraction.

Simple Example:

code
trait Greet {
    fn greet(&self);
}

struct Person {
    name: String,
}

impl Greet for Person {
    fn greet(&self) {
        println!("Hello, my name is {}", self.name);
    }
}

fn main() {
    let person = Person {
        name: "Alice".to_string(),
    };
    person.greet();
}

Complex Example:

code
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn new(x: T, y: T) -> Self {
        Point { x, y }
    }
}

fn main() {
    let integer_point = Point::new(1, 2);
    let float_point = Point::new(1.5, 2.5);

    println!("Integer Point: ({}, {})", integer_point.x, integer_point.y);
    println!("Float Point: ({}, {})", float_point.x, float_point.y);
}
Pattern Matching:

Pattern matching in Rust allows for concise and expressive code by matching patterns against values and executing corresponding code blocks.

Simple Example:

code
fn main() {
    let number = 5;
    match number {
        1 => println!("One"),
        2 => println!("Two"),
        _ => println!("Other"),
    }
}

Complex Example:

code
fn main() {
    let result = Some(5);
    match result {
        Some(value) if value < 0 => println!("Negative"),
        Some(value) if value > 0 => println!("Positive"),
        Some(0) | None => println!("Zero or None"),
        _ => println!("Other"),
    }
}

This covers advanced concepts in Rust, including unsafe code, traits, generics, and pattern matching. In the next section, we'll explore tools and the Rust ecosystem.