Skip to content

Commit 6953b97

Browse files
committed
Percent-encode fragments
1 parent 1055810 commit 6953b97

File tree

1 file changed

+33
-16
lines changed

1 file changed

+33
-16
lines changed

src/lib.rs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
#[macro_use] extern crate matches;
22
pub extern crate mime;
33

4-
pub enum DataUrlError {
5-
NotADataUrl,
6-
NoComma,
7-
}
8-
94
pub struct DataUrl<'a> {
105
mime_type: mime::Mime,
116
base64: bool,
127
encoded_body_plus_fragment: &'a str,
138
}
149

10+
pub enum DataUrlError {
11+
NotADataUrl,
12+
NoComma,
13+
}
14+
1515
pub enum DecodeError<E> {
1616
InvalidBase64(InvalidBase64),
1717
WriteError(E),
@@ -23,12 +23,6 @@ impl<E> From<InvalidBase64> for DecodeError<E> {
2323
fn from(e: InvalidBase64) -> Self { DecodeError::InvalidBase64(e) }
2424
}
2525

26-
/// The URL’s fragment identifier (after `#`) encoded as in the original input.
27-
///
28-
/// It needs to be either percent-encoded to obtain the same string as in a parsed URL,
29-
/// or percent-decoded to interpret it as text.
30-
pub struct UrlFragmentIdentifier<'a>(pub &'a str);
31-
3226
impl<'a> DataUrl<'a> {
3327
/// <https://fetch.spec.whatwg.org/#data-url-processor>
3428
/// but starting from a string rather than a Url, to avoid extra string copies.
@@ -52,7 +46,7 @@ impl<'a> DataUrl<'a> {
5246
/// Streaming-decode the data URL’s body to `write_body_bytes`,
5347
/// and return the URL’s fragment identifier is returned if it has one.
5448
pub fn decode<F, E>(&self, write_body_bytes: F)
55-
-> Result<Option<UrlFragmentIdentifier<'a>>, DecodeError<E>>
49+
-> Result<Option<FragmentIdentifier<'a>>, DecodeError<E>>
5650
where F: FnMut(&[u8]) -> Result<(), E>
5751
{
5852
if self.base64 {
@@ -65,7 +59,7 @@ impl<'a> DataUrl<'a> {
6559

6660
/// Return the decoded body and the URL’s fragment identifier
6761
pub fn decode_to_vec(&self)
68-
-> Result<(Vec<u8>, Option<UrlFragmentIdentifier<'a>>), InvalidBase64>
62+
-> Result<(Vec<u8>, Option<FragmentIdentifier<'a>>), InvalidBase64>
6963
{
7064
enum Impossible {}
7165
let mut body = Vec::new();
@@ -78,6 +72,29 @@ impl<'a> DataUrl<'a> {
7872
}
7973
}
8074

75+
/// The URL’s fragment identifier (after `#`)
76+
pub struct FragmentIdentifier<'a>(&'a str);
77+
78+
impl<'a> FragmentIdentifier<'a> {
79+
/// Like in a parsed URL
80+
pub fn to_percent_encoded(&self) -> String {
81+
let mut string = String::new();
82+
for byte in self.0.bytes() {
83+
match byte {
84+
// Ignore ASCII tabs or newlines like the URL parser would
85+
b'\t' | b'\n' | b'\r' => continue,
86+
// Fragment encode set
87+
b'\0'...b' ' | b'"' | b'<' | b'>' | b'`' | b'\x7F'...b'\xFF' => {
88+
percent_encode(byte, &mut string)
89+
}
90+
// Printable ASCII
91+
_ => string.push(byte as char)
92+
}
93+
}
94+
string
95+
}
96+
}
97+
8198
macro_rules! require {
8299
($condition: expr) => {
83100
if !$condition {
@@ -217,7 +234,7 @@ fn percent_encode(byte: u8, string: &mut String) {
217234
/// would be percent-decoded here.
218235
/// We skip that round-trip and pass it through unchanged.
219236
fn decode_without_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes: F)
220-
-> Result<Option<UrlFragmentIdentifier>, E>
237+
-> Result<Option<FragmentIdentifier>, E>
221238
where F: FnMut(&[u8]) -> Result<(), E>
222239
{
223240
let bytes = encoded_body_plus_fragment.as_bytes();
@@ -251,7 +268,7 @@ fn decode_without_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes
251268
b'#' => {
252269
let fragment_start = i + 1;
253270
let fragment = &encoded_body_plus_fragment[fragment_start..];
254-
return Ok(Some(UrlFragmentIdentifier(fragment)))
271+
return Ok(Some(FragmentIdentifier(fragment)))
255272
}
256273

257274
// Ignore over '\t' | '\n' | '\r'
@@ -267,7 +284,7 @@ fn decode_without_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes
267284
/// <https://infra.spec.whatwg.org/#isomorphic-decode> composed with
268285
/// <https://infra.spec.whatwg.org/#forgiving-base64-decode>.
269286
fn decode_with_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes: F)
270-
-> Result<Option<UrlFragmentIdentifier>, DecodeError<E>>
287+
-> Result<Option<FragmentIdentifier>, DecodeError<E>>
271288
where F: FnMut(&[u8]) -> Result<(), E>
272289
{
273290
let mut bit_buffer: u32 = 0;

0 commit comments

Comments
 (0)