Skip to main content

Crate parse_net

Crate parse_net 

Source
Expand description

§parse_net

The grammar layer for Internet message fields: RFC 9110 field syntax, media types, RFC 9651 Structured Field Values, HTTP and RFC 5322 dates, content negotiation, entity tags, ranges, Content-Disposition with RFC 8187, Cache-Control, Link, Forwarded, authentication challenges, Host, Origin, and the email lexical layer, with safe writers for each.

Protocol engines (http-net, ws-net, h2-net) frame messages; parse-net reads what is inside a field value and writes field values back out without ever emitting CR, LF, or NUL. It is no_std, needs no allocator for any parse, does no I/O, and has no dependencies.

§Tier 1

The convention in every example is use parse_net as pn;. One plain call per field:

use parse_net as pn;

// Media types: one strict view, no copy.
let mt = pn::parse_media_type(b"text/html; charset=UTF-8")?;
assert!(mt.essence_is("text/html"));
assert!(mt.charset().is_some_and(|c| c.eq_ignore_ascii_case(b"utf-8")));

// Lists: commas inside quoted strings and comments do not split.
let codings: Vec<&[u8]> = pn::list(b"gzip, deflate;q=0.5, x=\"a,b\"")?.iter().collect();
assert_eq!(codings, [&b"gzip"[..], b"deflate;q=0.5", b"x=\"a,b\""]);

// HTTP-date: all three formats in, IMF-fixdate out.
let now = 1_792_540_800; // the caller's clock, Unix seconds
let d = pn::http_date_at(b"Sunday, 06-Nov-94 08:49:37 GMT", now)?;
assert_eq!(&d.format(), b"Sun, 06 Nov 1994 08:49:37 GMT");

// Host: real IPv4 and IPv6 validation, ports up to 65535.
let hp = pn::parse_host_port(b"[2001:db8::1]:8443")?;
assert_eq!(hp.port, Some(8443));
assert!(pn::parse_host_port(b"127.1").is_err()); // read as IPv4 by browsers: refused

// Writers cannot emit CR, LF, or NUL.
let mut buf = [0u8; 64];
let mut out = pn::SliceSink::new(&mut buf);
pn::media::write("text", "plain", &[("charset", "utf-8")], &mut out)?;
assert_eq!(out.written(), b"text/plain; charset=utf-8");
assert!(pn::write::write_field_value(b"x\r\nSet-Cookie: y", &mut out).is_err());

Errors carry a kind and an offset, never input bytes:

use parse_net as pn;

let err = pn::parse_media_type(b"text/ html").unwrap_err();
assert_eq!(err.kind(), pn::ErrorKind::InvalidMediaType);
assert_eq!(err.to_string(), "invalid media type at offset 5");

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, &current_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]>

§Status

The core, 0.3.0. The public API is written down in docs/API.md, the design in dev/PLAN.md, and the milestone schedule in dev/ROADMAP.md (all in the repository).

Re-exports§

pub use date::http_date;std
pub use date::Civil;
pub use date::DateFormat;
pub use date::HttpDate;
pub use date::http_date_at;
pub use host::Host;
pub use host::HostPort;
pub use host::parse_host_port;
pub use list::List;
pub use list::list;
pub use media::Boundary;
pub use media::MediaType;
pub use media::parse_media_type;
pub use param::Param;
pub use param::Params;
pub use text::Comment;
pub use text::Quoted;
pub use text::Word;
pub use write::CountSink;
pub use write::Sink;
pub use write::SliceSink;

Modules§

class
The byte classes of the ABNF, in one table.
date
The proleptic Gregorian calendar and HTTP-date (RFC 9110 section 5.6.7).
host
Host = uri-host [ ":" port ] (RFC 9110 section 7.2, citing RFC 3986 section 3.2.2), with real IPv4 and IPv6 validation.
list
The #rule lists of RFC 9110 section 5.6.1, including several field lines read as one list (section 5.3).
media
Media types: type "/" subtype parameters (RFC 9110 section 8.3.1), and the RFC 2046 multipart boundary.
num
Decimal digits with overflow checks.
param
Parameters: *( OWS ";" OWS [ parameter ] ) (RFC 9110 section 5.6.6).
pct
The percent-encoding primitive: validate, decode into a caller buffer, and encode with a named set and hex case.
scan
Byte search and field-value validation, eight bytes per step.
text
The lexical forms of RFC 9110 section 5.6: tokens, optional whitespace, quoted strings, words (token / quoted-string), and comments.
write
Output: the Sink trait, SliceSink, CountSink, and the writers for numbers, tokens, quoted strings, parameters, and field values.

Structs§

Full
A sink has no room for the bytes it was given.
Limits
The work and size bounds every parser enforces.
ParseError
Why a value was refused, and where.

Enums§

DuplicatePolicy
What a parameter parser does when a name repeats.
ErrorKind
What a parser refused.
WriteError
Why a writer refused.

Constants§

VERSION
Crate version string, populated by Cargo at build time.