diff --git a/rust-url-todo b/rust-url-todo new file mode 100644 index 000000000..6aeefbf13 --- /dev/null +++ b/rust-url-todo @@ -0,0 +1,14 @@ +* standalone path parsing? +* Test setters + * Test trim C0/space + * Test remove tab & newline + + + +#[test] +fn test_path_segments() { + let mut url = Url::parse("http://example.net").unwrap(); + url.push_path_segment("foo").unwrap(); + url.extend_path_segments(&["bar", "b/az"]).unwrap(); + assert_eq!(url.as_str(), "http://example.net/foo"); +} diff --git a/src/percent_encoding.rs b/src/percent_encoding.rs index 854ad0e67..6767dd664 100644 --- a/src/percent_encoding.rs +++ b/src/percent_encoding.rs @@ -6,6 +6,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! URLs use special chacters to indicate the parts of the request. For example, a forward slash +//! indicates a path. In order for that charcter to exist outside of a path separator, that +//! charcter would need to be encoded. +//! +//! Percent encoding replaces reserved charcters with the `%` escape charcter followed by hexidecimal +//! ASCII representaton. For non-ASCII charcters that are percent encoded, a UTF-8 byte sequence +//! becomes percent encoded. A simple example can be seen when the space literal is replaced with +//! `%20`. +//! +//! Percent encoding is further complicated by the fact that different parts of an URL have +//! different encoding requirements. In order to support the variety of encoding requirements, +//! `url::percent_encoding` includes different *encode sets*. +//! See [URL Standard](https://url.spec.whatwg.org/#percent-encoded-bytes) for details. +//! +//! This module provides some `*_ENCODE_SET` constants. +//! If a different set is required, it can be created with +//! the [`define_encode_set!`](../macro.define_encode_set!.html) macro. +//! +//! # Examples +//! +//! ``` +//! use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET}; +//! +//! assert_eq!(utf8_percent_encode("foo bar?", DEFAULT_ENCODE_SET).to_string(), "foo%20bar%3F"); +//! ``` + use encoding; use std::ascii::AsciiExt; use std::borrow::Cow; @@ -77,6 +103,9 @@ macro_rules! define_encode_set { } /// This encode set is used for the path of cannot-be-a-base URLs. +/// +/// All ASCII charcters less than hexidecimal 20 and greater than 7E are encoded. This includes +/// special charcters such as line feed, carriage return, NULL, etc. #[derive(Copy, Clone, Debug)] #[allow(non_camel_case_types)] pub struct SIMPLE_ENCODE_SET; @@ -90,21 +119,39 @@ impl EncodeSet for SIMPLE_ENCODE_SET { define_encode_set! { /// This encode set is used in the URL parser for query strings. + /// + /// Aside from special chacters defined in the [`SIMPLE_ENCODE_SET`](struct.SIMPLE_ENCODE_SET.html), + /// space, double quote ("), hash (#), and inequality qualifiers (<), (>) are encoded. pub QUERY_ENCODE_SET = [SIMPLE_ENCODE_SET] | {' ', '"', '#', '<', '>'} } define_encode_set! { /// This encode set is used for path components. + /// + /// Aside from special chacters defined in the [`SIMPLE_ENCODE_SET`](struct.SIMPLE_ENCODE_SET.html), + /// space, double quote ("), hash (#), inequality qualifiers (<), (>), backtick (`), + /// question mark (?), and curly brackets ({), (}) are encoded. pub DEFAULT_ENCODE_SET = [QUERY_ENCODE_SET] | {'`', '?', '{', '}'} } define_encode_set! { /// This encode set is used for on '/'-separated path segment + /// + /// Aside from special chacters defined in the [`SIMPLE_ENCODE_SET`](struct.SIMPLE_ENCODE_SET.html), + /// space, double quote ("), hash (#), inequality qualifiers (<), (>), backtick (`), + /// question mark (?), and curly brackets ({), (}), percent sign (%), forward slash (/) are + /// encoded. pub PATH_SEGMENT_ENCODE_SET = [DEFAULT_ENCODE_SET] | {'%', '/'} } define_encode_set! { /// This encode set is used for username and password. + /// + /// Aside from special chacters defined in the [`SIMPLE_ENCODE_SET`](struct.SIMPLE_ENCODE_SET.html), + /// space, double quote ("), hash (#), inequality qualifiers (<), (>), backtick (`), + /// question mark (?), and curly brackets ({), (}), forward slash (/), colon (:), semi-colon (;), + /// equality (=), at (@), backslash (\\), square brackets ([), (]), caret (\^), and pipe (|) are + /// encoded. pub USERINFO_ENCODE_SET = [DEFAULT_ENCODE_SET] | { '/', ':', ';', '=', '@', '[', '\\', ']', '^', '|' } @@ -113,6 +160,15 @@ define_encode_set! { /// Return the percent-encoding of the given bytes. /// /// This is unconditional, unlike `percent_encode()` which uses an encode set. +/// +/// # Examples +/// +/// ``` +/// use url::percent_encoding::percent_encode_byte; +/// +/// assert_eq!("foo bar".bytes().map(percent_encode_byte).collect::(), +/// "%66%6F%6F%20%62%61%72"); +/// ``` pub fn percent_encode_byte(byte: u8) -> &'static str { let index = usize::from(byte) * 3; &"\ @@ -146,6 +202,14 @@ pub fn percent_encode_byte(byte: u8) -> &'static str { /// that also implements `Display` and `Into>`. /// The latter returns `Cow::Borrowed` when none of the bytes in `input` /// are in the given encode set. +/// +/// # Examples +/// +/// ``` +/// use url::percent_encoding::{percent_encode, DEFAULT_ENCODE_SET}; +/// +/// assert_eq!(percent_encode(b"foo bar?", DEFAULT_ENCODE_SET).to_string(), "foo%20bar%3F"); +/// ``` #[inline] pub fn percent_encode(input: &[u8], encode_set: E) -> PercentEncode { PercentEncode { @@ -157,6 +221,14 @@ pub fn percent_encode(input: &[u8], encode_set: E) -> PercentEncod /// Percent-encode the UTF-8 encoding of the given string. /// /// See `percent_encode()` for how to use the return value. +/// +/// # Examples +/// +/// ``` +/// use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET}; +/// +/// assert_eq!(utf8_percent_encode("foo bar?", DEFAULT_ENCODE_SET).to_string(), "foo%20bar%3F"); +/// ``` #[inline] pub fn utf8_percent_encode(input: &str, encode_set: E) -> PercentEncode { percent_encode(input.as_bytes(), encode_set) @@ -241,6 +313,14 @@ impl<'a, E: EncodeSet> From> for Cow<'a, str> { /// that also implements `Into>` /// (which returns `Cow::Borrowed` when `input` contains no percent-encoded sequence) /// and has `decode_utf8()` and `decode_utf8_lossy()` methods. +/// +/// # Examples +/// +/// ``` +/// use url::percent_encoding::percent_decode; +/// +/// assert_eq!(percent_decode(b"foo%20bar%3F").decode_utf8().unwrap(), "foo bar?"); +/// ``` #[inline] pub fn percent_decode(input: &[u8]) -> PercentDecode { PercentDecode {