rust
48 lines · 8 steps
Parsing a URL query string in Rust
A byte-level percent-decoder feeds an iterator pipeline that splits a query string into a key-value map.
Explained by
highlit
1use std::collections::HashMap;
2
3fn decode_component(input: &str) -> String {
4 let bytes = input.as_bytes();
5 let mut out = Vec::with_capacity(bytes.len());
6 let mut i = 0;
7
8 while i < bytes.len() {
9 match bytes[i] {
10 b'+' => {
11 out.push(b' ');
12 i += 1;
13 }
14 b'%' if i + 2 < bytes.len() => {
15 let hi = (bytes[i + 1] as char).to_digit(16);
16 let lo = (bytes[i + 2] as char).to_digit(16);
17 match (hi, lo) {
18 (Some(hi), Some(lo)) => {
19 out.push((hi * 16 + lo) as u8);
20 i += 3;
21 }
22 _ => {
23 out.push(bytes[i]);
24 i += 1;
25 }
26 }
27 }
28 b => {
29 out.push(b);
30 i += 1;
31 }
32 }
33 }
34
35 String::from_utf8_lossy(&out).into_owned()
36}
37
38pub fn parse_query(query: &str) -> HashMap<String, String> {
39 query
40 .trim_start_matches('?')
41 .split('&')
42 .filter(|pair| !pair.is_empty())
43 .map(|pair| match pair.split_once('=') {
44 Some((k, v)) => (decode_component(k), decode_component(v)),
45 None => (decode_component(pair), String::new()),
46 })
47 .collect()
48}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Walking raw bytes with a manual index gives precise control over multi-byte escape sequences like percent-encoding.
- 2Guarded match arms let you branch on both a byte's value and surrounding conditions in one expression.
- 3An iterator pipeline ending in collect turns a query string into a HashMap without any explicit loop.
Related explainers
rust
use axum::{ extract::State, response::sse::{Event, KeepAlive, Sse}, Json,
Proxying an SSE chat stream in Axum
server-sent-events
streaming
async-generators
Advanced
10 steps
ruby
require "csv" class CsvExporter def initialize(records, columns: nil)
Turning records into CSV in Ruby
csv
data-export
serialization
Intermediate
7 steps
rust
#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FileKind { Png, Jpeg,
Detecting file types by magic bytes in Rust
pattern-matching
byte-slices
lookup-table
Intermediate
7 steps
rust
use crossbeam_channel::{Receiver, Sender, select, tick}; use std::time::Duration; pub enum Command {
A channel-driven worker loop in Rust
channels
select
message-passing
Intermediate
9 steps
php
<?php namespace App\Support;
Recursively finding files with SPL iterators in PHP
recursion
iterators
filesystem
Intermediate
7 steps
rust
use std::time::Duration; use axum::{ http::{header, HeaderValue, Request},
Serving fingerprinted assets in Axum
static-assets
http-caching
middleware
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/parsing-a-url-query-string-in-rust-explained-rust-ee83/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.