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, 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. Numbers are published in
docs/PERFORMANCE.mdfrom0.6.0; until then they are targets, not measurements.
Installation
Add to your Cargo.toml:
[]
= "0.4.0"
# Optional features:
= { = "0.4.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: extended
Current Version: 0.4.0 - the core plus the web layer and what form-net needs.
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.
- 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 and a single-pass visitor, passing the httpwg structured-field-tests suite in full.
- 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, 27 fuzz targets including three differential oracles against
httpdate,mime, andsfv.
What's planned next:
0.5.0:Link, Structured Field writing, the email lexical layer, owned forms,docs/ARCHITECTURE.md.0.6.0: benchmarks against the named competitors anddocs/PERFORMANCE.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
- 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.