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.
Discussion
Loading…