Rust's Cow (Copy-on-Write) is a smart pointer that enables lazy cloning. It's useful when data might be mutated or ownership might change, but you want to avoid unnecessary copies—ideal for read-heavy, write-rare scenarios.
pub enum Cow<'a, B: ?Sized + 'a>
where
B: ToOwned,
{
/// Borrowed data.
Borrowed(&'a B),
/// Owned data.
Owned(<B as ToOwned>::Owned),
}
The core idea: as long as you only read the data, a Cow holds a borrow. The moment you need to mutate it, it clones the underlying data in to an owned version and then modifies the clone. This avoids cloning when not needed.
Key Methods
to_mut()– returns a mutable reference to the owned data. If theCowis currently borrowed, it clones first.into_owned()– consumes theCowand returns the owned data, cloning if necessary.
Official Example
The standard library demonstrates three scenarios:
use std::borrow::Cow;
fn abs_all(input: &mut Cow<[i32]>) {
for i in 0..input.len() {
let v = input[i];
if v < 0 {
// Only clones when mutation is needed.
input.to_mut()[i] = -v;
}
}
}
// No clone: input is never mutated.
let slice = [0, 1, 2];
let mut input = Cow::from(&slice[..]);
abs_all(&mut input);
// Clone occurs: mutation is required.
let slice = [-1, 0, 1];
let mut input = Cow::from(&slice[..]);
abs_all(&mut input);
// No clone: input is already owned.
let mut input = Cow::from(vec![-1, 0, 1]);
abs_all(&mut input);
Observing Ownership Changes
We can track memory addresses to see when cloning actually happens. Here's a helper functon:
fn print_addr(s: &str) {
println!("{}", s);
let mut ptr = s.as_ptr();
for ch in s.chars() {
println!("\t{:p}\t{}", ptr, ch);
ptr = ptr.wrapping_add(ch.len_utf8());
}
}
Borrowed Data – Mutate Then Take Ownership
This is the most common pattern: start with a borrow, mutate, then extract ownership.
{
let s = String::from("AB");
print_addr(&s);
let mut cow = Cow::Borrowed(&s);
cow.to_mut().insert_str(1, "cd");
let owned = cow.into_owned();
print_addr(&owned);
}
// Output (addresses will differ each run):
// AB
// 0x7fb694c05af0 A
// 0x7fb694c05af1 B
// AcdB
// 0x7fb694c05b00 A
// 0x7fb694c05b01 c
// 0x7fb694c05b02 d
// 0x7fb694c05b03 B
The changed address confirms a clone occurred when to_mut() was called.
If you don't call to_mut(), no clone happens. Instead, use as_str() (or similar) for read-only access:
{
let s = String::from("AB");
print_addr(&s);
let mut cow = Cow::Borrowed(&s);
// No mutation – clone is avoided.
let view: &str = cow.as_str();
print_addr(view);
}
Mutating Already-Owned Data
When the Cow already owns the data, to_mut() returns a mutable reference without cloning.
{
let s1 = String::from("cd");
print_addr(&s1);
let mut cow1: Cow<'_, String> = Cow::Owned(s1);
cow1.to_mut().insert_str(0, "AB");
let owned1 = cow1.into_owned();
print_addr(&owned1);
}
// Output:
// cd
// 0x7fb694c05b10 c
// 0x7fb694c05b11 d
// ABcd
// 0x7fb694c05b10 A
// 0x7fb694c05b11 B
// 0x7fb694c05b12 c
// 0x7fb694c05b13 d
Notice the same base address – no copy was made. The string was mutated in place (two memcpy operations shift the content).
Implemantation Details
Cow is an enum with two variants. Any type that can be used with Cow must implement the ToOwned trait.
The ToOwned Trait
pub trait ToOwned {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
fn clone_into(&self, target: &mut Self::Owned) { ... }
}
pub trait Borrow<Borrowed> where Borrowed: ?Sized {
fn borrow(&self) -> &Borrowed;
}
The blanket implementation:
impl<T: ?Sized> Borrow<T> for T {
fn borrow(&self) -> &T { self }
}
impl<T> ToOwned for T where T: Clone {
type Owned = T;
fn to_owned(&self) -> T { self.clone() }
}
Method: to_mut()
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
match *self {
Borrowed(borrowed) => {
*self = Owned(borrowed.to_owned());
match *self {
Borrowed(..) => unreachable!(),
Owned(ref mut owned) => owned,
}
}
Owned(ref mut owned) => owned,
}
}
If currently borrowed, it replaces itself with the cloned owned variant. The ref mut pattern borrows the inner owned value mutably without moving it.
Method: into_owned()
pub fn into_owned(self) -> <B as ToOwned>::Owned {
match self {
Borrowed(borrowed) => borrowed.to_owned(),
Owned(owned) => owned,
}
}
Consumes the Cow and returns the owned value, cloning if needed.
Deref Implementation
impl<B: ?Sized + ToOwned> Deref for Cow<'_, B> {
type Target = B;
fn deref(&self) -> &B {
match *self {
Borrowed(borrowed) => borrowed,
Owned(ref owned) => owned.borrow(),
}
}
}
This allows Cow<str> to be used where &str is expected (deref coercion). For example, print_addr can accept both &str and &Cow<str>.