url-escape-0.1.1/.cargo_vcs_info.json0000644000000001360000000000100130730ustar { "git": { "sha1": "8e38f9dc4b38bd25aae5208eb10d21feeda9a2be" }, "path_in_vcs": "" }url-escape-0.1.1/Cargo.toml0000644000000020210000000000100110640ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "url-escape" version = "0.1.1" authors = ["Magic Len "] include = ["src/**/*", "Cargo.toml", "README.md", "LICENSE"] description = "This library is for encoding/escaping special characters in URLs and decoding/unescaping URLs as well." homepage = "https://magiclen.org/url-escape" readme = "README.md" keywords = ["url", "escape", "unescape", "encode", "decode"] categories = ["encoding"] license = "MIT" repository = "https://github.com/magiclen/url-escape" resolver = "2" [dependencies.percent-encoding] version = "2.1" url-escape-0.1.1/Cargo.toml.orig000064400000000000000000000010470072674642500146040ustar 00000000000000[package] name = "url-escape" version = "0.1.1" authors = ["Magic Len "] edition = "2021" repository = "https://github.com/magiclen/url-escape" homepage = "https://magiclen.org/url-escape" keywords = ["url", "escape", "unescape", "encode", "decode"] categories = ["encoding"] description = "This library is for encoding/escaping special characters in URLs and decoding/unescaping URLs as well." readme = "README.md" license = "MIT" include = ["src/**/*", "Cargo.toml", "README.md", "LICENSE"] [dependencies] percent-encoding = "2.1"url-escape-0.1.1/LICENSE000064400000000000000000000020660072674642500127240ustar 00000000000000MIT License Copyright (c) 2021 magiclen.org (Ron Li) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. url-escape-0.1.1/README.md000064400000000000000000000030150072674642500131710ustar 00000000000000URL Escape ==================== [![CI](https://github.com/magiclen/url-escape/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/url-escape/actions/workflows/ci.yml) This library is for encoding/escaping special characters in URLs and decoding/unescaping URLs as well. ## Usage ### Encoding This crate provides some `encode_*` functions to encode URL text in different situations. For example, to put a text to a fragment, use the `encode_fragment` function. ```rust assert_eq!("a%20%3E%20b?", url_escape::encode_fragment("a > b?")); ``` The functions suffixed with `_to_writer`, `_to_vec` or `_to_string` are useful to generate URL text. ```rust let mut url = String::from("https://"); assert_eq!("admin%40example.com", url_escape::encode_userinfo_to_string("admin@example.com", &mut url)); url.push_str("@127.0.0.1/"); assert_eq!("%E4%B8%AD%E6%96%87%E5%AD%97/eng/12%2034", url_escape::encode_path_to_string("中文字/eng/12 34", &mut url)); url.push('/'); assert_eq!(r"56%2F78", url_escape::encode_component_to_string("56/78", &mut url)); url.push('?'); assert_eq!(r"a=1&b=a%20b%20c", url_escape::encode_query_to_string("a=1&b=a b c", &mut url)); assert_eq!("https://admin%40example.com@127.0.0.1/%E4%B8%AD%E6%96%87%E5%AD%97/eng/12%2034/56%2F78?a=1&b=a%20b%20c", url); ``` ### Decoding ```rust assert_eq!("中文字/eng/12 34", url_escape::decode("%E4%B8%AD%E6%96%87%E5%AD%97/eng/12%2034")); ``` ## Crates.io https://crates.io/crates/url-escape ## Documentation https://docs.rs/url-escape ## License [MIT](LICENSE)url-escape-0.1.1/src/decode/mod.rs000064400000000000000000000026020072674642500150520ustar 00000000000000use std::borrow::Cow; use std::io::{self, Write}; use std::str::from_utf8_unchecked; use crate::percent_encoding::percent_decode_str; /// Decode percent-encoded bytes in a given string. #[inline] pub fn decode>(text: &S) -> Cow { let pd = percent_decode_str(text.as_ref()); pd.decode_utf8_lossy() } /// Decode percent-encoded bytes in a given string to a mutable `String` reference and return the decoded string slice. #[inline] pub fn decode_to_string>(text: S, output: &mut String) -> &str { unsafe { from_utf8_unchecked(decode_to_vec(text, output.as_mut_vec())) } } /// Decode percent-encoded bytes in a given string to a mutable `Vec` reference and return the decoded data slice. #[inline] pub fn decode_to_vec>(text: S, output: &mut Vec) -> &[u8] { let text = text.as_ref(); let text_bytes = text.as_bytes(); let text_length = text_bytes.len(); output.reserve(text_length); let current_length = output.len(); let pd = percent_decode_str(text); output.extend(pd); &output[current_length..] } /// Decode percent-encoded bytes in a given string to a writer. #[inline] pub fn decode_to_writer, W: Write>(text: S, output: &mut W) -> Result<(), io::Error> { let pd = percent_decode_str(text.as_ref()); for s in pd { output.write_all(&[s])?; } Ok(()) } url-escape-0.1.1/src/encode/mod.rs000064400000000000000000000254650072674642500151000ustar 00000000000000// Ref: https://url.spec.whatwg.org/ use std::borrow::Cow; use std::io::{self, Write}; use std::str::from_utf8_unchecked; use crate::percent_encoding::{utf8_percent_encode, AsciiSet}; /// The C0 control percent-encode set are the C0 controls and U+007F (DEL). pub use percent_encoding::CONTROLS; /// Not an ASCII letter or digit. pub use percent_encoding::NON_ALPHANUMERIC; /// The fragment percent-encode set is the C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+003C (<), U+003E (>), and U+0060 (`). pub const FRAGMENT: &AsciiSet = &CONTROLS.add(b' ').add(b'"').add(b'<').add(b'>').add(b'`'); /// The query percent-encode set is the C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#), U+003C (<), and U+003E (>). /// /// The query percent-encode set cannot be defined in terms of the fragment percent-encode set due to the omission of U+0060 (`). pub const QUERY: &AsciiSet = &CONTROLS.add(b' ').add(b'"').add(b'#').add(b'<').add(b'>'); /// The special-query percent-encode set is the query percent-encode set and U+0027 ('). pub const SPECIAL_QUERY: &AsciiSet = &QUERY.add(b'\''); /// The path percent-encode set is the query percent-encode set and U+003F (?), U+0060 (`), U+007B ({), and U+007D (}). pub const PATH: &AsciiSet = &QUERY.add(b'?').add(b'`').add(b'{').add(b'}'); /// The userinfo percent-encode set is the path percent-encode set and U+002F (/), U+003A (:), U+003B (;), U+003D (=), U+0040 (@), U+005B ([) to U+005E (^), inclusive, and U+007C (|). pub const USERINFO: &AsciiSet = &PATH .add(b'/') .add(b':') .add(b';') .add(b'=') .add(b'@') .add(b'[') .add(b'\\') .add(b']') .add(b'^') .add(b'|'); /// The component percent-encode set is the userinfo percent-encode set and U+0024 ($) to U+0026 (&), inclusive, U+002B (+), and U+002C (,). pub const COMPONENT: &AsciiSet = &USERINFO.add(b'$').add(b'%').add(b'&').add(b'+').add(b','); /// The application/x-www-form-urlencoded percent-encode set is the component percent-encode set and U+0021 (!), U+0027 (') to U+0029 RIGHT PARENTHESIS, inclusive, and U+007E (~). pub const X_WWW_FORM_URLENCODED: &AsciiSet = &COMPONENT.add(b'!').add(b'\'').add(b'(').add(b')').add(b'~'); /// Encode text. #[inline] pub fn encode<'a, S: ?Sized + AsRef>( text: &'a S, ascii_set: &'static AsciiSet, ) -> Cow<'a, str> { Cow::from(utf8_percent_encode(text.as_ref(), ascii_set)) } /// Write text to a mutable `String` reference and return the encoded string slice. #[inline] pub fn encode_to_string<'a, S: AsRef>( text: S, ascii_set: &'static AsciiSet, output: &'a mut String, ) -> &'a str { unsafe { from_utf8_unchecked(encode_to_vec(text, ascii_set, output.as_mut_vec())) } } /// Write text to a mutable `Vec` reference and return the encoded data slice. pub fn encode_to_vec<'a, S: AsRef>( text: S, ascii_set: &'static AsciiSet, output: &'a mut Vec, ) -> &'a [u8] { let text = text.as_ref(); let text_bytes = text.as_bytes(); let text_length = text_bytes.len(); output.reserve(text_length); let current_length = output.len(); let pe = utf8_percent_encode(text, ascii_set); output.extend(pe.flat_map(|e| e.bytes())); &output[current_length..] } /// Write text to a writer. #[inline] pub fn encode_to_writer, W: Write>( text: S, ascii_set: &'static AsciiSet, output: &mut W, ) -> Result<(), io::Error> { let pe = utf8_percent_encode(text.as_ref(), ascii_set); for s in pe { output.write_all(s.as_bytes())?; } Ok(()) } macro_rules! encode_impl { ($(#[$attr: meta])* $escape_set:ident; $(#[$encode_attr: meta])* $encode_name: ident; $(#[$encode_to_string_attr: meta])* $encode_to_string_name: ident; $(#[$encode_to_vec_attr: meta])* $encode_to_vec_name: ident; $(#[$encode_to_writer_attr: meta])* $encode_to_writer_name: ident $(;)*) => { $(#[$encode_attr])* /// $(#[$attr])* #[inline] pub fn $encode_name>(text: &S) -> Cow { encode(text, $escape_set) } $(#[$encode_to_string_attr])* /// $(#[$attr])* #[inline] pub fn $encode_to_string_name>(text: S, output: &mut String) -> &str { encode_to_string(text, $escape_set, output) } $(#[$encode_to_vec_attr])* /// $(#[$attr])* #[inline] pub fn $encode_to_vec_name>(text: S, output: &mut Vec) -> &[u8] { encode_to_vec(text, $escape_set, output) } $(#[$encode_to_writer_attr])* /// $(#[$attr])* #[inline] pub fn $encode_to_writer_name, W: Write>(text: S, output: &mut W) -> Result<(), io::Error> { encode_to_writer(text, $escape_set, output) } }; } encode_impl! { /// The following characters are escaped: /// /// C0 controls and, /// /// * SPACE /// * `"` /// * `<` /// * `>` /// * ` /// /// and all code points greater than `~` (U+007E) are escaped. FRAGMENT; /// Encode text used in a fragment part. encode_fragment; /// Write text used in a fragment part to a mutable `String` reference and return the encoded string slice. encode_fragment_to_string; /// Write text used in a fragment part to a mutable `Vec` reference and return the encoded data slice. encode_fragment_to_vec; /// Write text used in a fragment part to a writer. encode_fragment_to_writer; } encode_impl! { /// The following characters are escaped: /// /// C0 controls and, /// /// * SPACE /// * `"` /// * `#` /// * `<` /// * `>` /// /// and all code points greater than `~` (U+007E) are escaped. QUERY; /// Encode text used in the query part. encode_query; /// Write text used in the query part to a mutable `String` reference and return the encoded string slice. encode_query_to_string; /// Write text used in the query part to a mutable `Vec` reference and return the encoded data slice. encode_query_to_vec; /// Write text used in the query part to a writer. encode_query_to_writer; } encode_impl! { /// The following characters are escaped: /// /// C0 controls and, /// /// * SPACE /// * `"` /// * `#` /// * `'` /// * `<` /// * `>` /// /// and all code points greater than `~` (U+007E) are escaped. /// /// The term "special" means whether a URL is special. A URL is special is the scheme of that URL is **ftp**, **file** , **http**, **https**, **ws**, or **wss**. SPECIAL_QUERY; /// Encode text used in the query part. encode_special_query; /// Write text used in the query part to a mutable `String` reference and return the encoded string slice. encode_special_query_to_string; /// Write text used in the query part to a mutable `Vec` reference and return the encoded data slice. encode_special_query_to_vec; /// Write text used in the query part to a writer. encode_special_query_to_writer; } encode_impl! { /// The following characters are escaped: /// /// C0 controls and, /// /// * SPACE /// * `"` /// * `#` /// * `<` /// * `>` /// * `?` /// * ` /// * `{` /// * `}` /// /// and all code points greater than `~` (U+007E) are escaped. PATH; /// Encode text used in the path part. encode_path; /// Write text used in the path part to a mutable `String` reference and return the encoded string slice. encode_path_to_string; /// Write text used in the path part to a mutable `Vec` reference and return the encoded data slice. encode_path_to_vec; /// Write text used in the path part to a writer. encode_path_to_writer; } encode_impl! { /// The following characters are escaped: /// /// C0 controls and, /// /// * SPACE /// * `"` /// * `#` /// * `/` /// * `:` /// * `;` /// * `<` /// * `=` /// * `>` /// * `?` /// * `@` /// * `[` /// * `\` /// * `]` /// * `^` /// * ` /// * `{` /// * `}` /// * `|` /// /// and all code points greater than `~` (U+007E) are escaped. USERINFO; /// Encode text used in the userinfo part. encode_userinfo; /// Write text used in the userinfo part to a mutable `String` reference and return the encoded string slice. encode_userinfo_to_string; /// Write text used in the userinfo part to a mutable `Vec` reference and return the encoded data slice. encode_userinfo_to_vec; /// Write text used in the userinfo part to a writer. encode_userinfo_to_writer; } encode_impl! { /// The following characters are escaped: /// /// C0 controls and, /// /// * SPACE /// * `"` /// * `#` /// * `$` /// * `%` /// * `&` /// * `+` /// * `,` /// * `/` /// * `:` /// * `;` /// * `<` /// * `=` /// * `>` /// * `?` /// * `@` /// * `[` /// * `\` /// * `]` /// * `^` /// * ` /// * `{` /// * `}` /// * `|` /// /// and all code points greater than `~` (U+007E) are escaped. /// /// It gives identical results to JavaScript's `encodeURIComponent()`. COMPONENT; /// Encode text used in a component. encode_component; /// Write text used in a component to a mutable `String` reference and return the encoded string slice. encode_component_to_string; /// Write text used in a component to a mutable `Vec` reference and return the encoded data slice. encode_component_to_vec; /// Write text used in a component to a writer. encode_component_to_writer; } encode_impl! { /// The following characters are escaped: /// /// C0 controls and, /// /// * SPACE /// * `!` /// * `"` /// * `#` /// * `$` /// * `%` /// * `&` /// * `'` /// * `(` /// * `)` /// * `+` /// * `,` /// * `/` /// * `:` /// * `;` /// * `<` /// * `=` /// * `>` /// * `?` /// * `@` /// * `[` /// * `\` /// * `]` /// * `^` /// * ` /// * `{` /// * `}` /// * `|` /// * `~` /// /// and all code points greater than `~` (U+007E) are escaped. X_WWW_FORM_URLENCODED; /// Encode text as a www-form-urlencoded text. encode_www_form_urlencoded; /// Write text as a urlencoded text to a mutable `String` reference and return the encoded string slice. encode_www_form_urlencoded_to_string; /// Write text as a www-form-urlencoded text to a mutable `Vec` reference and return the encoded data slice. encode_www_form_urlencoded_to_vec; /// Write text as a www-form-urlencoded text to a writer. encode_www_form_urlencoded_to_writer; } url-escape-0.1.1/src/lib.rs000064400000000000000000000025250072674642500136220ustar 00000000000000/*! # URL Escape This library is for encoding/escaping special characters in URLs and decoding/unescaping URLs as well. ## Usage ### Encoding This crate provides some `encode_*` functions to encode URL text in different situations. For example, to put a text to a fragment, use the `encode_fragment` function. ```rust assert_eq!("a%20%3E%20b?", url_escape::encode_fragment("a > b?")); ``` The functions suffixed with `_to_writer`, `_to_vec` or `_to_string` are useful to generate URL text. ```rust let mut url = String::from("https://"); assert_eq!("admin%40example.com", url_escape::encode_userinfo_to_string("admin@example.com", &mut url)); url.push_str("@127.0.0.1/"); assert_eq!("%E4%B8%AD%E6%96%87%E5%AD%97/eng/12%2034", url_escape::encode_path_to_string("中文字/eng/12 34", &mut url)); url.push('/'); assert_eq!(r"56%2F78", url_escape::encode_component_to_string("56/78", &mut url)); url.push('?'); assert_eq!(r"a=1&b=a%20b%20c", url_escape::encode_query_to_string("a=1&b=a b c", &mut url)); assert_eq!("https://admin%40example.com@127.0.0.1/%E4%B8%AD%E6%96%87%E5%AD%97/eng/12%2034/56%2F78?a=1&b=a%20b%20c", url); ``` ### Decoding ```rust assert_eq!("中文字/eng/12 34", url_escape::decode("%E4%B8%AD%E6%96%87%E5%AD%97/eng/12%2034")); ``` */ pub extern crate percent_encoding; mod decode; mod encode; pub use decode::*; pub use encode::*;