Use Cases

Claude Code Rust dengan Claude Code

Pelajari tentang claude code rust menggunakan Claude Code. Dilengkapi tips praktis dan contoh kode.

RustpengembanganでClaude Codeが活躍する場面

Rust 所有権、ライフタイム、トレイト dll.独自 概念 多く、学習コスト 高い言語.Claude Code これら 概念 正確 理解し、コンパイル 通るコード 高い精度 generate bisa dilakukan.特 errorハンドリングや非同期pemrosesan 定型pola 威力 発揮.

pengembangan CLItools

> clap 使ったCLItools buatkan.
> JSONfile 読み込ん dengan CSV konversiする機能 dengan 。
> progress bar dan errorハンドリング implementasikan juga.
// src/main.rs
use clap::Parser;
use anyhow::{Context, Result};
use indicatif::{ProgressBar, ProgressStyle};
use serde_json::Value;
use std::fs;
use std::io::Write;

#[derive(Parser, Debug)]
#[command(name = "json2csv", about = "Convert JSON to CSV")]
struct Args {
    /// Input JSON file path
    #[arg(short, long)]
    input: String,

    /// Output CSV file path
    #[arg(short, long)]
    output: String,

    /// Fields to extract (comma-separated)
    #[arg(short, long)]
    fields: Option<String>,
}

fn main() -> Result<()> {
    let args = Args::parse();

    let content = fs::read_to_string(&args.input)
        .context(format!("Failed to read file: {}", args.input))?;

    let data: Vec<Value> = serde_json::from_str(&content)
        .context("Failed to parse JSON")?;

    if data.is_empty() {
        println!("No data found in the JSON file.");
        return Ok(());
    }

    // フィールド 決定
    let fields: Vec<String> = match &args.fields {
        Some(f) => f.split(',').map(|s| s.trim().to_string()).collect(),
        None => {
            if let Some(obj) = data[0].as_object() {
                obj.keys().cloned().collect()
            } else {
                anyhow::bail!("JSON array elements must be objects");
            }
        }
    };

    let pb = ProgressBar::new(data.len() as u64);
    pb.set_style(
        ProgressStyle::with_template(
            "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})"
        )?
        .progress_chars("=>-"),
    );

    let mut output = fs::File::create(&args.output)
        .context(format!("Failed to create output file: {}", args.output))?;

    // Header
    writeln!(output, "{}", fields.join(","))?;

    // データ行
    for item in &data {
        let row: Vec<String> = fields.iter().map(|field| {
            match item.get(field) {
                Some(Value::String(s)) => format!("\"{}\"", s.replace('"', "\"\"")),
                Some(v) => v.to_string(),
                None => String::new(),
            }
        }).collect();

        writeln!(output, "{}", row.join(","))?;
        pb.inc(1);
    }

    pb.finish_with_message("Done");
    println!("Converted {} records to {}", data.len(), args.output);

    Ok(())
}
# Cargo.toml
[package]
name = "json2csv"
version = "0.1.0"
edition = "2021"

[dependencies]
clap = { version = "4", features = ["derive"] }
serde_json = "1"
anyhow = "1"
indicatif = "0.17"

pengembangan(Axum) Web API

> Axum 使ったREST API buatkan.
> CRUDoperasi、validasi、errorハンドリング implementasikan.
// src/main.rs
use axum::{
    extract::{Path, State},
    http::StatusCode,
    response::IntoResponse,
    routing::{get, post, put, delete},
    Json, Router,
};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use uuid::Uuid;

#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
struct Task {
    id: Uuid,
    title: String,
    description: Option<String>,
    completed: bool,
    created_at: chrono::NaiveDateTime,
}

#[derive(Debug, Deserialize)]
struct CreateTask {
    title: String,
    description: Option<String>,
}

#[derive(Debug, Deserialize)]
struct UpdateTask {
    title: Option<String>,
    description: Option<String>,
    completed: Option<bool>,
}

#[derive(Clone)]
struct AppState {
    db: PgPool,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let db = PgPool::connect(&std::env::var("DATABASE_URL")?).await?;
    sqlx::migrate!().run(&db).await?;

    let state = AppState { db };

    let app = Router::new()
        .route("/api/tasks", get(list_tasks).post(create_task))
        .route("/api/tasks/:id", get(get_task).put(update_task).delete(delete_task))
        .with_state(state);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
    println!("Server running on http://localhost:3000");
    axum::serve(listener, app).await?;

    Ok(())
}

async fn list_tasks(State(state): State<AppState>) -> impl IntoResponse {
    let tasks = sqlx::query_as::<_, Task>("SELECT * FROM tasks ORDER BY created_at DESC")
        .fetch_all(&state.db)
        .await;

    match tasks {
        Ok(tasks) => Json(tasks).into_response(),
        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
    }
}

async fn create_task(
    State(state): State<AppState>,
    Json(input): Json<CreateTask>,
) -> impl IntoResponse {
    if input.title.trim().is_empty() {
        return (StatusCode::BAD_REQUEST, "Title is required").into_response();
    }

    let task = sqlx::query_as::<_, Task>(
        "INSERT INTO tasks (id, title, description) VALUES ($1, $2, $3) RETURNING *"
    )
    .bind(Uuid::new_v4())
    .bind(&input.title)
    .bind(&input.description)
    .fetch_one(&state.db)
    .await;

    match task {
        Ok(task) => (StatusCode::CREATED, Json(task)).into_response(),
        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
    }
}

async fn get_task(
    State(state): State<AppState>,
    Path(id): Path<Uuid>,
) -> impl IntoResponse {
    let task = sqlx::query_as::<_, Task>("SELECT * FROM tasks WHERE id = $1")
        .bind(id)
        .fetch_optional(&state.db)
        .await;

    match task {
        Ok(Some(task)) => Json(task).into_response(),
        Ok(None) => StatusCode::NOT_FOUND.into_response(),
        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
    }
}

async fn update_task(
    State(state): State<AppState>,
    Path(id): Path<Uuid>,
    Json(input): Json<UpdateTask>,
) -> impl IntoResponse {
    let task = sqlx::query_as::<_, Task>(
        "UPDATE tasks SET title = COALESCE($2, title), description = COALESCE($3, description), completed = COALESCE($4, completed) WHERE id = $1 RETURNING *"
    )
    .bind(id)
    .bind(&input.title)
    .bind(&input.description)
    .bind(input.completed)
    .fetch_optional(&state.db)
    .await;

    match task {
        Ok(Some(task)) => Json(task).into_response(),
        Ok(None) => StatusCode::NOT_FOUND.into_response(),
        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
    }
}

async fn delete_task(
    State(state): State<AppState>,
    Path(id): Path<Uuid>,
) -> impl IntoResponse {
    let result = sqlx::query("DELETE FROM tasks WHERE id = $1")
        .bind(id)
        .execute(&state.db)
        .await;

    match result {
        Ok(r) if r.rows_affected() > 0 => StatusCode::NO_CONTENT.into_response(),
        Ok(_) => StatusCode::NOT_FOUND.into_response(),
        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
    }
}

pola errorハンドリング

Claude Code 依頼 際、Rustらしいerrorハンドリング 指示 bisa dilakukan.

> カスタムerror型 thiserror dengan definisiして。
> APIresponseへ konversi implementasikan juga.
use axum::{http::StatusCode, response::IntoResponse, Json};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum AppError {
    #[error("Not found: {0}")]
    NotFound(String),

    #[error("Validation error: {0}")]
    Validation(String),

    #[error("Database error: {0}")]
    Database(#[from] sqlx::Error),

    #[error("Internal error: {0}")]
    Internal(#[from] anyhow::Error),
}

impl IntoResponse for AppError {
    fn into_response(self) -> axum::response::Response {
        let (status, message) = match &self {
            AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg.clone()),
            AppError::Validation(msg) => (StatusCode::BAD_REQUEST, msg.clone()),
            AppError::Database(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Database error".into()),
            AppError::Internal(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal error".into()),
        };

        (status, Json(serde_json::json!({ "error": message }))).into_response()
    }
}

Summary

Dengan Claude Code, Rust 所有権やライフタイム 正しく扱ったコード efisien generate bisa dilakukan.CLItools、Web API、errorハンドリング dll.、Rust特有 pola 精通 untuk 、コンパイルerror dan 戦い 大幅 減らせ.他 言語 dan 比較 Claude Code vs GitHub Copilot silakan lihat.efisienな使い方 生産性 3倍 Tips perkenalan い.

Claude Code 詳細 Anthropic公式dokumen silakan lihat.Rust 学習 The Rust Programming Language 最適.

#Claude Code #Rust #CLI #Web API #sistemプログラミング