sorug
sorug is an ultra-high-performance, zero-copy, WHATWG URL Living Standard-compliant URL parser written in Rust. It targets production parsers that need correctness and nanosecond-scale throughput — and currently outperforms both servo/rust-url and ada-url on the hot paths that matter.
Why sorug?
| Pillar | What it means |
|---|---|
| Zero-Copy | Canonical ASCII inputs stay borrowed (Backing::Borrowed); heap allocation only on first required mutation (CoW). |
| SIMD / SWAR | 64-bit scheme-prefix jumps + SWAR delimiter scans for short inputs; memchr for longer buffers. |
| Custom Punycode | Lightweight in-crate Punycode / minimal UTS #46 — no heavy idna dependency. |
| 891 / 891 WPT | Full pass of the Web Platform Tests urltestdata suite shipped in-tree. |
| 278 / 278 setters | Full pass of WPT setters_tests.json (component mutators). |
forbid(unsafe_code) |
Zero unsafe in library code. Correctness first; speed without memory-safety shortcuts. |
Benchmarks
Criterion, Linux, release profile (lto = true, codegen-units = 1). Lower is better (nanoseconds / parse).
| Workload | sorug | ada-url | servo/url |
|---|---|---|---|
Fast Path ASCII (https://example.com/api/v1/users) |
30.9 ns | 31.5 ns | 97.6 ns |
| Complex Query / Fragment | 53.1 ns | 141 ns | 193 ns |
| IDNA / Punycode | 171 ns | 239 ns | 243 ns |
| File Edge Case | 30.8 ns | 91.6 ns | 129 ns |
Reproduce locally:
Numbers are indicative. Absolute values vary by CPU; relative ordering is what we track.
Quick start
[]
= "0.2"
use Url;
Mutate components (WHATWG / WPT setters) and edit the query as form-urlencoded pairs:
use ;
let mut url = parse?;
url.set_pathname;
url.set_search;
assert_eq!;
let mut params = parse;
params.append;
url.set_search_params;
assert_eq!;
Relative resolution with a base URL:
use Url;
let base = parse?;
let joined = parse_with_base?;
assert_eq!;
Git dependency (tracking main):
[]
= { = "https://github.com/hocestnonsatis/sorug" }
Current Status & Roadmap
Today
- Published on crates.io; in-tree version
0.2.0. - WPT parser: 891 / 891; WPT setters: 278 / 278.
- Public API: parse + getters,
origin, component setters,SearchParams/ form-urlencoded. - Docs: docs.rs/sorug.
Next
- Stabilize public API toward
1.0. join/make_relative, optional serde, optionalno_std(+alloc).- Continued differential testing against rust-url / ada where intentional divergences are documented.
Not goals (for now)
- Matching every historical quirk of non-WHATWG parsers.
- Trading
forbid(unsafe_code)for micro-wins.
Design sketch
- Index-based record — component boundaries are
u32offsets into the WHATWGhrefserialization. - Lazy / CoW serialization — borrow when input is already canonical; upgrade to owned on mutation.
- Strict state machine — transitions follow the URL Living Standard basic URL parser.
Testing
See CONTRIBUTING.md for policies, style, and review expectations.
License
Licensed under either of
at your option.
Code of Conduct
Participation is governed by our Code of Conduct.