Skip to main content

pct_str/
lib.rs

1//! This crate provides two types, [`PctStr`] and [`PctString`], similar to `str` and [`String`],
2//! representing percent-encoded strings used in URL, URI, IRI, etc.
3//! You can use them to encode, decode and compare percent-encoded strings.
4//!
5//! # Basic usage
6//!
7//! You can parse/decode percent-encoded strings by building a [`PctStr`] slice over a `str` slice.
8//!
9//! ```
10//! use pct_str::PctStr;
11//!
12//! let pct_str = PctStr::new("Hello%20World%21").unwrap();
13//! assert_eq!(pct_str, "Hello World!");
14//!
15//! let decoded_string: String = pct_str.decode();
16//! assert_eq!(decoded_string, "Hello World!")
17//! ```
18//!
19//! To create new percent-encoded strings, use the [`PctString`] to copy or encode new strings.
20//!
21//! ```
22//! use pct_str::{PctString, UriReserved};
23//!
24//! // Copy the given percent-encoded string.
25//! let pct_string = PctString::new("Hello%20World%21").unwrap();
26//!
27//! // Encode the given regular string.
28//! let pct_string = PctString::encode("Hello World!".chars(), UriReserved::Any);
29//!
30//! assert_eq!(pct_string.as_str(), "Hello%20World%21");
31//! ```
32//!
33//! You can choose which character will be percent-encoded by the `encode` function
34//! by implementing the [`Encoder`] trait.
35//!
36//! ```
37//! use pct_str::{UriReserved, PctString};
38//!
39//! struct CustomEncoder;
40//!
41//! impl pct_str::Encoder for CustomEncoder {
42//!   fn encode(&self, c: char) -> bool {
43//!     UriReserved::Any.encode(c) || c.is_uppercase()
44//!   }
45//! }
46//!
47//! let pct_string = PctString::encode("Hello World!".chars(), CustomEncoder);
48//! assert_eq!(pct_string.as_str(), "%48ello%20%57orld%21")
49//! ```
50//!
51//! [`String`]: std::string::String
52//! [`PctStr`]: crate::nsized::PctStr
53//! [`PctString`]: crate::sized::PctString
54//! [`Encoder`]: crate::encoder::Encoder
55#![cfg_attr(not(feature = "std"), no_std)]
56
57mod encoder;
58mod error;
59mod nsized;
60#[cfg(feature = "std")]
61mod sized;
62pub(crate) mod util;
63
64pub use encoder::*;
65pub use error::*;
66pub use nsized::*;
67#[cfg(feature = "std")]
68pub use sized::*;
69
70#[cfg(test)]
71mod tests {
72	use std::convert::TryInto;
73
74	use super::*;
75
76	#[test]
77	fn pct_encoding_invalid() {
78		let s = "%FF%FE%20%4F";
79		assert!(PctStr::new(s).is_err());
80		let s = "%36%A";
81		assert!(PctStr::new(s).is_err());
82		let s = "%%32";
83		assert!(PctStr::new(s).is_err());
84		let s = "%%32";
85		assert!(PctStr::new(s).is_err());
86	}
87
88	#[test]
89	fn pct_encoding_valid() {
90		let s = "%00%5C%F4%8F%BF%BD%69";
91		assert!(PctStr::new(s).is_ok());
92		let s = "No percent.";
93		assert!(PctStr::new(s).is_ok());
94		let s = "%e2%82%acwat";
95		assert!(PctStr::new(s).is_ok());
96	}
97
98	#[test]
99	fn try_from() {
100		let s = "%00%5C%F4%8F%BF%BD%69";
101		let _pcs = PctString::try_from(s).unwrap();
102		let _pcs: &PctStr = s.try_into().unwrap();
103	}
104
105	#[test]
106	fn encode_percent_always() {
107		struct NoopEncoder;
108		impl Encoder for NoopEncoder {
109			fn encode(&self, _: char) -> bool {
110				false
111			}
112		}
113		let s = "%";
114		let c = PctString::encode(s.chars(), NoopEncoder);
115		assert_eq!(c.as_str(), "%25");
116	}
117}