#206 Jun 16, 2026

206. trim_ascii — Trim Whitespace From &[u8] Without Going Through str

Got a &[u8] with leading or trailing whitespace? You don’t need to validate it as UTF-8 just to trim it.

The reflex is to convert to str first — which can fail and forces a UTF-8 check you may not want:

1
2
3
4
5
6
let raw: &[u8] = b"  42 \n";

// The detour: validate as UTF-8, trim, go back to bytes
let s = std::str::from_utf8(raw).unwrap(); // can panic on non-UTF-8
let trimmed = s.trim().as_bytes();
assert_eq!(trimmed, b"42");

Since Rust 1.80, byte slices trim themselves directly — no str, no validation, no panic path:

1
2
3
4
5
let raw: &[u8] = b"  42 \n";

assert_eq!(raw.trim_ascii(),       b"42");
assert_eq!(raw.trim_ascii_start(), b"42 \n");
assert_eq!(raw.trim_ascii_end(),   b"  42");

It strips ASCII whitespace (space, tab, newline, carriage return, form feed, vertical tab) from a &[u8] and hands back a borrowed sub-slice — zero allocation.

Best part: it’s a const fn, so it works where str::trim can’t:

1
2
const KEY: &[u8] = b"  secret  ".trim_ascii();
assert_eq!(KEY, b"secret");

Reach for it when you’re parsing bytes straight off a socket, file, or buffer and want to clean up edges before validating the rest.

← Previous 205. strip_prefix / strip_suffix — Remove a Prefix Once, Not Every Repeat Next → 207. if let Guards — Match a Pattern Inside a Guard, and Still Fall Through