Skip to content

Commit de977b5

Browse files
author
bors-servo
authored
Auto merge of #407 - servo:custom-encoding, r=mbrubeck
Add custom_encoding_override() to form_urlencoded::Serializer. This is an alternative to `encoding_override()` that can be used without a dependency on rust-encoding. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-url/407) <!-- Reviewable:end -->
2 parents 8c55c50 + b761d6c commit de977b5

File tree

4 files changed

+50
-6
lines changed

4 files changed

+50
-6
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
name = "url"
44
# When updating version, also modify html_root_url in the lib.rs
5-
version = "1.5.1"
5+
version = "1.6.0"
66
authors = ["The rust-url developers"]
77

88
description = "URL library for Rust, based on the WHATWG URL Standard"

src/form_urlencoded.rs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use encoding::EncodingOverride;
1717
use percent_encoding::{percent_encode_byte, percent_decode};
1818
use std::borrow::{Borrow, Cow};
19+
use std::fmt;
1920
use std::str;
2021

2122

@@ -216,6 +217,15 @@ pub struct Serializer<T: Target> {
216217
target: Option<T>,
217218
start_position: usize,
218219
encoding: EncodingOverride,
220+
custom_encoding: Option<SilentDebug<Box<FnMut(&str) -> Cow<[u8]>>>>,
221+
}
222+
223+
struct SilentDebug<T>(T);
224+
225+
impl<T> fmt::Debug for SilentDebug<T> {
226+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
227+
f.write_str("…")
228+
}
219229
}
220230

221231
pub trait Target {
@@ -272,6 +282,7 @@ impl<T: Target> Serializer<T> {
272282
target: Some(target),
273283
start_position: start_position,
274284
encoding: EncodingOverride::utf8(),
285+
custom_encoding: None,
275286
}
276287
}
277288

@@ -290,11 +301,20 @@ impl<T: Target> Serializer<T> {
290301
self
291302
}
292303

304+
/// Set the character encoding to be used for names and values before percent-encoding.
305+
pub fn custom_encoding_override<F>(&mut self, encode: F) -> &mut Self
306+
where F: FnMut(&str) -> Cow<[u8]> + 'static
307+
{
308+
self.custom_encoding = Some(SilentDebug(Box::new(encode)));
309+
self
310+
}
311+
293312
/// Serialize and append a name/value pair.
294313
///
295314
/// Panics if called after `.finish()`.
296315
pub fn append_pair(&mut self, name: &str, value: &str) -> &mut Self {
297-
append_pair(string(&mut self.target), self.start_position, self.encoding, name, value);
316+
append_pair(string(&mut self.target), self.start_position, self.encoding,
317+
&mut self.custom_encoding, name, value);
298318
self
299319
}
300320

@@ -311,7 +331,8 @@ impl<T: Target> Serializer<T> {
311331
let string = string(&mut self.target);
312332
for pair in iter {
313333
let &(ref k, ref v) = pair.borrow();
314-
append_pair(string, self.start_position, self.encoding, k.as_ref(), v.as_ref());
334+
append_pair(string, self.start_position, self.encoding,
335+
&mut self.custom_encoding, k.as_ref(), v.as_ref());
315336
}
316337
}
317338
self
@@ -324,6 +345,8 @@ impl<T: Target> Serializer<T> {
324345
/// Panics if called after `.finish()`.
325346
#[cfg(feature = "query_encoding")]
326347
pub fn append_charset(&mut self) -> &mut Self {
348+
assert!(self.custom_encoding.is_none(),
349+
"Cannot use both custom_encoding_override() and append_charset()");
327350
{
328351
let string = string(&mut self.target);
329352
append_separator_if_needed(string, self.start_position);
@@ -361,9 +384,20 @@ fn string<T: Target>(target: &mut Option<T>) -> &mut String {
361384
}
362385

363386
fn append_pair(string: &mut String, start_position: usize, encoding: EncodingOverride,
387+
custom_encoding: &mut Option<SilentDebug<Box<FnMut(&str) -> Cow<[u8]>>>>,
364388
name: &str, value: &str) {
365389
append_separator_if_needed(string, start_position);
366-
string.extend(byte_serialize(&encoding.encode(name.into())));
390+
append_encoded(name, string, encoding, custom_encoding);
367391
string.push('=');
368-
string.extend(byte_serialize(&encoding.encode(value.into())));
392+
append_encoded(value, string, encoding, custom_encoding);
393+
}
394+
395+
fn append_encoded(s: &str, string: &mut String, encoding: EncodingOverride,
396+
custom_encoding: &mut Option<SilentDebug<Box<FnMut(&str) -> Cow<[u8]>>>>) {
397+
let bytes = if let Some(SilentDebug(ref mut custom)) = *custom_encoding {
398+
custom(s)
399+
} else {
400+
encoding.encode(s.into())
401+
};
402+
string.extend(byte_serialize(&bytes));
369403
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ assert_eq!(css_url.as_str(), "http://servo.github.io/rust-url/main.css");
104104
# run().unwrap();
105105
*/
106106

107-
#![doc(html_root_url = "https://docs.rs/url/1.5.1")]
107+
#![doc(html_root_url = "https://docs.rs/url/1.6.0")]
108108

109109
#[cfg(feature="rustc-serialize")] extern crate rustc_serialize;
110110
#[macro_use] extern crate matches;

tests/unit.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#[macro_use]
1212
extern crate url;
1313

14+
use std::ascii::AsciiExt;
1415
use std::borrow::Cow;
1516
use std::net::{Ipv4Addr, Ipv6Addr};
1617
use std::path::{Path, PathBuf};
@@ -255,6 +256,15 @@ fn test_form_serialize() {
255256
assert_eq!(encoded, "foo=%C3%A9%26&bar=&foo=%23");
256257
}
257258

259+
#[test]
260+
fn form_urlencoded_custom_encoding_override() {
261+
let encoded = form_urlencoded::Serializer::new(String::new())
262+
.custom_encoding_override(|s| s.as_bytes().to_ascii_uppercase().into())
263+
.append_pair("foo", "bar")
264+
.finish();
265+
assert_eq!(encoded, "FOO=BAR");
266+
}
267+
258268
#[test]
259269
fn host_and_port_display() {
260270
assert_eq!(

0 commit comments

Comments
 (0)