We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Collections, Text and First Iterators step 3 of 21
Build a CSV record with one output buffer
Join fields into one CSV record, adding quotes where needed. Build the result in a shared output buffer instead of creating a new accumulated String for every field.
pub fn render_csv_line(fields: &[String]) -> String
Exact output rules
Preserve field order and place one comma between adjacent fields. Quote a field if it contains a comma, double quote, carriage return or newline. Surround that field with double quotes and write each double quote inside it twice. Copy every other character unchanged.
Do not quote other fields. Do not trim spaces, normalize line endings or add a record terminator. Tabs, other controls and Unicode are preserved; only the four characters above determine quoting in this exercise.
| Fields | Output |
|---|---|
a, b, c |
a,b,c |
a,b, c |
"a,b",c |
he said "hi" |
"he said ""hi""" |
| Two empty fields | , |
| No fields or one empty field | Empty string. |
An embedded newline stays inside its quoted field, so a single record may span multiple physical lines. The task uses familiar CSV quoting rules while allowing arbitrary Rust string contents; follow the rules here rather than adding separate character validation.
Allocation budget
A generated test builds 5000 fields, then measures allocator calls during render_csv_line. The call must make at most 20 allocation or reallocation requests through the harness's global allocator. Input construction and JSON serialization are outside the measured interval.
The counter measures requests, not allocated bytes, live memory or execution time. Exact counts depend on library and compiler behavior. Reusing one output String avoids allocating a separate formatted result for each field; reserving capacity can reduce growth requests further. Preserve correct quoting whether or not you choose to reserve space.
Small tests compare the whole output. The generated test checks its UTF-8 byte length and allocation budget, so those two checks alone do not establish that the generated record's contents are correct.
Why write! needs an import
The starter calls write! on a String but has not imported the trait that
provides the formatting method. Rust reports E0599. std::fmt::Write supplies
text-formatting methods for String; std::io::Write is for byte-oriented
outputs such as files and sockets.
Bringing the appropriate trait into scope enables method lookup. Trait methods still exist without the import and can also be called with fully qualified syntax. A missing import is one possible cause of E0599, not the explanation for every missing-method error.
This complete example writes formatted values into an existing String:
use std::fmt::Write as _;
fn main() {
let mut out = String::from("items=");
write!(&mut out, "{}", 3).unwrap();
out.push_str("; ready");
assert_eq!(out, "items=3; ready");
}
Formatting returns fmt::Result. That error represents a formatting failure, not every possible allocation failure. Writing these string contents into a String normally succeeds; adding the import still leaves CSV quoting to implement. You can also build this output entirely with push and push_str.
Append rather than rebuild
push appends a character, and push_str appends a string slice. If capacity
runs out, the buffer can grow and existing bytes may need to move.
String addition takes its left operand by value. An expression such as
out = out + part can reuse that String's buffer; it does not inherently
rebuild the whole prefix on each iteration. It may still need to grow.
By contrast, out = format!("{out}{part}") formats the accumulated prefix
into a new String each time. Repeatedly rebuilding a growing prefix can cause
quadratic copying work. Appending to the existing buffer avoids that pattern.
Plain join is useful for fields that need no transformation, but CSV quoting may require escaping individual characters. Keep one output buffer, insert separators as needed, and append either an unchanged field or its quoted form. Use write! when formatting values into that buffer helps; use format! when a separately owned formatted result is actually needed.
Submissions must compile, pass the output and budget checks, and pass Clippy with warnings treated as errors. Clippy does not replace performance testing.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.