{
"title": "10 Expert Prompts for Rust: Systems Programming, CLI, and WebAssembly",
"content": "## Introduction\n\nRust has matured into a language that powers everything from operating systems to real-time web applications. Its combination of memory safety without a garbage collector and zero-cost abstractions makes it the go-to choice for systems programming, command-line tools, and WebAssembly. However, even experienced developers sometimes struggle to craft the right prompts for AI assistants when working with Rust’s unique ownership model, lifetimes, and async runtime.\n\nThis article provides a curated collection of 10 expert-level prompts organized by difficulty—basic, advanced, and expert. Each prompt includes a clear task, the exact prompt to use, and a realistic example result. Whether you are building a CLI utility with clap, writing unsafe code for embedded systems, or compiling Rust to WebAssembly with wasm-pack, these prompts will help you get precise, production-ready answers.\n\n## Basic Prompts\n\n### 1. Safe String Parsing with No Panics\n\nTask: Parse a CSV line into a struct without using unwrap() or causing a panic.\n\nPrompt:\n> Write a Rust function that parses a comma-separated string into a Person struct with fields name: String, age: u32, and email: String. Use only safe error handling (Result and Option). Do not use unwrap() or expect(). Show the implementation and a test case.\n\nExample Result:\n```rust\nuse std::num::ParseIntError;\n\n#[derive(Debug, PartialEq)]\nstruct Person {\n name: String,\n age: u32,\n email: String,\n}\n\nfn parse_person(line: &str) -> Result
|e: ParseIntError| e.to_string())?;\n let email = parts[2].trim().to_string();\n if !email.contains('@') {\n return Err(\"Invalid email\".to_string());\n }\n Ok(Person { name, age, email })\n}\n\n#[test]\nfn test_parse_valid() {\n let result = parse_person(\"Alice,30,alice@example.com\");\n assert_eq!(result, Ok(Person {\n name: \"Alice\".into(),\n age: 30,\n email: \"alice@example.com\".into(),\n }));\n}\n\n\n### 2. Simple CLI with clap\n\n**Task:** Create a minimal command-line tool that greets a user.\n\n**Prompt:**\n> Using the `clap` crate (version 4.x), write a Rust program that accepts a `--name` argument and an optional `--count` flag (default 1). Print \"Hello, {name}!\" repeated `count` times. Include error handling for missing required arguments.\n\n**Example Result:**\nrust\nuse clap::Parser;\n\n#[derive(Parser)]\n#[command(name = \"greeter\", version = \"1.0\")]\nstruct Args {\n #[arg(short, long)]\n name: String,\n\n #[arg(short, long, default_value_t = 1)]\n count: u32,\n}\n\nfn main() {\n let args = Args::parse();\n for _ in 0..args.count {\n println!(\"Hello, {}!\", args.name);\n }\n}\n\n\n### 3. Basic WebAssembly Function\n\n**Task:** Export a Rust function to WebAssembly that adds two integers.\n\n**Prompt:**\n> Write a Rust library that exports a function `add(a: i32, b: i32) -> i32` for WebAssembly. Use `wasm-bindgen` version 0.2. Include the `Cargo.toml` dependencies and the `lib.rs` code.\n\n**Example Result:**\ntoml\n# Cargo.toml\n[package]\nname = \"wasm-add\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nwasm-bindgen = \"0.2\"\n\n\nrust\nuse wasm_bindgen::prelude::;\n\n#[wasm_bindgen]\npub fn add(a: i32, b: i32) -> i32 {\n a + b\n}\n\n\n## Advanced Prompts\n\n### 4. Lifetimes in a Custom Iterator\n\n**Task:** Implement a custom iterator that yields references to elements of a slice without cloning.\n\n**Prompt:**\n> Write a Rust struct `Chunks` that implements `Iterator` yielding `&[u8]` chunks of a fixed size from a `&[u8]`. Use explicit lifetime annotations. Include a `new` function and a complete test.\n\n**Example Result:**\nrust\nstruct Chunks<'a> {\n data: &'a [u8],\n chunk_size: usize,\n index: usize,\n}\n\nimpl<'a> Chunks<'a> {\n fn new(data: &'a [u8], chunk_size: usize) -> Self {\n Chunks { data, chunk_size, index: 0 }\n }\n}\n\nimpl<'a> Iterator for Chunks<'a> {\n type Item = &'a [u8];\n\n fn next(&mut self) -> Option\n\n### 5. Async File Processing with Tokio\n\n**Task:** Read a large file line by line asynchronously, process each line, and write results to another file.\n\n**Prompt:**\n> Using `tokio` (version 1.x) and `tokio::fs::File`, write an async function that reads lines from `input.txt`, converts each line to uppercase, and writes to `output.txt`. Handle errors with `anyhow`. Show `Cargo.toml` dependencies and the main function.\n\n**Example Result:**\ntoml\n[dependencies]\ntokio = { version = \"1\", features = [\"full\"] }\nanyhow = \"1\"\n\n\nrust\nuse anyhow::Result;\nuse tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};\n\n#[tokio::main]\nasync fn main() -> Result<()> {\n let input = tokio::fs::File::open(\"input.txt\").await?;\n let reader = BufReader::new(input);\n let mut output = tokio::fs::File::create(\"output.txt\").await?;\n\n let mut lines = reader.lines();\n while let Some(line) = lines.next_line().await? {\n let upper = line.to_uppercase();\n output.write_all(upper.as_bytes()).await?;\n output.write_all(b\"\n\").await?;\n }\n Ok(())\n}\n\n\n### 6. Interacting with a REST API using reqwest\n\n**Task:** Fetch JSON data from a public API and deserialize it.\n\n**Prompt:**\n> Using `reqwest` (0.12.x) and `serde`, write a Rust program that fetches the current weather from the OpenWeatherMap API (you can use a placeholder URL). Parse the JSON response into a struct and print the temperature. Handle network errors gracefully.\n\n**Example Result:**\nrust\nuse reqwest::Error;\nuse serde::Deserialize;\n\n#[derive(Deserialize, Debug)]\nstruct WeatherResponse {\n main: Main,\n}\n\n#[derive(Deserialize, Debug)]\nstruct Main {\n temp: f64,\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), Error> {\n let url = \"https://api.openweathermap.org/data/2.5/weather?q=London&appid=YOUR_API_KEY\";\n let resp = reqwest::get(url).await?;\n let weather: WeatherResponse = resp.json().await?;\n println!(\"Temperature: {} K\", weather.main.temp);\n Ok(())\n}\n\n\n*Note:* For real API integrations, consider using `dotenv` to manage keys. ASI Biont supports connecting to external APIs like OpenWeatherMap through its automation platform — learn more at asibiont.com/courses.\n\n### 7. Unsafe Code for FFI with C\n\n**Task:** Call a C function from Rust using `extern \"C\"` and unsafe blocks.\n\n**Prompt:**\n> Write Rust code that links to a C library `libmylib.so` containing a function `int multiply(int a, int b)`. Declare the FFI, call it safely by wrapping it in a safe Rust function, and include a test. Show the build configuration in `build.rs` if necessary.\n\n**Example Result:**\nrust\n// In build.rs\nfn main() {\n println!(\"cargo:rustc-link-lib=mylib\");\n}\n\n// In lib.rs\nextern \"C\" {\n fn multiply(a: i32, b: i32) -> i32;\n}\n\npub fn safe_multiply(a: i32, b: i32) -> i32 {\n unsafe { multiply(a, b) }\n}\n\n#[cfg(test)]\nmod tests {\n use super::\n\n## Expert Prompts\n\n### 8. Procedural Macro for Derive\n\n**Task:** Write a custom derive macro that adds a `to_json()` method.\n\n**Prompt:**\n> Create a procedural derive macro called `ToJson` that generates a method `to_json(&self) -> String` for any struct where all fields implement `Display`. Use the `proc-macro2`, `quote`, and `syn` crates. Provide the macro crate (`tojson_derive`) and an example usage.\n\n**Example Result:**\nrust\n// tojson_derive/src/lib.rs\nuse proc_macro::TokenStream;\nuse quote::quote;\nuse syn::{parse_macro_input, DeriveInput};\n\n#[proc_macro_derive(ToJson)]\npub fn derive_to_json(input: TokenStream) -> TokenStream {\n let input = parse_macro_input!(input as DeriveInput);\n let name = &input.ident;\n let fields = if let syn::Data::Struct(data) = &input.data {\n &data.fields\n } else {\n panic!(\"ToJson only supports structs\");\n };\n\n let field_names: Vec<> = fields.iter().map(|f| &f.ident).collect();\n let field_strs: Vec<> = field_names.iter().map(|f| format!(\"{}\", f.as_ref().unwrap())).collect();\n\n let expanded = quote! {\n impl #name {\n pub fn to_json(&self) -> String {\n let mut parts = vec![];\n #(\n parts.push(format!(\"\\"{}\\": \\"{}\\"\", #field_strs, self.#field_names));\n )\n format!(\"{{{}}}\", parts.join(\", \"))\n }\n }\n };\n TokenStream::from(expanded)\n}\n\n\n### 9. Custom Allocator for Embedded Systems\n\n**Task:** Implement a simple bump allocator that works in `no_std` environment.\n\n**Prompt:**\n> Write a `no_std` compatible bump allocator in Rust that implements the `GlobalAlloc` trait. The allocator should pre-allocate a static byte array of 1024 bytes and serve allocations by incrementing a pointer. Include `alloc_init` function and an example using `alloc::boxed::Box`. Ensure it is safe for single-threaded use.\n\n**Example Result:**\nrust\n#![no_std]\n\nuse core::alloc::{GlobalAlloc, Layout};\nuse core::cell::UnsafeCell;\nuse core::sync::atomic::{AtomicUsize, Ordering};\n\nstruct BumpAllocator {\n heap: UnsafeCell<[u8; 1024]>,\n offset: AtomicUsize,\n}\n\nunsafe impl Sync for BumpAllocator {}\n\nunsafe impl GlobalAlloc for BumpAllocator {\n unsafe fn alloc(&self, layout: Layout) -> mut u8 {\n let size = layout.size();\n let align = layout.align();\n let current = self.offset.fetch_add(size, Ordering::SeqCst);\n let aligned = (current + align - 1) & !(align - 1);\n let ptr = (self.heap.get() as mut u8).add(aligned);\n ptr\n }\n\n unsafe fn dealloc(&self, _ptr: mut u8, layout: Layout) {\n // bump allocator does not free individually\n }\n}\n\n#[global_allocator]\nstatic ALLOCATOR: BumpAllocator = BumpAllocator {\n heap: UnsafeCell::new([0u8; 1024]),\n offset: AtomicUsize::new(0),\n};\n\n\n### 10. Wasm-Generated UI with Yew\n\n**Task:** Create a simple counter component using Yew 0.21.\n\n**Prompt:**\n> Write a Yew component that displays a counter with increment and decrement buttons. Use `use_state` hook. Compile to WebAssembly with `trunk`. Show the `main.rs`, `Cargo.toml`, and `index.html`.\n\n**Example Result:**\ntoml\n[package]\nname = \"yew-counter\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\nyew = { version = \"0.21\", features = [\"csr\"] }\n\n\nrust\nuse yew::prelude::;\n\n#[function_component]\nfn App() -> Html {\n let counter = use_state(|| 0);\n let on_increment = {\n let counter = counter.clone();\n Callback::from(move |_| counter.set(counter + 1))\n };\n let on_decrement = {\n let counter = counter.clone();\n Callback::from(move || counter.set(counter - 1))\n };\n\n html! {\n { \"Counter: \" } { counter }
\n \n \n
"excerpt": "A curated collection of 10 expert-level Rust prompts covering systems programming, CLI tools, and WebAssembly. Each prompt includes a task, exact prompt text, and a realistic code example with error handling, lifetimes, async, unsafe FFI, and procedural macros."
}
Comments