A generic URI parser in Rust that strictly adheres to IETF RFC 3986.
- Fast: Zero-copy parsing. Observed to be 2x ~ 25x faster than common URI parsers in Rust.
- Easy: Carefully designed and documented APIs. Handy percent-encoding utilities.
- Strict: Parses every possible URI defined in the RFC and denies anything else.
-
EStr
(Percent-encoded string slices):All components in a URI that may be percent-encoded are parsed as
EStr
s, which allows easy splitting and fast decoding:let query = "name=%E5%BC%A0%E4%B8%89&speech=%C2%A1Ol%C3%A9!"; let map: HashMap<_, _> = EStr::new(query) .split('&') .filter_map(|pair| pair.split_once('=')) .map(|(k, v)| (k.decode(), v.decode())) .filter_map(|(k, v)| k.into_string().ok().zip(v.into_string().ok())) .collect(); assert_eq!(map["name"], "张三"); assert_eq!(map["speech"], "¡Olé!");
-
Three variants of
Uri
for different use cases:Uri<&str>
: borrowed; immutable.Uri<&mut [u8]>
: borrowed; in-place mutable.Uri<String>
: owned; immutable.
Decode and extract query parameters in-place from a URI reference:
fn decode_and_extract_query( bytes: &mut [u8], ) -> Result<(Uri<&mut [u8]>, HashMap<&str, &str>), ParseError> { let mut uri = Uri::parse_mut(bytes)?; let map = if let Some(query) = uri.take_query() { query .split_view('&') .flat_map(|pair| pair.split_once_view('=')) .map(|(k, v)| (k.decode_in_place(), v.decode_in_place())) .flat_map(|(k, v)| k.into_str().ok().zip(v.into_str().ok())) .collect() } else { HashMap::new() }; Ok((uri, map)) } let mut bytes = *b"?lang=Rust&mascot=Ferris%20the%20crab"; let (uri, query) = decode_and_extract_query(&mut bytes)?; assert_eq!(query["lang"], "Rust"); assert_eq!(query["mascot"], "Ferris the crab"); // The query is taken from the `Uri`. assert!(uri.query().is_none()); // In-place decoding is like this if you're interested: assert_eq!(&bytes, b"?lang=Rust&mascot=Ferris the crabcrab");
- URI building.
- Reference resolution.
- Normalization and comparison.
- Host: IDNA encoding and DNS syntax checking.