parse_net/lib.rs
1//! # parse_net
2//!
3//! The grammar layer for Internet message fields: RFC 9110 field syntax,
4//! media types, RFC 9651 Structured Field Values, HTTP and RFC 5322 dates,
5//! content negotiation, entity tags, ranges, `Content-Disposition` with
6//! RFC 8187, `Cache-Control`, `Link`, `Forwarded`, authentication challenges,
7//! `Host`, `Origin`, and the email lexical layer, with safe writers for each.
8//!
9//! Protocol engines (http-net, ws-net, h2-net) frame messages; parse-net reads
10//! what is inside a field value and writes field values back out without ever
11//! emitting CR, LF, or NUL. It is `no_std`, needs no allocator for any parse,
12//! does no I/O, and has no dependencies.
13//!
14//! ## Tier 1
15//!
16//! The convention in every example is `use parse_net as pn;`:
17//!
18//! ```
19//! use parse_net as pn;
20//!
21//! assert!(!pn::VERSION.is_empty());
22//! ```
23//!
24//! The Tier 1 functions arrive from `0.3.0` on, one plain call per field:
25//!
26//! ```text
27//! pn::parse_media_type(b"text/html; charset=UTF-8")? // MediaType view
28//! pn::best_media(accept, &["text/html", "application/json"]) // Option<usize>
29//! pn::http_date_at(b"Sun, 06 Nov 1994 08:49:37 GMT", now)? // HttpDate
30//! pn::if_none_match(if_none_match, ¤t_etag)? // bool: answer 304
31//! pn::byte_ranges(range, file_len, &mut buf)? // RangeOutcome
32//! pn::parse_content_disposition(value)?.filename() // prefers filename*
33//! pn::sfv::parse_item(b"same-origin")? // Sec-Fetch-Site
34//! pn::parse_host_port(b"example.com:8443")? // HostPort
35//! ```
36//!
37//! ## Status
38//!
39//! Design lock. The public API is written down in `docs/API.md`, the design
40//! in `dev/PLAN.md`, and the milestone schedule in `dev/ROADMAP.md` (all in
41//! the [repository](https://github.com/jamesgober/parse-net)); the core ships
42//! in `0.3.0`.
43
44#![doc(html_root_url = "https://docs.rs/parse-net")]
45#![no_std]
46#![cfg_attr(docsrs, feature(doc_cfg))]
47#![forbid(unsafe_code)]
48#![deny(missing_docs)]
49#![deny(unused_must_use, unused_results)]
50#![cfg_attr(
51 not(test),
52 deny(
53 clippy::unwrap_used,
54 clippy::expect_used,
55 clippy::panic,
56 clippy::todo,
57 clippy::unimplemented,
58 clippy::unreachable,
59 clippy::dbg_macro,
60 clippy::print_stdout,
61 clippy::print_stderr,
62 clippy::indexing_slicing
63 )
64)]
65
66#[cfg(any(feature = "std", test))]
67extern crate std;
68
69#[cfg(feature = "alloc")]
70extern crate alloc;
71
72/// Crate version string, populated by Cargo at build time.
73///
74/// # Examples
75///
76/// ```
77/// assert_eq!(parse_net::VERSION.split('.').count(), 3);
78/// ```
79pub const VERSION: &str = env!("CARGO_PKG_VERSION");
80
81#[cfg(test)]
82mod tests {
83 use super::VERSION;
84
85 #[test]
86 fn test_version_matches_manifest() {
87 assert_eq!(VERSION, env!("CARGO_PKG_VERSION"));
88 assert_eq!(VERSION.split('.').count(), 3, "expected MAJOR.MINOR.PATCH");
89 }
90}