Minimize heap allocations by passing iterators directly to functions instead of collecting them into vectors, allowing values to be moved rather than cloned. Change your function signature to accept impl Iterator<Item = String> and use .next() to consume values without intermediate storage.
fn build_config<I: Iterator<Item = String>>(mut args: I) -> Result<Config, String> {
let _program_name = args.next().ok_or("No program name")?;
let query = args.next().ok_or("No query")?;
let file_path = args.next().ok_or("No file path")?;
Ok(Config { query, file_path })
}
fn main() {
let config = build_config(std::env::args());
}