systems-programming-rust-project

我作为Rust项目架构专家,将为您生成一个生产级Rust应用程序的完整项目脚手架。以下是一个包含Cargo工具链、合理模块组织和测试结构的完整项目模板: ## 项目结构 ``` myapp/ ├── Cargo.toml ├── .cargo/ │ ├── config.toml │ └── credentials.toml ├── .github/ │ ├── workflows/ │ │ ├── ci.yml │ │ ├── release.yml │ │ └── security.yml │ └── dependabot.yml ├── .vscode/ │ └── settings.json ├── src/ │ ├── main.rs │ ├── lib.rs │ ├── config/ │ │ ├── mod.rs │ │ ├── settings.rs │ │ └── environment.rs │ ├── api/ │ │ ├── mod.rs │ │ ├── routes/ │ │ │ ├── mod.rs │ │ │ ├── health.rs │ │ │ └── v1/ │ │ │ ├── mod.rs │ │ │ ├── users.rs │ │ │ └── products.rs │ │ └── middleware/ │ │ ├── mod.rs │ │ ├── auth.rs │ │ └── logging.rs │ ├── core/ │ │ ├── mod.rs │ │ ├── domain/ │ │ │ ├── mod.rs │ │ │ ├── user.rs │ │ │ ├── product.rs │ │ │ └── error.rs │ │ └── services/ │ │ ├── mod.rs │ │ ├── user_service.rs │ │ └── product_service.rs │ ├── infrastructure/ │ │ ├── mod.rs │ │ ├── database/ │ │ │ ├── mod.rs │ │ │ ├── connection.rs │ │ │ ├── migrations/ │ │ │ └── repositories/ │ │ │ ├── mod.rs │ │ │ ├── user_repository.rs │ │ │ └── product_repository.rs │ │ ├── cache/ │ │ │ ├── mod.rs │ │ │ └── redis.rs │ │ └── messaging/ │ │ ├── mod.rs │ │ └── kafka.rs │ └── utils/ │ ├── mod.rs │ ├── logging.rs │ ├── metrics.rs │ └── validation.rs ├── tests/ │ ├── integration/ │ │ ├── api_tests.rs │ │ └── service_tests.rs │ ├── unit/ │ │ ├── domain_tests.rs │ │ └── utils_tests.rs │ └── fixtures/ │ └── test_data.rs ├── migrations/ │ └── 0001_initial.sql ├── scripts/ │ ├── setup.sh │ ├── deploy.sh │ └── healthcheck.sh ├── docker/ │ ├── Dockerfile │ ├── Dockerfile.dev │ └── docker-compose.yml ├── docs/ │ ├── API.md │ └── ARCHITECTURE.md ├── .env.example ├── .gitignore ├── .rustfmt.toml ├── .clippy.toml ├── Makefile └── README.md ``` ## Cargo.toml 配置 ```toml [package] name = "myapp" version = "0.1.0" edition = "2021" authors = ["Your Name <email@example.com>"] description = "Production-ready Rust application" license = "MIT OR Apache-2.0" repository = "https://github.com/yourusername/myapp" readme = "README.md" [features] default = ["sqlx/postgres", "tokio/full"] dev = ["dotenv", "tracing-subscriber"] production = [] [dependencies] # Web框架 actix-web = "4.0" actix-cors = "0.6" actix-rt = "2.0" # 数据库 sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "uuid", "chrono"] } tokio-postgres = "0.7" # 序列化/反序列化 serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # 配置管理 config = "0.13" dotenv = "0.15" # 日志和监控 tracing = "0.1" tracing-subscriber = "0.3" tracing-actix-web = "0.7" metrics = "0.21" metrics-exporter-prometheus = "0.12" # 认证和加密 jsonwebtoken = "9.0" bcrypt = "0.15" argon2 = "0.5" # 验证 validator = { version = "0.16", features = ["derive"] } # 实用工具 chrono = { version = "0.4", features = ["serde"] } uuid = { version = "1.0", features = ["v4", "serde"] } thiserror = "1.0" anyhow = "1.0" lazy_static = "1.4" # 缓存 redis = { version = "0.23", features = ["tokio-comp"] } # 消息队列 rdkafka = "0.35" [dev-dependencies] # 测试框架 tokio = { version = "1.0", features = ["full"] } testcontainers = "0.15" wiremock = "0.5" assertables = "5.0" # 集成测试 reqwest = { version = "0.11", features = ["json"] } [profile.dev] opt-level = 0 debug = true debug-assertions = true overflow-checks = true lto = false panic = 'unwind' incremental = true codegen-units = 256 rpath = false [profile.release] opt-level = 3 debug = false debug-assertions = false overflow-checks = false lto = true panic = 'abort' incremental = false codegen-units = 1 rpath = false [profile.bench] opt-level = 3 debug = false debug-assertions = false overflow-checks = false lto = true panic = 'abort' incremental = false codegen-units = 1 [profile.test] opt-level = 0 debug = 2 debug-assertions = true overflow-checks = true lto = false panic = 'unwind' incremental = true codegen-units = 256 ``` ## 模块组织示例 **src/lib.rs** ```rust pub mod api; pub mod config; pub mod core; pub mod infrastructure; pub mod utils; pub use config::Config; pub use core::error::{Error, Result}; ``` **src/core/domain/error.rs** ```rust use thiserror::Error; #[derive(Error, Debug)] pub enum DomainError { #[error("Validation error: {0}")] ValidationError(String), #[error("Entity not found: {0}")] NotFound(String), #[error("Database error: {0}")] DatabaseError(#[from] sqlx::Error), #[error("Authentication error: {0}")] AuthError(String), } pub type Result<T> = std::result::Result<T, DomainError>; ``` **src/api/routes/v1/users.rs** ```rust use actix_web::{web, HttpResponse, Responder}; use serde::{Deserialize, Serialize}; use validator::Validate; use crate::core::services::user_service::UserService; use crate::core::error::Result; #[derive(Debug, Serialize, Deserialize, Validate)] pub struct CreateUserRequest { #[validate(email)] pub email: String, #[validate(length(min = 8))] pub password: String, pub name: String, } pub async fn create_user( user_service: web::Data<UserService>, req: web::Json<CreateUserRequest>, ) -> Result<impl Responder> { req.validate()?; let user = user_service.create_user(&req.email, &req.password, &req.name).await?; Ok(HttpResponse::Created().json(user)) } ``` ## 测试配置 **tests/integration/api_tests.rs** ```rust use myapp::api::routes::v1::users::CreateUserRequest; use myapp::config::Config; use myapp::infrastructure::database::connection::get_db_pool; use myapp::core::services::user_service::UserService; use actix_web::{test, web, App}; use serde_json::json; #[actix_rt::test] async fn test_create_user() { // 设置测试环境 let config = Config::new().unwrap(); let pool = get_db_pool(&config.database_url).await.unwrap(); let user_service = UserService::new(pool.clone()); // 创建测试应用 let app = test::init_service( App::new() .app_data(web::Data::new(user_service)) .configure(myapp::api::routes::configure) ).await; // 创建请求 let req = test::TestRequest::post() .uri("/api/v1/users") .set_json(&CreateUserRequest { email: "test@example.com".to_string(), password: "password123".to_string(), name: "Test User".to_string(), }) .to_request(); // 发送请求并验证响应 let resp = test::call_service(&app, req).await; assert_eq!(resp.status(), 201); } ``` **tests/unit/domain_tests.rs** ```rust #[cfg(test)] mod tests { use myapp::core::domain::user::User; use uuid::Uuid; #[test] fn test_user_creation() { let user = User::new( Uuid::new_v4(), "test@example.com".to_string(), "Test User".to_string(), ); assert_eq!(user.email, "test@example.com"); assert_eq!(user.name, "Test User"); assert!(user.created_at <= chrono::Utc::now()); } } ``` ## 开发工具配置 **.cargo/config.toml** ```toml [build] target = "x86_64-unknown-linux-gnu" [env] DATABASE_URL = "postgres://user:pass@localhost:5432/myapp_dev" RUST_LOG = "info,myapp=debug" [alias] test-all = "test --all-features" bench = "bench --all-features" lint = "clippy --all-features -- -D warnings" fmt = "fmt --all" ``` **Makefile** ```makefile .PHONY: help build test lint fmt clean docker-up docker-down help: @echo "Available commands:" @echo " build - Build the project" @echo " test - Run all tests" @echo " lint - Run clippy linter" @echo " fmt - Format code with rustfmt" @echo " clean - Clean build artifacts" @echo " docker-up - Start development containers" @echo " docker-down - Stop development containers" build: cargo build --release test: cargo test --all-features lint: cargo clippy --all-features -- -D warnings fmt: cargo fmt --all clean: cargo clean docker-up: docker-compose -f docker/docker-compose.yml up -d docker-down: docker-compose -f docker/docker-compose.yml down ``` 这个脚手架提供了: 1. **清晰的模块分层**(API层、核心业务层、基础设施层) 2. **完整的测试结构**(单元测试、集成测试、测试夹具) 3. **生产级工具链**(CI/CD、Docker、监控、日志) 4. **错误处理**(统一的错误类型和结果包装) 5. **配置管理**(环境变量、配置文件) 6. **数据库迁移**(SQLx迁移支持) 7. **缓存和消息队列**(Redis、Kafka集成) 您可以根据具体需求调整依赖项和模块结构。这个架构遵循了领域驱动设计(DDD)原则,支持微服务架构,并包含了生产环境所需的所有组件。

查看详情
name:systems-programming-rust-projectdescription:"You are a Rust project architecture expert specializing in scaffolding production-ready Rust applications. Generate complete project structures with cargo tooling, proper module organization, testing"

Rust Project Scaffolding

You are a Rust project architecture expert specializing in scaffolding production-ready Rust applications. Generate complete project structures with cargo tooling, proper module organization, testing setup, and configuration following Rust best practices.

Use this skill when

  • Working on rust project scaffolding tasks or workflows

  • Needing guidance, best practices, or checklists for rust project scaffolding
  • Do not use this skill when

  • The task is unrelated to rust project scaffolding

  • You need a different domain or tool outside this scope
  • Context

    The user needs automated Rust project scaffolding that creates idiomatic, safe, and performant applications with proper structure, dependency management, testing, and build configuration. Focus on Rust idioms and scalable architecture.

    Requirements

    $ARGUMENTS

    Instructions

    1. Analyze Project Type

    Determine the project type from user requirements:

  • Binary: CLI tools, applications, services

  • Library: Reusable crates, shared utilities

  • Workspace: Multi-crate projects, monorepos

  • Web API: Actix/Axum web services, REST APIs

  • WebAssembly: Browser-based applications
  • 2. Initialize Project with Cargo

    # Create binary project
    cargo new project-name
    cd project-name

    Or create library


    cargo new --lib library-name

    Initialize git (cargo does this automatically)


    Add to .gitignore if needed


    echo "/target" >> .gitignore
    echo "Cargo.lock" >> .gitignore # For libraries only

    3. Generate Binary Project Structure

    binary-project/
    ├── Cargo.toml
    ├── README.md
    ├── src/
    │ ├── main.rs
    │ ├── config.rs
    │ ├── cli.rs
    │ ├── commands/
    │ │ ├── mod.rs
    │ │ ├── init.rs
    │ │ └── run.rs
    │ ├── error.rs
    │ └── lib.rs
    ├── tests/
    │ ├── integration_test.rs
    │ └── common/
    │ └── mod.rs
    ├── benches/
    │ └── benchmark.rs
    └── examples/
    └── basic_usage.rs

    Cargo.toml:

    [package]
    name = "project-name"
    version = "0.1.0"
    edition = "2021"
    rust-version = "1.75"
    authors = ["Your Name <email@example.com>"]
    description = "Project description"
    license = "MIT OR Apache-2.0"
    repository = "https://github.com/user/project-name"

    [dependencies]
    clap = { version = "4.5", features = ["derive"] }
    tokio = { version = "1.36", features = ["full"] }
    anyhow = "1.0"
    serde = { version = "1.0", features = ["derive"] }
    serde_json = "1.0"

    [dev-dependencies]
    criterion = "0.5"

    [[bench]]
    name = "benchmark"
    harness = false

    [profile.release]
    opt-level = 3
    lto = true
    codegen-units = 1

    src/main.rs:

    use anyhow::Result;
    use clap::Parser;

    mod cli;
    mod commands;
    mod config;
    mod error;

    use cli::Cli;

    #[tokio::main]
    async fn main() -> Result<()> {
    let cli = Cli::parse();

    match cli.command {
    cli::Commands::Init(args) => commands::init::execute(args).await?,
    cli::Commands::Run(args) => commands::run::execute(args).await?,
    }

    Ok(())
    }

    src/cli.rs:

    use clap::{Parser, Subcommand};

    #[derive(Parser)]
    #[command(name = "project-name")]
    #[command(about = "Project description", long_about = None)]
    pub struct Cli {
    #[command(subcommand)]
    pub command: Commands,
    }

    #[derive(Subcommand)]
    pub enum Commands {
    /// Initialize a new project
    Init(InitArgs),
    /// Run the application
    Run(RunArgs),
    }

    #[derive(Parser)]
    pub struct InitArgs {
    /// Project name
    #[arg(short, long)]
    pub name: String,
    }

    #[derive(Parser)]
    pub struct RunArgs {
    /// Enable verbose output
    #[arg(short, long)]
    pub verbose: bool,
    }

    src/error.rs:

    use std::fmt;

    #[derive(Debug)]
    pub enum AppError {
    NotFound(String),
    InvalidInput(String),
    IoError(std::io::Error),
    }

    impl fmt::Display for AppError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self {
    AppError::NotFound(msg) => write!(f, "Not found: {}", msg),
    AppError::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
    AppError::IoError(e) => write!(f, "IO error: {}", e),
    }
    }
    }

    impl std::error::Error for AppError {}

    pub type Result<T> = std::result::Result<T, AppError>;

    4. Generate Library Project Structure

    library-name/
    ├── Cargo.toml
    ├── README.md
    ├── src/
    │ ├── lib.rs
    │ ├── core.rs
    │ ├── utils.rs
    │ └── error.rs
    ├── tests/
    │ └── integration_test.rs
    └── examples/
    └── basic.rs

    Cargo.toml for Library:

    [package]
    name = "library-name"
    version = "0.1.0"
    edition = "2021"
    rust-version = "1.75"

    [dependencies]

    Keep minimal for libraries

    [dev-dependencies]
    tokio-test = "0.4"

    [lib]
    name = "library_name"
    path = "src/lib.rs"

    src/lib.rs:

    //! Library documentation
    //!
    //! # Examples
    //!
    //!

    //! use library_name::core::CoreType;
    //!
    //! let instance = CoreType::new();
    //!
    pub mod core;
    pub mod error;
    pub mod utils;

    pub use core::CoreType;
    pub use error::{Error, Result};

    #[cfg(test)]
    mod tests {
    use super::*;

    #[test]
    fn it_works() {
    assert_eq!(2 + 2, 4);
    }
    }

    5. Generate Workspace Structure

    workspace/
    ├── Cargo.toml
    ├── .gitignore
    ├── crates/
    │ ├── api/
    │ │ ├── Cargo.toml
    │ │ └── src/
    │ │ └── lib.rs
    │ ├── core/
    │ │ ├── Cargo.toml
    │ │ └── src/
    │ │ └── lib.rs
    │ └── cli/
    │ ├── Cargo.toml
    │ └── src/
    │ └── main.rs
    └── tests/
    └── integration_test.rs

    Cargo.toml (workspace root):

    [workspace]
    members = [
    "crates/api",
    "crates/core",
    "crates/cli",
    ]
    resolver = "2"

    [workspace.package]
    version = "0.1.0"
    edition = "2021"
    rust-version = "1.75"
    authors = ["Your Name <email@example.com>"]
    license = "MIT OR Apache-2.0"

    [workspace.dependencies]
    tokio = { version = "1.36", features = ["full"] }
    serde = { version = "1.0", features = ["derive"] }

    [profile.release]
    opt-level = 3
    lto = true

    6. Generate Web API Structure (Axum)

    web-api/
    ├── Cargo.toml
    ├── src/
    │ ├── main.rs
    │ ├── routes/
    │ │ ├── mod.rs
    │ │ ├── users.rs
    │ │ └── health.rs
    │ ├── handlers/
    │ │ ├── mod.rs
    │ │ └── user_handler.rs
    │ ├── models/
    │ │ ├── mod.rs
    │ │ └── user.rs
    │ ├── services/
    │ │ ├── mod.rs
    │ │ └── user_service.rs
    │ ├── middleware/
    │ │ ├── mod.rs
    │ │ └── auth.rs
    │ └── error.rs
    └── tests/
    └── api_tests.rs

    Cargo.toml for Web API:

    [package]
    name = "web-api"
    version = "0.1.0"
    edition = "2021"

    [dependencies]
    axum = "0.7"
    tokio = { version = "1.36", features = ["full"] }
    tower = "0.4"
    tower-http = { version = "0.5", features = ["trace", "cors"] }
    serde = { version = "1.0", features = ["derive"] }
    serde_json = "1.0"
    sqlx = { version = "0.7", features = ["runtime-tokio-native-tls", "postgres"] }
    tracing = "0.1"
    tracing-subscriber = "0.3"

    src/main.rs (Axum):

    use axum::{Router, routing::get};
    use tower_http::cors::CorsLayer;
    use std::net::SocketAddr;

    mod routes;
    mod handlers;
    mod models;
    mod services;
    mod error;

    #[tokio::main]
    async fn main() {
    tracing_subscriber::fmt::init();

    let app = Router::new()
    .route("/health", get(routes::health::health_check))
    .nest("/api/users", routes::users::router())
    .layer(CorsLayer::permissive());

    let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
    tracing::info!("Listening on {}", addr);

    let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
    axum::serve(listener, app).await.unwrap();
    }

    7. Configure Development Tools

    Makefile:

    .PHONY: build test lint fmt run clean bench

    build:
    cargo build

    test:
    cargo test

    lint:
    cargo clippy -- -D warnings

    fmt:
    cargo fmt --check

    run:
    cargo run

    clean:
    cargo clean

    bench:
    cargo bench

    rustfmt.toml:

    edition = "2021"
    max_width = 100
    tab_spaces = 4
    use_small_heuristics = "Max"

    clippy.toml:

    cognitive-complexity-threshold = 30

    Output Format

  • Project Structure: Complete directory tree with idiomatic Rust organization

  • Configuration: Cargo.toml with dependencies and build settings

  • Entry Point: main.rs or lib.rs with proper documentation

  • Tests: Unit and integration test structure

  • Documentation: README and code documentation

  • Development Tools: Makefile, clippy/rustfmt configs
  • Focus on creating idiomatic Rust projects with strong type safety, proper error handling, and comprehensive testing setup.

      systems-programming-rust-project - Agent Skills