36. Cow<str> — Clone on Write
Stop cloning strings “just in case” — Cow<str> lets you borrow when you can and clone only when you must.
The problem
You’re writing a function that sometimes needs to modify a string and sometimes doesn’t. The easy fix? Clone every time:
| |
This works, but that first branch allocates a brand-new String even though name is already perfect as-is. In a hot loop, those wasted allocations add up.
Enter Cow<str>
Cow stands for Clone on Write. It holds either a borrowed reference or an owned value, and only clones when you actually need to mutate or take ownership:
| |
Now the happy path (name already starts with “Hello”) does zero allocation. The caller gets a Cow<str> that derefs to &str transparently — most code won’t even notice the difference.
Using Cow values
Because Cow<str> implements Deref<Target = str>, you can use it anywhere a &str is expected:
| |
When to reach for Cow
Cow shines in these situations:
- Conditional transformations — functions that modify input only sometimes (normalization, trimming, escaping)
- Config/lookup values — return a static default or a dynamically built string
- Parser outputs — most tokens are slices of the input, but some need unescaping
The Cow type works with any ToOwned pair, not just strings. You can use Cow<[u8]>, Cow<Path>, or Cow<[T]> the same way.
Quick reference
| Operation | Cost |
|---|---|
Cow::Borrowed(s) | Free — wraps a reference |
Cow::Owned(s) | Whatever creating the owned value costs |
*cow (deref) | Free |
cow.into_owned() | Free if already owned, clones if borrowed |
cow.to_mut() | Clones if borrowed, then gives &mut access |