iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Examples

Five idiomatic Rust snippets covering the cases you actually write: CLI args with clap, a typed HTTP request with reqwest, channel-based pipelines, file I/O with error context, and a tiny iterator helper. Each is paste-ready.

Five idiomatic Rust examples

EXAMPLE
// Cargo.toml
// [dependencies]
// clap = { version = "4", features = ["derive"] }
// reqwest = { version = "0.12", features = ["json"] }
// serde = { version = "1", features = ["derive"] }
// tokio = { version = "1", features = ["full"] }
// anyhow = "1"

// ============================================================
// 1) CLI with clap derive
// ============================================================
use clap::{Parser, Subcommand};

#[derive(Parser)]
#[command(name = "shop", version)]
struct Cli {
    #[command(subcommand)]
    cmd: Cmd,
}

#[derive(Subcommand)]
enum Cmd {
    List { #[arg(long, default_value_t = 20)] limit: u32 },
    Show { id: String },
}

// fn main() { let cli = Cli::parse(); match cli.cmd { Cmd::List{ limit } => ..., Cmd::Show{ id } => ... } }

// ============================================================
// 2) Typed HTTP request with reqwest + serde
// ============================================================
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize)]
struct Order {
    id: String,
    customer: String,
    total_cents: u64,
}

#[derive(Serialize)]
struct CreateOrder<>;
struct CreateOrderReal {
    customer: String,
    total_cents: u64,
}

async fn fetch_order(client: &reqwest::Client, id: &str) -> anyhow::Result<Order> {
    let resp = client
        .get(format!("https://api.example.com/orders/{id}"))
        .bearer_auth(std::env::var("TOKEN")?)
        .send()
        .await?
        .error_for_status()?;
    Ok(resp.json::<Order>().await?)
}

// ============================================================
// 3) Channel-based pipeline with bounded concurrency
// ============================================================
use tokio::sync::{mpsc, Semaphore};
use std::sync::Arc;

async fn crawl(urls: Vec<String>, concurrency: usize) -> Vec<(String, usize)> {
    let sem = Arc::new(Semaphore::new(concurrency));
    let (tx, mut rx) = mpsc::channel::<(String, usize)>(64);
    let client = reqwest::Client::new();

    for url in urls {
        let sem = sem.clone();
        let tx  = tx.clone();
        let client = client.clone();
        tokio::spawn(async move {
            let _permit = sem.acquire().await.unwrap();
            if let Ok(resp) = client.get(&url).send().await {
                if let Ok(body) = resp.bytes().await {
                    let _ = tx.send((url, body.len())).await;
                }
            }
        });
    }
    drop(tx);

    let mut out = Vec::new();
    while let Some(item) = rx.recv().await { out.push(item); }
    out
}

// ============================================================
// 4) File I/O with rich error context
// ============================================================
use anyhow::{Context, Result};
use std::fs;
use std::path::Path;

fn load_config(path: &Path) -> Result<toml::Value> {
    let raw = fs::read_to_string(path)
        .with_context(|| format!("reading config from {}", path.display()))?;
    let value = raw.parse::<toml::Value>()
        .with_context(|| format!("parsing TOML in {}", path.display()))?;
    Ok(value)
}

// ============================================================
// 5) Iterator helpers — chunked, windowed, deduped
// ============================================================
fn chunked_average(data: &[f64], size: usize) -> Vec<f64> {
    data.chunks(size)
        .map(|c| c.iter().sum::<f64>() / c.len() as f64)
        .collect()
}

fn moving_average(data: &[f64], size: usize) -> Vec<f64> {
    data.windows(size)
        .map(|w| w.iter().sum::<f64>() / size as f64)
        .collect()
}

fn dedup_consecutive<T: PartialEq + Clone>(xs: &[T]) -> Vec<T> {
    let mut out: Vec<T> = Vec::with_capacity(xs.len());
    for x in xs {
        if out.last().map(|l| l != x).unwrap_or(true) {
            out.push(x.clone());
        }
    }
    out
}

// ============================================================
// Patterns to internalise
// ============================================================
// - clap derive: never roll your own arg parser
// - reqwest: error_for_status + ? for clean propagation
// - bounded concurrency: Semaphore + spawn, never unbounded
// - file I/O: .with_context for "what was I doing when this broke"
// - iterators: prefer chunks/windows over manual indices

#[tokio::main]
async fn main() -> Result<()> { Ok(()) }

Why it matters

`.with_context(|| format!("reading {}", path.display()))?` turns Rusts terse errors into stack-trace-quality reports. Combined with anyhows error chain, a single bug location prints as "place: action: lower-level cause" — you read the error and know exactly which file and step blew up without firing the debugger.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Read the Rust book — chapter 4 (ownership) is the unlock.
Try it Yourself »

Discussion

Loading…