rust
44 lines · 9 steps
Redacting sensitive data from logs in Rust
Compile regexes once and validate credit card matches with the Luhn checksum before masking them out of log text.
Explained by
highlit
1use once_cell::sync::Lazy;
2use regex::Regex;
3
4static CREDIT_CARD: Lazy<Regex> = Lazy::new(|| {
5 Regex::new(r"\b(?:\d[ -]*?){13,16}\b").unwrap()
6});
7
8static SSN: Lazy<Regex> = Lazy::new(|| {
9 Regex::new(r"\b\d{3}-\d{2}-\d{4}\b").unwrap()
10});
11
12fn luhn_valid(candidate: &str) -> bool {
13 let digits: Vec<u32> = candidate.chars().filter_map(|c| c.to_digit(10)).collect();
14 if !(13..=16).contains(&digits.len()) {
15 return false;
16 }
17 let sum: u32 = digits
18 .iter()
19 .rev()
20 .enumerate()
21 .map(|(i, &d)| {
22 if i % 2 == 1 {
23 let doubled = d * 2;
24 if doubled > 9 { doubled - 9 } else { doubled }
25 } else {
26 d
27 }
28 })
29 .sum();
30 sum % 10 == 0
31}
32
33pub fn redact(log: &str) -> String {
34 let cc_masked = CREDIT_CARD.replace_all(log, |caps: ®ex::Captures| {
35 let matched = &caps[0];
36 if luhn_valid(matched) {
37 "[REDACTED-CC]".to_string()
38 } else {
39 matched.to_string()
40 }
41 });
42
43 SSN.replace_all(&cc_masked, "[REDACTED-SSN]").into_owned()
44}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Lazy statics let you compile expensive resources like regexes exactly once and share them safely.
- 2A structural regex match isn't proof of a real value — pairing it with a checksum like Luhn cuts false positives.
- 3Passing a closure to replace_all lets each match be inspected and conditionally transformed.
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
php
<?php declare(strict_types=1);
Normalizing human names in PHP
unicode
text-normalization
transliteration
Intermediate
8 steps
rust
use std::borrow::Cow; pub fn escape_html(input: &str) -> Cow<'_, str> { let needs_escape = input
Zero-copy HTML escaping with Cow in Rust
clone-on-write
zero-copy
string-escaping
Intermediate
6 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
go
package middleware import ( "net/http"
A content-type guard middleware in Gin
middleware
closures
http
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/redacting-sensitive-data-from-logs-in-rust-explained-rust-c11b/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.