rust
42 lines · 7 steps
Avoiding allocations with Cow in Rust
How Cow<str> lets string helpers borrow when nothing changes and only allocate when they must.
Explained by
highlit
1use std::borrow::Cow;
2
3fn sanitize_filename(input: &str) -> Cow<'_, str> {
4 if input.chars().all(|c| c.is_alphanumeric() || matches!(c, '.' | '-' | '_')) {
5 return Cow::Borrowed(input);
6 }
7
8 let cleaned: String = input
9 .chars()
10 .map(|c| match c {
11 c if c.is_alphanumeric() => c,
12 '.' | '-' | '_' => c,
13 _ => '_',
14 })
15 .collect();
16
17 Cow::Owned(cleaned)
18}
19
20fn strip_prefix<'a>(path: &'a str, base: &str) -> Cow<'a, str> {
21 match path.strip_prefix(base) {
22 Some(rest) => Cow::Borrowed(rest.trim_start_matches('/')),
23 None => Cow::Borrowed(path),
24 }
25}
26
27fn ensure_extension(name: Cow<'_, str>, ext: &str) -> Cow<'_, str> {
28 if name.ends_with(ext) {
29 name
30 } else {
31 let mut owned = name.into_owned();
32 owned.push_str(ext);
33 Cow::Owned(owned)
34 }
35}
36
37fn build_asset_key(raw_path: &str, base: &str) -> String {
38 let relative = strip_prefix(raw_path, base);
39 let safe = sanitize_filename(&relative);
40 let finalized = ensure_extension(safe, ".bin");
41 finalized.into_owned()
42}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Cow lets a function return either a borrowed slice or an owned String behind one type, deferring allocation until it's genuinely needed.
- 2Checking the common case first and returning Cow::Borrowed keeps the fast path allocation-free.
- 3Chaining Cow-returning helpers preserves borrows across steps, so a single into_owned at the end materializes the result at most once.
Related explainers
rust
use axum::{ body::Bytes, extract::State, http::{HeaderMap, StatusCode},
Verifying Stripe webhook signatures in Axum
hmac
webhooks
constant-time-comparison
Intermediate
8 steps
rust
use axum::{ body::Body, extract::Request, http::{header, StatusCode},
How bearer-auth middleware works in Axum
middleware
authentication
request extensions
Intermediate
7 steps
rust
use axum::{ http::StatusCode, response::IntoResponse, routing::get,
Serving an SPA and API with Axum
routing
static-files
spa-fallback
Intermediate
7 steps
rust
use std::time::{Duration, Instant}; pub struct TokenBucket { capacity: f64,
A token bucket rate limiter in Rust
rate-limiting
token-bucket
lazy-refill
Intermediate
8 steps
rust
use axum::{ extract::{Path, State}, http::StatusCode, routing::get,
Building a JSON user API in Axum
routing
shared-state
json-serialization
Intermediate
8 steps
rust
use std::time::Duration; use axum::{ http::{header, HeaderValue, Method},
Configuring CORS on an Axum Router
cors
middleware
http-headers
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/avoiding-allocations-with-cow-in-rust-explained-rust-d2ec/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.