All skills
jeffallan avatar

/rust-engineer

@efebc44
by jeffallanjeffallan/claude-skills12k stars
1,124

Writes, reviews, and debugs idiomatic Rust code with memory safety and zero-cost abstractions. Implements ownership patterns, manages lifetimes, designs trait hierarchies, builds async applications with tokio, and structures error handling with Result/Option. Use when building Rust applications, solving ownership or borrowing issues, designing trait-based APIs, implementing async/await concurrency, creating FFI bindings, or optimizing for performance and memory safety. Invoke for Rust, Cargo, ownership, borrowing, lifetimes, async Rust, tokio, zero-cost abstractions, memory safety, systems programming.

Use this Skill: https://skilld.dev/gh/jeffallan/claude-skills/rust-engineer

This session only. Nothing lands on disk.

referencestraits.md

≈2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Traits, Generics, and Type System

Basic Trait Definition

// Simple trait
trait Drawable {
    fn draw(&self);
}

// Trait with default implementation
trait Describable {
    fn describe(&self) -> String {
        String::from("No description available")
    }
}

// Implementing traits
struct Circle {
    radius: f64,
}

impl Drawable for Circle {
    fn draw(&self) {
        println!("Drawing circle with radius {}", self.radius);
    }
}

impl Describable for Circle {
    fn describe(&self) -> String {
        format!("A circle with radius {}", self.radius)
    }
}

Associated Types

// Associated types vs generic parameters
trait Container {
    type Item;

    fn add(&mut self, item: Self::Item);
    fn get(&self, index: usize) -> Option<&Self::Item>;
}

impl Container for Vec<i32> {
    type Item = i32;

    fn add(&mut self, item: i32) {
        self.push(item);
    }

    fn get(&self, index: usize) -> Option<&i32> {
        self.get(index)
    }
}

// Iterator trait (standard library example)
trait MyIterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
}

Generic Traits and Bounds

// Generic trait with multiple bounds
fn print_info<T>(item: &T)
where
    T: std::fmt::Display + std::fmt::Debug,
{
    println!("Display: {}", item);
    println!("Debug: {:?}", item);
}

// Generic struct with trait bounds
struct Pair<T: PartialOrd> {
    first: T,
    second: T,
}

impl<T: PartialOrd> Pair<T> {
    fn new(first: T, second: T) -> Self {
        Self { first, second }
    }

    fn larger(&self) -> &T {
        if self.first > self.second {
            &self.first
        } else {
            &self.second
        }
    }
}

// Blanket implementation
trait MyTrait {
    fn do_something(&self);
}

impl<T: std::fmt::Display> MyTrait for T {
    fn do_something(&self) {
        println!("Value: {}", self);
    }
}

Trait Objects (Dynamic Dispatch)

// Static dispatch (monomorphization)
fn static_dispatch<T: Drawable>(item: &T) {
    item.draw();
}

// Dynamic dispatch (trait objects)
fn dynamic_dispatch(item: &dyn Drawable) {
    item.draw();
}

// Storing trait objects
struct Canvas {
    shapes: Vec<Box<dyn Drawable>>,
}

impl Canvas {
    fn new() -> Self {
        Self { shapes: Vec::new() }
    }

    fn add_shape(&mut self, shape: Box<dyn Drawable>) {
        self.shapes.push(shape);
    }

    fn draw_all(&self) {
        for shape in &self.shapes {
            shape.draw();
        }
    }
}

// Object safety: traits must meet criteria
trait ObjectSafe {
    fn method(&self);  // OK: takes &self
}

trait NotObjectSafe {
    fn generic<T>(&self);  // NOT OK: generic method
    fn by_value(self);     // NOT OK: takes self by value
}

Derive Macros

// Standard derive macros
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct User {
    id: u64,
    name: String,
}

// Deriving more traits
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct Point {
    x: i32,
    y: i32,
}

// Custom derive with serde
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct Config {
    host: String,
    port: u16,
}

Advanced Trait Patterns

// Extension trait pattern
trait StringExt {
    fn truncate_to(&self, max_len: usize) -> String;
}

impl StringExt for str {
    fn truncate_to(&self, max_len: usize) -> String {
        if self.len() <= max_len {
            self.to_string()
        } else {
            format!("{}...", &self[..max_len])
        }
    }
}

// Sealed trait pattern (prevent external implementation)
mod sealed {
    pub trait Sealed {}
}

pub trait MySealed: sealed::Sealed {
    fn method(&self);
}

struct MyType;
impl sealed::Sealed for MyType {}
impl MySealed for MyType {
    fn method(&self) {
        println!("Implemented");
    }
}

// Supertraits
trait Printable {
    fn print(&self);
}

trait Loggable: Printable {  // Supertrait: must also impl Printable
    fn log(&self) {
        self.print();  // Can call supertrait methods
    }
}

Associated Constants

trait Config {
    const MAX_SIZE: usize;
    const DEFAULT_TIMEOUT: u64;
}

struct ServerConfig;

impl Config for ServerConfig {
    const MAX_SIZE: usize = 1024;
    const DEFAULT_TIMEOUT: u64 = 30;
}

fn use_config<T: Config>() {
    println!("Max size: {}", T::MAX_SIZE);
}

Generic Associated Types (GATs)

// GATs allow generics in associated types
trait LendingIterator {
    type Item<'a> where Self: 'a;

    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
}

struct WindowsMut<'data, T> {
    data: &'data mut [T],
    index: usize,
}

impl<'data, T> LendingIterator for WindowsMut<'data, T> {
    type Item<'a> = &'a mut [T] where Self: 'a;

    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
        if self.index >= self.data.len() {
            return None;
        }

        let start = self.index;
        self.index += 2;

        Some(&mut self.data[start..start.min(self.data.len())])
    }
}

Marker Traits

use std::marker::{PhantomData, Send, Sync};

// Send: type can be transferred across thread boundaries
// Sync: type can be shared between threads (&T is Send)

// Custom marker trait
trait Trusted {}

struct TrustedData<T> {
    data: T,
    _marker: PhantomData<T>,
}

impl<T: Trusted> TrustedData<T> {
    fn new(data: T) -> Self {
        Self {
            data,
            _marker: PhantomData,
        }
    }
}

Operator Overloading

use std::ops::{Add, Mul};

#[derive(Debug, Clone, Copy)]
struct Vector2D {
    x: f64,
    y: f64,
}

impl Add for Vector2D {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        Self {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}

impl Mul<f64> for Vector2D {
    type Output = Self;

    fn mul(self, scalar: f64) -> Self {
        Self {
            x: self.x * scalar,
            y: self.y * scalar,
        }
    }
}

// Usage
let v1 = Vector2D { x: 1.0, y: 2.0 };
let v2 = Vector2D { x: 3.0, y: 4.0 };
let v3 = v1 + v2;
let v4 = v1 * 2.5;

From/Into Conversion Traits

struct UserId(u64);

impl From<u64> for UserId {
    fn from(id: u64) -> Self {
        UserId(id)
    }
}

// Into is automatically implemented
fn accept_user_id(id: impl Into<UserId>) {
    let user_id = id.into();
    println!("User ID: {}", user_id.0);
}

// TryFrom for fallible conversions
use std::convert::TryFrom;

impl TryFrom<i64> for UserId {
    type Error = &'static str;

    fn try_from(value: i64) -> Result<Self, Self::Error> {
        if value < 0 {
            Err("User ID cannot be negative")
        } else {
            Ok(UserId(value as u64))
        }
    }
}

Const Traits (Nightly)

// Const trait implementations (requires nightly)
#![feature(const_trait_impl)]

#[const_trait]
trait ConstAdd {
    fn add(self, other: Self) -> Self;
}

impl const ConstAdd for i32 {
    fn add(self, other: Self) -> Self {
        self + other
    }
}

const fn compute() -> i32 {
    5.add(10)  // Can use in const context
}

Best Practices

  • Prefer associated types when there's one clear type per implementation
  • Use generic parameters when multiple types might be used simultaneously
  • Keep traits small and focused (single responsibility)
  • Use extension traits to add functionality to existing types
  • Document trait requirements and invariants
  • Use marker traits for compile-time guarantees
  • Prefer static dispatch for performance, dynamic dispatch for flexibility
  • Use #[derive] when possible instead of manual implementations
  • Implement standard traits (Debug, Clone, etc.) for better ecosystem integration
  • Use sealed traits to prevent external implementations when needed

Source: SKILL.md on GitHub

1 alert16d5 checks · Risk CRITICAL
  • Gen Agent Trust Hub16d

    The skill provides comprehensive instructions for Rust engineering tasks. Security analysis identifies risks associated with the execution of testing commands and the handling of untrusted code, which are inherent to the skill's purpose. An external documentation link is provided which has been flagged by automated scanners, though it appears to be a legitimate vendor resource.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    6 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at efebc44. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 5 months ago
Other metadata
metadata
{
  "author": "https://github.com/Jeffallan",
  "version": "1.1.0",
  "domain": "language",
  "triggers": "Rust, Cargo, ownership, borrowing, lifetimes, async Rust, tokio, zero-cost abstractions, memory safety, systems programming",
  "role": "specialist",
  "scope": "implementation",
  "output-format": "code",
  "related-skills": "test-master"
}
  • Rust
  • cargo
  • ownership
  • lifetimes
  • async
  • tokio
  • traits
  • error-handling
  • systems-programming
  • memory-safety

README badge

README badge for jeffallan/claude-skills/rust-engineer

Writes, reviews, and debugs idiomatic Rust code with emphasis on ownership patterns, lifetime management, trait design, and async concurrency using tokio. Handles error propagation via Result/Option, validates against clippy and rustfmt, and minimizes unsafe code with documented safety invariants.

Generated from the current SKILL.md.

Does this skill handle async Rust and tokio?
Yes. The skill covers async/await patterns, tokio runtime setup, spawning concurrent tasks, and proper error handling in async contexts. It includes examples of tokio::join! and reqwest integration.
Will this skill write unsafe code?
The skill minimizes unsafe code and requires documentation of safety invariants for every unsafe block. It treats unsafe as a last resort and prefers type-system guarantees.
What error handling approach does this skill use?
The skill uses Result/Option with the ? operator and thiserror for custom error types. It avoids unwrap() in production code in favor of expect() with descriptive messages.
Does this skill validate code before returning it?
Yes. The skill runs cargo clippy, cargo fmt, and cargo test, and fixes all warnings before finalizing.
Can this skill help with lifetime and borrowing issues?
Yes. The skill analyzes ownership relationships, annotates lifetimes explicitly where needed, and designs borrowing patterns to leverage Rust's memory safety without cloning.

Generated from the current SKILL.md. These answers refresh after source changes.