Features
The list below is the plan for 1.0. What ships in the current version is under Status.
Field grammar
- Byte classes - every ABNF class (
tchar,qdtext,ctext,etagc,attr-char, MIMEtoken, RFC 3986, Structured Field keys and tokens) in one 1 KiB table, one load and one mask per byte. - Lexical forms - tokens, OWS (space and tab only), quoted strings with zero-copy access and buffer-free comparison, nested comments without recursion.
- Lists and parameters - quote- and comment-aware comma lists, several field lines read as one list without copying, parameters that refuse duplicates by default.
Field values
- Media types and negotiation - media types, RFC 2046 boundaries, exact q-values,
Accept,Accept-Language(RFC 4647),Accept-Encoding,Accept-Charset. - Dates - HTTP-date in all three formats with the RFC 9110 50-year rule, IMF-fixdate formatting, RFC 5322 date-time; years 1 to 9999.
- Caching and conditions - entity tags,
If-Match,If-None-Match,Range,Content-Range,If-Range,Cache-Control. - Downloads and links -
Content-Dispositionwith RFC 8187 decoding,Linkwithtitle*. - Proxies and auth -
Forwarded,X-Forwarded-*with a trust predicate that fails closed,Authorization,WWW-Authenticate. - Hosts and origins -
Hostwith real IPv4 and IPv6 validation,Originwith same-origin comparison. - Structured Fields - RFC 9651 Items, Lists, Dictionaries, every bare item type, parse and serialize.
- Email - folding, RFC 2047 encoded words in Q and B, MIME parameters with RFC 2231 continuations,
addr-spec,msg-id.
Reliability and safety
- No unsafe code -
#![forbid(unsafe_code)]; the SWAR scanners are plain safe Rust. - No allocation, no recursion - proved by a counting allocator and depth tests.
- Bounded work - every limit checked before the work it governs; linear time on every input.
- Tested to the byte - unit tests on every path, property tests, fuzz targets for every parser, RFC vectors and the httpwg Structured Field suite.
Note on performance: the target is at least 20% faster than the best Rust competitor for each comparable operation, at equal or stronger strictness. The measurements, the method, and the commands to reproduce them are in docs/PERFORMANCE.md.
Installation
Add to your Cargo.toml:
[]
= "0.9.0"
# Optional features:
= { = "0.9.0", = [
"alloc", # owned forms and Sink for Vec<u8>
"std", # SystemTime conversions and http_date() with the system clock
] }
Feature recommendations:
- Minimal (embedded, engines): no features;
no_std, no allocator. - Servers:
std. - Owned values:
alloc.
Quick Start
The convention is use parse_net as pn;.
use parse_net as pn;
// Media types: one strict view, no copy.
let mt = parse_media_type?;
assert!;
assert!;
// Lists: commas inside quoted strings and comments do not split.
let codings: = list?.iter.collect;
assert_eq!;
// HTTP-date: all three formats in, IMF-fixdate out.
let now = 1_792_540_800; // the caller's clock, Unix seconds
let d = http_date_at?;
assert_eq!;
// Host: real IPv4 and IPv6 validation, ports up to 65535.
let hp = parse_host_port?;
assert_eq!;
assert!; // read as IPv4 by browsers: refused
// Writers cannot emit CR, LF, or NUL.
let mut buf = ;
let mut out = new;
write?;
assert_eq!;
assert!;
# Ok::
Errors carry a kind and an offset, never input bytes:
use parse_net as pn;
let err = parse_media_type.unwrap_err;
assert_eq!;
assert_eq!;
The rest of Tier 1 arrives with 0.4.0 and 0.5.0 (see the roadmap):
pn::best_media(accept, &["text/html", "application/json"]) // Option<usize>
pn::if_none_match(if_none_match, ¤t_etag)? // bool: answer 304
pn::byte_ranges(range, file_len, &mut buf)? // RangeOutcome
pn::parse_content_disposition(value)?.filename() // prefers filename*
pn::response_cache_control(value)? // ResponseDirectives
pn::client_address(peer, pn::ForwardedSource::XForwardedFor(&lines), &trusted, 16)?
pn::sfv::parse_item(b"same-origin")? // Sec-Fetch-Site
pn::bearer(authorization)? // Option<&[u8]>
What it is not
- Not a protocol engine: message framing, start lines, and chunked bodies belong to http-net, h2-net, fcgi-net, and ws-net.
- Not a header map: the engine owns field storage.
- Not a URL parser (url-lib) or a base64 codec (encode-lib).
- Not cookie grammar (cookie-net) or a full email parser.
- Not a policy engine: it reports facts strictly; what to accept is the caller's call.
Status: feature complete
Current Version: 0.9.0 - beta: every planned field, for HTTP and for mail, benchmarked, reviewed, hardened, and in use by published consumers: http-net, cookie-net, and form-net.
Target: 1.0.0 stable, per the roadmap in dev/ROADMAP.md.
What's complete:
-
Errors and limits -
ParseError(8 bytes: kind and offset, never input bytes),ErrorKind,WriteError,Limitswith RFC-sourced defaults,DuplicatePolicy. -
Byte classes and scanning - every ABNF class in one 1 KiB table; SWAR byte search and field-value validation, eight bytes per step.
-
Writers -
Sink,SliceSink,CountSink,Vec<u8>(withalloc); tokens, quoted strings, words, parameters, field values, numbers; nothing half-written after an error. -
Lexical forms - tokens, OWS, quoted strings (zero-copy, buffer-free comparison), words, comments (nested, counted, never recursed).
-
Lists and parameters - quote- and comment-aware lists, several field lines as one list without copying, parameters that refuse duplicates by default, and RFC 6455 extension parameters whose value may be left out.
-
Media types - parsing, RFC 2046 boundaries,
charset, suffixes, writing, canonical form. -
HTTP-date - all three formats, the RFC 9110 50-year rule with an explicit clock, IMF-fixdate formatting, years 1 to 9999, the calendar functions;
SystemTimeconversions withstd. -
Host - reg-names, IPv4, IPv6, IPvFuture, ports; numeric names that browsers read as IPv4 refused.
-
Percent-encoding - validation, decoding into a caller buffer (UTF-8 checked, lowercase-only for Structured Fields), encoding with named sets.
-
Content negotiation -
Accept,Accept-Language(RFC 4647 lookup or filtering),Accept-Encoding,Accept-Charset, with q-values and an explicit outcome when a header is ignored. -
Conditional and range requests - entity tags with strong and weak comparison,
If-Match,If-None-Match,Rangeresolution that refuses abusive sets,Content-Range,If-Range. -
File names - RFC 8187 values and
Content-Dispositionwithfilename*preferred, decoded controls refused, path separators and bidi controls reported; every tc2231 case has a verdict. -
Caching, proxies, auth, origins -
Cache-Control,ForwardedandX-Forwarded-*with client-address resolution through trusted proxies only,AuthorizationandWWW-Authenticatewith redactedDebug,Originwith exact same-origin comparison. -
Structured Fields - RFC 9651 Items, Lists, and Dictionaries with every bare item type: views, a single-pass visitor, and a canonical writer, passing the httpwg parsing and serialisation suites in full.
-
Links - RFC 8288
Linkvalues, with the firstrelwinning andtitle*decoded. -
Email - RFC 5322 dates, header folding and unfolding, RFC 2047 encoded words (Q and B, read and written), MIME parameters with RFC 2231 continuations,
addr-spec, mailboxes, and message identifiers, for smtp-net and login validation. -
Owned forms - with
alloc, owned media types, entity tags, host-ports, and Structured Field values that give the same views back. -
Proof - unit tests on every path, property tests (no panic, round trips, writer-parser closure, combined lines), counting-allocator tests for every parse and write, RFC and tc2231 vectors, 38 fuzz targets including four differential oracles against
httpdate,mime,sfv, andbase64, and an example for every public item. -
Performance - at least 25% faster than the competing Rust crates on every compared operation (25% to 81%), without allocating: see docs/PERFORMANCE.md.
-
Hardening - an attack test for every threat in the model, every walker checked for linear time at 1 KiB, 64 KiB, and 1 MiB, and every fuzz target run for 24 hours: see docs/SECURITY.md.
What's planned next:
0.9.x: ws-net, smtp-net, and web-net on parse-net, then the release candidates.1.0.0: the full audit indocs/STABILITY-1.0.md, released on James's go; what stands open is in dev/READINESS-1.0.md.
Note on API stability: the API was locked at 0.2.0 (docs/API.md); names and signatures change only with a recorded decision until 1.0.0 freezes them, with the contract recorded in docs/STABILITY-1.0.md.
Documentation & Resources
- API Reference - every public item with examples
- Grammar - each field's ABNF, case rules, and leniencies
- Architecture - modules, the byte-class table, views, and algorithms
- Performance - benchmarks against the competing crates, and the method
- Security - the threat model, its tests, and how to report a vulnerability
- Platform notes - features,
no_stdand bare-metal builds, stack use - Migration - moving http-net and ws-net onto parse-net
- Plan - design, threats, and decisions
- Roadmap - versions and exit criteria
- Changelog - every change
- docs.rs - rendered API documentation
- crates.io - the crate
Version Compatibility
- Rust: 1.85+ (edition 2024)
- MSRV Policy: after
1.0.0, an MSRV raise is a major change - API Stability: pre-1.0; the API may change at each minor version until
1.0.0 - Targets: anything with
core;thumbv7em-none-eabiis checked in CI
Development Setup
Contributing
See dev/DIRECTIVES.md for engineering standards and the definition of done. Before a PR: cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-features must be clean.