Use Cases

Claude Code के साथ Claude Code Rust

Claude Code का उपयोग करके claude code rust सीखें। Practical tips और code examples शामिल हैं।

RustdevelopmentでClaude Codeが活躍する場面

Rustは所有権、ライフタイム、トレイト आदि独自の概念が多く、学習コストの高い言語 है।Claude Codeはこれらの概念を正確に理解し、コンパイルが通るcodeを高い精度でgenerateでき है।विशेष रूप सेerror handlingやasyncprocessingの定型patternで威力を発揮し है।

CLIツールのdevelopment

> clapを使ったCLIツールをबनाओ。
> JSONfileを読み込んでCSVに変換するfeaturesで。
> プlogレスバーとerror handlingもimplement करो。
// 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(());
    }

    // fieldの決定
    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(","))?;

    // data行
    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"

Web APIのdevelopment(Axum)

> Axumを使ったREST APIをबनाओ。
> CRUD操作、validation、error handlingをimplement करो。
// 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(),
    }
}

error handlingのpattern

Claude Code को requestする際、Rustらしいerror handlingを指示でき है।

> カスタムerror型をthiserrorで定義して。
> APIresponseへの変換もimplement करो。
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

Claude Code का उपयोग करके、Rustの所有権やライフタイムを正しく扱ったcodeをefficientlygenerateでき है।CLIツール、Web API、error handling आदि、Rust特有のpatternに精通しているため、コンパイルerrorとの戦いを大幅に減らせ है।他の言語との比較はClaude Code vs GitHub Copilotをदेखें。効率的なuse करने का तरीकाは生産性を3倍にするTipsで紹介してい है।

Claude Codeके details के लिएAnthropicofficial documentationदेखें。Rustの学習にはThe Rust Programming Languageが最適 है।

#Claude Code #Rust #CLI #Web API #システムプlogラミング