Rustlers Atom 2.8: Cow<T> - Clone On Write
April 18, 2026•279 words
Sometimes you want to efficiently return a string slice &str (no allocation) but sometimes you need to modify that string before returning it, which requires a String (heap allocation). Do you return String every time and pay the allocation cost even when you didn't change anything? Do you return Option<String> and make the caller confuse?
Rust provides a standard enum for this exact scenario: std::borrow::Cow (Clone-on-Write). Cow is a smart wrapper that can hold either a borrowed reference or an owned value.
pub enum Cow<'a, B>
where B: 'a + ToOwned + ?Sized
{
Borrowed(&'a B),
Owned(<B as ToOwned>::Owned),
}
Think of it as a Lazy Clone. It starts as a borrow. It stays a borrow as long as you only read. The moment you try to write to it or call .to_mut(), it clones the data into an owned instance (if it wasn't already owned) and lets you mutate that copy.
In Practice: Cow<str>
A common use case is string processing where changes are rare.
use std::borrow::Cow;
fn sanitize<'a>(input: &'a str) -> Cow<'a, str> {
if input.contains("bad_word") {
// Mutation needed: Allocate a new String
let replaced = input.replace("bad_word", "****");
Cow::Owned(replaced)
} else {
// No change needed: Just wrap the reference
Cow::Borrowed(input)
}
}
fn main() {
let s1 = "hello world";
let result1 = sanitize(s1); // Returns Cow::Borrowed
let s2 = "hello bad_word";
let result2 = sanitize(s2); // Returns Cow::Owned
// Cow implements Deref, so you can treat it like &str
println!("Result 1: {}", result1);
println!("Length: {}", result2.len());
}