Rustlers Atom 2.8: Cow<T> - Clone On Write

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());
}

You'll only receive email when they publish something new.

More from GSLF
All posts