All skills
lukemurraynz avatar

/rust-patterns

@2cc2455

USE FOR: Rust implementation recipes for new Rust 2024 services, libraries, CLIs, and workspace scaffolds - Cargo setup, error types, async patterns, serde/config, gRPC/Protobuf, HTTP/axum, OpenTelemetry/tracing, testing, quality gates, API design, production readiness, and security/supply-chain checks. Pairs with `rust.instructions.md` and `rust-tests.instructions.md`. Load this skill when Copilot needs working Rust code patterns or configuration guidance.

Use this Skill: https://skilld.dev/gh/lukemurraynz/hve-agent-skills/rust-patterns

This session only. Nothing lands on disk.

recipesasync-traits.md

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

Async Trait Patterns

Use this recipe when designing async traits, repositories, service abstractions, and test doubles.

Native async fn in Traits

Use native async fn in traits for static dispatch and concrete types:

pub trait Repository: Send + Sync {
    async fn find_by_id(&self, id: &str) -> Result<Option<Item>>;
    async fn save(&self, item: &Item) -> Result<()>;
}

This is concise and works well when callers use generic type parameters:

pub struct UserService<R> {
    repository: R,
}

impl<R> UserService<R>
where
    R: Repository,
{
    pub async fn load(&self, id: &str) -> Result<Option<Item>> {
        self.repository.find_by_id(id).await
    }
}

Dynamic Dispatch

Use async-trait only when dyn Trait, Box<dyn Trait>, or trait-object storage is required:

async-trait = "0.1"
use async_trait::async_trait;

#[async_trait]
pub trait Repository: Send + Sync {
    async fn find_by_id(&self, id: &str) -> Result<Option<Item>>;
}

#[async_trait]
impl Repository for Box<dyn Repository> {
    async fn find_by_id(&self, id: &str) -> Result<Option<Item>> {
        self.as_ref().find_by_id(id).await
    }
}

Public Library Traits

For public libraries where Send bounds and object safety matter, prefer explicit future return types or boxed futures rather than assuming native async fn will fit every caller:

use std::future::Future;

pub trait Repository {
    fn find_by_id(
        &self,
        id: &str,
    ) -> impl Future<Output = Result<Option<Item>>> + Send;
}

For trait objects:

use std::future::Future;
use std::pin::Pin;

pub trait Repository: Send + Sync {
    fn find_by_id<'a>(
        &'a self,
        id: &'a str,
    ) -> Pin<Box<dyn Future<Output = Result<Option<Item>>> + Send + 'a>>;
}

Rules

  • Prefer static dispatch first.
  • Use async-trait deliberately, not by habit.
  • Be explicit about Send when code will run on a multi-threaded executor.
  • Keep trait APIs small; avoid turning traits into broad service locators.
  • For tests, prefer small traits with focused responsibilities over mocking large clients.

Source: SKILL.md on GitHub

No alerts8d3 checks · Risk SAFE
  • Gen Agent Trust Hub8d

    The skill provides a comprehensive library of Rust implementation recipes and configuration baselines, emphasizing modern standards (Rust 2024) and security best practices such as secret redaction, dependency hygiene, and structured observability.

  • Socket8d

    No alerts

  • Snyk8d

    Risk: LOW · No issues

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

Last checked against GitHub last month.

Steadyupdated last month
Other metadata
metadata
{
  "last_verified": "2026-08-26",
  "layer": "scoped",
  "owner": "engineering"
}

README badge

README badge for lukemurraynz/hve-agent-skills/rust-patterns