1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! # URI percent encoding/decoding ("URI Escaping")
//!
//! This module was written before the author was aware of the [`percent-encode`] crate.
//! Nonetheless, it has some convenient features that are not present in that crate,
//! so it remains in the X-URI crate for now.
//!
//! [`percent-encode`]: https://docs.rs/percent-encoding/2.0.0/percent_encoding/index.html
//!
//! It focuses solely on percent encoding/decoding of UTF8-encoded strings, treating all
//! percent-encoded strings that would otherwise decode to invalid UTF8 as themselves invalid.
//!
//! The primary interface to encoding and decoding is a provided trait that extends `str`:
//! [`StrExt`].
//!
//! Percent encoding is performed by [`escape_uri()`], which returns an iterator that
//! escapes the string. Likewise, percent decoding is performed by [`unescape_uri()`].
//!
//! As a special case, the trait also provides [`unescape_uri_in_place()`], which performs
//! in-place percent-decoding for a mutable string slice.
//!
//! # Usage Patterns
//!
//! The iterators returned by [`escape_uri()`] and [`unescape_uri()`] both implement
//! [`core::fmt::Display`], and thus also implement [`std::string::ToString`]:
//!
//! ```
//! use lwuri::prelude::*;
//! let escaped_string = "This needs escaping".escape_uri().to_string();
//!
//! assert_eq!(&escaped_string, "This%20needs%20escaping");
//! ```
//!
//! Both methods also implent `From<Cow<str>>`:
//!
//! ```
//! # use lwuri::prelude::*;
//! use std::borrow::Cow;
//! use std::convert::From;
//! let escaped_cow_str = Cow::from("This needs escaping?+3".escape_uri());
//!
//! assert_eq!(&escaped_cow_str, "This%20needs%20escaping%3F+3");
//! ```
//!
//! # Changing Behavior
//!
//! There is no one-size-fits-all escaping strategy for URIs: Some parts need to be excaped
//! differently than others. For example, *path segments* must have the `?` character escaped to
//! `%3F`, but this character is perfectly acceptable in the *query component*. Also, query
//! components have historically escaped the space character (` `) to the plus (`+`)
//! character, so pluses need to be escaped to `%2B`.
//!
//! By default, [`StrExt::escape_uri`] produces an iterator suitable for encoding *path segments*,
//! but other cases are handled by calling a modifier method on the [`EscapeUri`] iterator:
//!
//! ```
//! # use lwuri::prelude::*;
//! let escaped_string = "This needs escaping?+3".escape_uri().for_query().to_string();
//!
//! assert_eq!(&escaped_string, "This+needs+escaping?%2B3");
//! ```
//!
//! The [`EscapeUri`] iterator also provides the modifier methods `for_fragment()` and `full()`
//! for encoding URI fragments and performing full percent encoding, respectively.
//!
//! ## Skipping Slashes
//!
//! The [`UnescapeUri`] iterator provides a modifier method for assisting in decoding the
//! entire URI *path component* (as opposed to individual *path segments*) where encoded
//! slashes (`%2F`) are not decoded, preserving the hierarchy:
//!
//! ```
//! # use lwuri::prelude::*;
//! let escaped_string = "/this/p%20a%20t%20h/has%2Fextra/segments";
//!
//! let unescaped = escaped_string.unescape_uri().to_string();
//! assert_eq!(&unescaped, "/this/p a t h/has/extra/segments");
//!
//! let unescaped = escaped_string.unescape_uri().skip_slashes().to_string();
//! assert_eq!(&unescaped, "/this/p a t h/has%2Fextra/segments");
//! ```
//!
//! # Handling Encoding Errors
//!
//! While [`escape_uri()`] cannot fail, an escaped string can contain errors.
//! In situations where escaped characters cannot be properly decoded, the
//! [`unescape_uri()`] iterator will by default insert replacement characters
//! where errors are detected:
//!
//! * Illegal escaped UTF8 errors are replaced with [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] (`�`).
//! * Escaped ASCII control codes are decoded as [Unicode Control Pictures] like `␀` and `␊`.
//! * Unescaped ASCII control codes are dropped entirely.
//!
//! In cases where this is not appropriate, the iterator for [`unescape_uri()`] ([`UnescapeUri`])
//! provides the following methods:
//!
//! * [`first_error()`]\: Returns the location of the first detected encoding error, or `None` if
//! there are no encoding errors.
//! * [`try_to_string()`]\: Returns an unescaped [`String`] only if no encoding errors were present.
//! * [`try_to_cow()`]\: Returns an unescaped [`Cow<str>`] only if no encoding errors were present.
//!
//! [U+FFFD]: core::char::REPLACEMENT_CHARACTER
//! [Unicode Control Pictures]: https://www.unicode.org/charts/PDF/U2400.pdf
//! [`escape_uri()`]: #method.escape_uri
//! [`unescape_uri()`]: #method.unescape_uri
//! [`unescape_uri_in_place()`]: #method.unescape_uri_in_place
//! [`first_error()`]: struct.UnescapeUri.html#method.first_error
//! [`try_to_string()`]: struct.UnescapeUri.html#method.try_to_string
//! [`try_to_cow()`]: struct.UnescapeUri.html#method.try_to_cow
//! [`EscapeUri`]: struct.EscapeUri.html
//! [`UnescapeUri`]: struct.UnescapeUri.html
//!
pub use *;
pub use *;
/// Trait for `str` adding URI percent encoding/decoding
///
/// See the [module-level](index.html) documentation for more details.
///