rust
33 lines · 6 steps
Zero-copy HTML escaping with Cow in Rust
How Cow lets escape_html avoid allocating when there's nothing to escape.
Explained by
highlit
1use std::borrow::Cow;
2
3pub fn escape_html(input: &str) -> Cow<'_, str> {
4 let needs_escape = input
5 .bytes()
6 .any(|b| matches!(b, b'&' | b'<' | b'>' | b'"' | b'\''));
7
8 if !needs_escape {
9 return Cow::Borrowed(input);
10 }
11
12 let mut escaped = String::with_capacity(input.len() + 16);
13 for ch in input.chars() {
14 match ch {
15 '&' => escaped.push_str("&"),
16 '<' => escaped.push_str("<"),
17 '>' => escaped.push_str(">"),
18 '"' => escaped.push_str("""),
19 '\'' => escaped.push_str("'"),
20 other => escaped.push(other),
21 }
22 }
23
24 Cow::Owned(escaped)
25}
26
27pub fn render_comment(author: &str, body: &str) -> String {
28 format!(
29 "<article class=\"comment\">\n <h3>{}</h3>\n <p>{}</p>\n</article>",
30 escape_html(author),
31 escape_html(body),
32 )
33}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Cow lets a function return either a borrow or an owned value from one signature, deferring allocation until it's actually needed.
- 2A cheap upfront scan can spare the common case from any allocation at all.
- 3Pre-sizing the output buffer with with_capacity trims reallocations when you already know the growth is small.
Related explainers
rust
use axum::{ body::{Body, Bytes}, extract::Request, http::StatusCode,
Logging request and response sizes in Axum
middleware
http
streaming-bodies
Advanced
8 steps
rust
use once_cell::sync::Lazy; use regex::Regex; static CREDIT_CARD: Lazy<Regex> = Lazy::new(|| {
Redacting sensitive data from logs in Rust
regex
lazy-initialization
checksum-validation
Intermediate
9 steps
rust
use axum::{ extract::{FromRequestParts, Query}, http::{request::Parts, StatusCode}, };
Building a custom Axum extractor for query filters
extractors
query-parsing
enums
Intermediate
8 steps
rust
use std::sync::Arc; use axum::{ extract::{Multipart, State}, http::StatusCode,
Throttling file uploads in Axum with a Semaphore
concurrency
backpressure
multipart
Advanced
8 steps
rust
use once_cell::sync::Lazy; use regex::Regex; static NON_ALPHANUMERIC: Lazy<Regex> = Lazy::new(|| Regex::new(r"[^a-z0-9]+").unwrap());
Building URL slugs in Rust
string-processing
regex
transliteration
Intermediate
8 steps
rust
#[derive(Debug, Clone, PartialEq)] pub enum Token { Number(f64), Plus,
How a tokenizer turns text into tokens
lexing
enums
iterators
Intermediate
8 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/zero-copy-html-escaping-with-cow-in-rust-explained-rust-732a/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.