mcpField
R
rust

rust

github.com/miles990Development2650 installsUpdated 41w ago
Repository

About rust

rust is a reference skill for Rust programming patterns. It covers ownership, lifetimes, traits, error handling, asynchronous programming, and collections.

Key features

  1. 01Ownership and borrowing patterns
  2. 02Lifetime annotations
  3. 03Structs, enums, and traits
  4. 04Error-handling examples
  5. 05Async programming and collections

Use cases

  1. 01Review Rust ownership and borrowing
  2. 02Refer to trait and error-handling patterns
  3. 03Study async code and iterator operations

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/miles990/claude-software-skills --skill rust

After installing, type/rustin Claude Code to confirm it loaded.

Bundled filestemplates/Cargo.tomltemplates/README.md

Details

From the project README

Rust

Overview

Rust programming patterns including ownership, lifetimes, traits, and async programming.


Ownership and Borrowing

Basic Ownership
fn main() {
    // Ownership transfer (move)
    let s1 = String::from("hello");
    let s2 = s1; // s1 is moved to s2
    // println!("{}", s1); // Error: s1 is no longer valid

    // Clone for deep copy
    let s3 = String::from("hello");
    let s4 = s3.clone();
    println!("{} {}", s3, s4); // Both valid

    // Copy types (stack-only data)
    let x = 5;
    let y = x; // Copy, not move
    println!("{} {}", x, y); // Both valid
}

// Ownership and functions
fn takes_ownership(s: String) {
    println!("{}", s);
} // s is dropped here

fn makes_copy(x: i32) {
    println!("{}", x);
} // x goes out of scope, nothing special

fn gives_ownership() -> String {
    String::from("hello")
}

fn takes_and_gives_back(s: String) -> String {
    s
}
Borrowing
// Immutable borrow
fn calculate_length(s: &String) -> usize {
    s.len()
} // s goes out of scope but doesn't drop the value

// Mutable borrow
fn append_world(s: &mut String) {
    s.push_str(" world");
}

fn main() {
    let s = String::from("hello");

    // Multiple immutable borrows OK
    let r1 = &s;
    let r2 = &s;
    println!("{} {}", r1, r2);

    // Mutable borrow (only one at a time)
    let mut s2 = String::from("hello");
    let r3 = &mut s2;
    r3.push_str(" world");
    println!("{}", r3);

    // Cannot have mutable and immutable at same time
    let mut s3 = String::from("hello");
    let r4 = &s3;
    // let r5 = &mut s3; // Error!
    println!("{}", r4);
}
Lifetimes
// Explicit lifetime annotations
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

// Struct with lifetime
struct Excerpt<'a> {
    part: &'a str,
}

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

    fn announce_and_return(&self, announcement: &str) -> &str {
        println!("Attention: {}", announcement);
        self.part
    }
}

// Multiple lifetimes
fn complex<'a, 'b>(x: &'a str, y: &'b str) -> &'a str
where
    'b: 'a, // 'b outlives 'a
{
    x
}

// Static lifetime
fn static_string() -> &'static str {
    "I live forever"
}

Structs and Enums

Structs
#[derive(Debug, Clone, PartialEq)]
struct User {
    id: u64,
    email: String,
    name: String,
    active: bool,
}

impl User {
    // Associated function (constructor)
    fn new(email: String, name: String) -> Self {
        Self {
            id: generate_id(),
            email,
            name,
            active: true,
        }
    }

    // Method
    fn deactivate(&mut self) {
        self.active = false;
    }

    // Method returning reference
    fn email(&self) -> &str {
        &self.email
    }
}

// Tuple struct
struct Color(u8, u8, u8);
struct Point(f64, f64, f64);

// Unit struct
struct AlwaysEqual;
Enums
// Basic enum
enum Direction {
    North,
    South,
    East,
    West,
}

// Enum with data
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(u8, u8, u8),
}

impl Message {
    fn process(&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),
        }
    }
}

// Result and Option
fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        Err(String::from("Division by zero"))
    } else {
        Ok(a / b)
    }
}

fn find_user(id: u64) -> Option<User> {
    // ...
    None
}

Traits

// Trait definition
trait Summary {
    fn summarize(&self) -> String;

    // Default implementation
    fn summarize_author(&self) -> String {
        String::from("(unknown author)")
    }
}

// Implement trait
impl Summary for User {
    fn summarize(&self) -> String {
        format!("{} ({})", self.name, self.email)
    }
}

// Trait bounds
fn notify<T: Summary>(item: &T) {
    println!("Breaking news: {}", item.summarize());
}

// Multiple trait bounds
fn notify_multiple<T: Summary + Clone>(item: &T) {
    let cloned = item.clone();
    println!("{}", cloned.summarize());
}

// where clause
fn some_function<T, U>(t: &T, u: &U) -> i32
where
    T: Summary + Clone,
    U: Clone + std::fmt::Debug,
{
    // ...
    0
}

// Return trait
fn create_summarizable() -> impl Summary {
    User::new(
        String::from("[email protected]"),
        String::from("Test"),
    )
}

// Trait objects (dynamic dispatch)
fn process_summaries(items: &[&dyn Summary]) {
    for item in items {
        println!("{}", item.summarize());
    }
}

Error Handling

use std::fs::File;
use std::io::{self, Read};
use thiserror::Error;

// Custom error with thiserror
#[derive(Error, Debug)]
pub enum AppError {
    #[error("IO error: {0}")]
    Io(#[from] io::Error),

    #[error("Parse error: {0}")]
    Parse(#[from] std::num::ParseIntError),

    #[error("Not found: {0}")]
    NotFound(String),

    #[error("Validation error: {field} - {message}")]
    Validation { field: String, message: String },
}

// Using Result
fn read_file(path: &str) -> Result<String, AppError> {
    let mut file = File::open(path)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    Ok(contents)
}

// ? operator chains
fn read_username_from_file() -> Result<String, io::Error> {
    let mut username = String::new();
    File::open("username.txt")?.read_to_string(&mut username)?;
    Ok(username)
}

// Option handling
fn find_and_process(id: u64) -> Option<String> {
    let user = find_user(id)?;
    let data = process_user(&user)?;
    Some(data)
}

// Combinators
fn get_user_email(id: u64) -> Option<String> {
    find_user(id)
        .map(|user| user.email)
        .filter(|email| !email.is_empty())
}

fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
    s.parse::<i32>().map(|n| n * 2)
}

Async Programming

use tokio;
use futures::future;

// Async function
async fn fetch_data(url: &str) -> Result<String, reqwest::Error> {
    let response = reqwest::get(url).await?;
    let body = response.text().await?;
    Ok(body)
}

// Concurrent execution
async fn fetch_all(urls: Vec<&str>) -> Vec<Result<String, reqwest::Error>> {
    let futures: Vec<_> = urls.iter().map(|url| fetch_data(url)).collect();
    future::join_all(futures).await
}

// Select (race)
use tokio::select;
use tokio::time::{sleep, Duration};

async fn fetch_with_timeout(url: &str) -> Result<String, &'static str> {
    select! {
        result = fetch_data(url) => result.map_err(|_| "fetch error"),
        _ = sleep(Duration::from_secs(5)) => Err("timeout"),
    }
}

// Spawn tasks
async fn process_items(items: Vec<String>) {
    let handles: Vec<_> = items
        .into_iter()
        .map(|item| {
            tokio::spawn(async move {
                process_item(&item).await
            })
        })
        .collect();

    for handle in handles {
        if let Err(e) = handle.await {
            eprintln!("Task failed: {}", e);
        }
    }
}

// Streams
use futures::stream::{self, StreamExt};

async fn process_stream() {
    let numbers = stream::iter(vec![1, 2, 3, 4, 5]);

    numbers
        .map(|n| async move { n * 2 })
        .buffer_unordered(3)
        .for_each(|n| async move {
            println!("{}", n);
        })
        .await;
}

// Channels
use tokio::sync::mpsc;

async fn channel_example() {
    let (tx, mut rx) = mpsc::channel(32);

    tokio::spawn(async move {
        for i in 0..10 {
            tx.send(i).await.unwrap();
        }
    });

    while let Some(value) = rx.recv().await {
        println!("Received: {}", value);
    }
}

Collections and Iterators

use std::collections::{HashMap, HashSet, VecDeque};

// Vec operations
let mut vec = vec![1, 2, 3];
vec.push(4);
vec.extend([5, 6, 7]);
let first = vec.first();
let last = vec.pop();

// HashMap
let mut map: HashMap<String, i32> = HashMap::new();
map.insert(String::from("key"), 42);
map.entry(String::from("key2")).or_insert(0);

// Iterator methods
let numbers = vec![1, 2, 3, 4, 5];

let doubled: Vec<_> = numbers.iter().map(|x| x * 2).collect();

let sum: i32 = numbers.iter().sum();

let evens: Vec<_> = numbers.iter().filter(|x| *x % 2 == 0).collect();

let found = numbers.iter().find(|&&x| x > 3);

let all_positive = numbers.iter().all(|x| *x > 0);

// Chaining
let result: i32 = numbers
    .iter()
    .filter(|x| *x % 2 == 0)
    .map(|x| x * 2)
    .sum();

// Custom iterator
struct Counter {
    count: u32,
    max: u32,
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        if self.count < self.max {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

Smart Pointers

use std::rc::Rc;
use std::cell::RefCell;
use std::sync::{Arc, Mutex};

// Box - heap allocation
let boxed = Box::new(5);
let list = Box::new(Node {
    value: 1,
    next: Some(Box::new(Node { value: 2, next: None })),
});

// Rc - reference counting
let a = Rc::new(5);
let b = Rc::clone(&a);
let c = Rc::clone(&a);
println!("count: {}", Rc::strong_count(&a)); // 3

// RefCell - interior mutability
let cell = RefCell::new(5);
*cell.borrow_mut() += 1;
println!("{}", cell.borrow()); // 6

// Rc<RefCell<T>> - shared mutable state
let shared = Rc::new(RefCell::new(vec![1, 2, 3]));
let shared2 = Rc::clone(&shared);
shared.borrow_mut().push(4);
shared2.borrow_mut().push(5);

// Arc - thread-safe Rc
let arc = Arc::new(5);
let arc2 = Arc::clone(&arc);

// Arc<Mutex<T>> - shared mutable state across threads
let counter = Arc::new(Mutex::new(0));
let handles: Vec<_> = (0..10)
    .map(|_| {
        let counter = Arc::clone(&counter);
        std::thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        })
    })
    .collect();

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

Related Skills

  • [[system-design]] - Systems programming
  • [[desktop-apps]] - Tauri applications
  • [[performance-optimization]] - Low-level optimization

Comments

Markdown supported