We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ownership I: Moves, Copy, Clone, Drop step 14 of 20
Moving out of &mut: take, replace, swap
Fix two ownership errors: rotate three owned strings with mem::swap, then
empty a borrowed buffer with mem::take. Keep the supplied drive parser.
pub fn rotate3(a: String, b: String, c: String) -> Vec<String>
pub fn drive(ops: Vec<String>) -> Vec<String>
Rotate three strings
rotate3 must return [c, a, b], moving each string one position to the right.
Use the supplied two calls to std::mem::swap; do not clone the strings or
replace the exercise with a directly reordered vector.
The starter tries to borrow immutable parameter bindings mutably. Declare the
three local parameter bindings mut so they can be swapped. The caller still
passes owned String values, not mutable references.
Track the contents after each operation:
Start: a = A, b = B, c = C
Swap a and b: a = B, b = A, c = C
Swap a and c: a = C, b = A, c = B
Return vec![a,b,c]: [C, A, B]
Empty strings, duplicates and Unicode strings follow the same rule. Swapping
the String values transfers their existing buffers; it does not clone their
text. Constructing the returned Vec is a separate operation.
Empty the buffer and return its contents
The supplied buffer stores pending strings and a flush counter:
struct Buffer {
pending: Vec<String>,
flushed: usize,
}
Fix Buffer::flush(&mut self) -> String so it takes the pending vector,
leaves an empty vector behind, increments the counter once and returns the
previous strings joined with commas. An empty flush returns "" and still
increments the counter.
The starter's let items = self.pending; cannot move a non-Copy field out
through a borrow of self. The caller still owns the buffer and expects its
field to remain usable. mem::take solves this by installing a replacement
while returning the old value.
Choose the replacement operation
| Operation | What remains in the destination | Return value |
|---|---|---|
mem::take(&mut place) |
T::default() |
Previous value |
mem::replace(&mut place, new) |
new |
Previous value |
mem::swap(&mut a, &mut b) |
Each place receives the other's value | () |
take requires T: Default; replace and swap do not. None of these
operations needs to clone the value. replace and swap do not drop the
values they transfer. Returned old values are dropped later unless their
caller moves or otherwise retains them.
For Vec<String>, the default replacement is an empty vector that does not
allocate. Its previous allocation moves with the returned vector, so pending
does not retain that capacity. The subsequent join constructs the output
string and may allocate. More generally, take calls the type's Default
implementation, which can allocate or panic; it is not universally free of
either behavior.
Follow the script exactly
drive recognizes these strings:
- Exactly
"flush": record the result of flushing. - A string beginning with
"push ": append everything after that prefix. - Any other string: ignore it.
"push " appends an empty string, but "push" is ignored. Extra spaces in
the appended text are preserved. The result contains all flush outputs in
order, followed by this summary:
flushes=COUNT|pending=LENGTH
For example, ["push a", "push b", "flush"] returns
["a,b", "flushes=1|pending=0"]. Adding another "flush" appends an empty
output and changes the summary to "flushes=2|pending=0". With no operations,
return ["flushes=0|pending=0"].
Use the standard idiom
mem::replace(&mut self.pending, Vec::new()) is valid Rust, but Clippy's
mem_replace_with_default recommends mem::take(&mut self.pending). This
exercise treats that warning as an error. Use replace when you want to
install a specific value rather than the default.
Output tests check the rotation and buffer behavior; they do not by themselves
prove that values were moved without cloning. Follow the requested operations
as well as returning the right values. The solution must compile and pass
clippy -D warnings.
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.