Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New IntoUrl trait #177

Closed
wants to merge 40 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
918352b
Make it possible to define new encode sets in other crates.
SimonSapin Dec 4, 2015
db9de70
Define encode sets based on another set.
SimonSapin Dec 4, 2015
691aec2
Remove the HTTP_VALUE encode set. It can be defined in another crate.
SimonSapin Dec 4, 2015
d140dc8
Rewrite ALL THE THINGS!
SimonSapin Dec 9, 2015
9edff44
Remove the dependency on uuid.
SimonSapin Feb 8, 2016
576bd2a
Add URL slicing/indexing by component.
SimonSapin Feb 8, 2016
7b11445
Add stubs with partial implementation for the WebIDL API.
SimonSapin Feb 8, 2016
c617ed1
Shorter Cargo.toml syntax.
SimonSapin Feb 8, 2016
22cf104
serde_serialization -> serde
SimonSapin Feb 8, 2016
0cb3f2b
Make rustc-serialize an optional dependency.
SimonSapin Feb 8, 2016
61a8185
Rename *{Start,End} posititons to {Before,After}*
SimonSapin Feb 9, 2016
813d270
Replace from_hex() with char::to_digit(16)
SimonSapin Feb 9, 2016
0b5ffb4
Make percent-decoding an iterator.
SimonSapin Feb 9, 2016
244d999
Make percent-encoding an iterator.
SimonSapin Feb 9, 2016
7b33b33
Add percent-encoding convienience wrappers.
SimonSapin Feb 9, 2016
ca9f87d
Update tests from https://github.com/w3c/web-platform-tests/blob/mast…
SimonSapin Feb 10, 2016
7a0e467
Remove Url::has_host
SimonSapin Feb 11, 2016
9a8d394
Remove unused ParseError variants
SimonSapin Feb 12, 2016
903f1d2
Make context a field of Parser.
SimonSapin Feb 11, 2016
a9b4e71
Remove the redundant is_relative field.
SimonSapin Feb 15, 2016
ded48a2
Add Url::domain and Url::ip_address
SimonSapin Feb 15, 2016
d3dba86
Implement ToSocketAddrs
SimonSapin Feb 15, 2016
088c3ed
Remove Url::ip_address for now
SimonSapin Feb 15, 2016
641f940
Add Unicode and ASCII serializations of origins
SimonSapin Feb 16, 2016
946d950
Test WebIdl::origin
SimonSapin Feb 16, 2016
4dff876
Add a fragment setter
SimonSapin Feb 11, 2016
0ae07ed
Add a query setter.
SimonSapin Feb 12, 2016
542feb0
Make Url::parse_with usable. (EncodingOverride is private.)
SimonSapin Feb 19, 2016
dd0436a
Add Origin::is_tuple
SimonSapin Feb 19, 2016
f7e0d7c
More consistent checks for URL with authority or path-only.
SimonSapin Feb 19, 2016
fd16b74
Re-export OpaqueOrigin. It is exposed publicly through Origin::Opaque
SimonSapin Feb 19, 2016
f1bdaa6
Add a scheme setter
SimonSapin Feb 19, 2016
158145f
Add host setters.
SimonSapin Feb 19, 2016
b1b0916
More setters
SimonSapin Feb 23, 2016
47e31ef
Add a path setter
SimonSapin Feb 26, 2016
e7a4dc0
Username and passowrd setters
SimonSapin Feb 26, 2016
5b26c89
More WebIDL implementations.
SimonSapin Feb 26, 2016
bf0f670
Port setters
SimonSapin Mar 1, 2016
b89d7d7
All setters.
SimonSapin Mar 1, 2016
3f9dcd4
New IntoUrl trait
cmbrandenburg Mar 4, 2016
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

All setters.

  • Loading branch information
SimonSapin committed Mar 3, 2016
commit b89d7d777e7226d67443b575f1726ec7fe66b88c
@@ -24,6 +24,16 @@ pub enum HostInternal {
Ipv6(Ipv6Addr),
}

impl<S> From<Host<S>> for HostInternal {
fn from(host: Host<S>) -> HostInternal {
match host {
Host::Domain(_) => HostInternal::Domain,
Host::Ipv4(address) => HostInternal::Ipv4(address),
Host::Ipv6(address) => HostInternal::Ipv6(address),
}
}
}

/// The host name of an URL.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature="heap_size", derive(HeapSizeOf))]
@@ -157,19 +167,6 @@ impl Iterator for SocketAddrs {
}
}

/// Parse `input` as a host.
/// If successful, write its serialization to `serialization`
/// and return the internal representation for `Url`.
pub fn parse(input: &str, serialization: &mut String) -> ParseResult<HostInternal> {
let host = try!(Host::parse(input));
write!(serialization, "{}", host).unwrap();
match host {
Host::Domain(_) => Ok(HostInternal::Domain),
Host::Ipv4(address) => Ok(HostInternal::Ipv4(address)),
Host::Ipv6(address) => Ok(HostInternal::Ipv6(address)),
}
}

fn write_ipv6(addr: &Ipv6Addr, f: &mut Formatter) -> fmt::Result {
let segments = addr.segments();
let (compress_start, compress_end) = longest_zero_sequence(&segments);
@@ -576,11 +576,11 @@ impl Url {
if port.is_some() && port == parser::default_port(self.scheme()) {
port = None
}
self.set_port_inner(port);
self.set_port_internal(port);
Ok(())
}

fn set_port_inner(&mut self, port: Option<u16>) {
fn set_port_internal(&mut self, port: Option<u16>) {
match (self.port, port) {
(None, None) => {}
(Some(_), None) => {
@@ -614,7 +614,8 @@ impl Url {

/// Change this URL’s host.
///
/// If this URL is non-relative, do nothing and return `Err`.
/// If this URL is non-relative or there is an error parsing the given `host`,
/// do nothing and return `Err`.
///
/// Removing the host (calling this with `None`)
/// will also remove any username, password, and port number.
@@ -624,7 +625,7 @@ impl Url {
}

if let Some(host) = host {
self.set_host_internal(try!(Host::parse(host).map_err(|_| ())))
self.set_host_internal(try!(Host::parse(host).map_err(|_| ())), None)
} else if self.has_host() {
// Not debug_assert! since this proves that `unsafe` below is OK:
assert!(self.byte_at(self.scheme_end) == b':');
@@ -646,8 +647,10 @@ impl Url {
Ok(())
}

fn set_host_internal(&mut self, host: Host<String>) {
let after_host = self.slice(self.host_end..).to_owned();
/// opt_new_port: None means leave unchanged, Some(None) means remove any port number.
fn set_host_internal(&mut self, host: Host<String>, opt_new_port: Option<Option<u16>>) {
let old_suffix_pos = if opt_new_port.is_some() { self.path_start } else { self.host_end };
let suffix = self.slice(old_suffix_pos..).to_owned();
self.serialization.truncate(self.host_start as usize);
if !self.has_host() {
debug_assert!(self.slice(self.scheme_end..self.host_start) == ":");
@@ -657,20 +660,22 @@ impl Url {
self.username_end += 2;
self.host_start += 2;
}
let old_host_end = self.host_end;
write!(&mut self.serialization, "{}", host).unwrap();
let new_host_end = to_u32(self.serialization.len()).unwrap();
self.serialization.push_str(&after_host);
self.host_end = to_u32(self.serialization.len()).unwrap();
self.host = host.into();

if let Some(new_port) = opt_new_port {
self.port = new_port;
if let Some(port) = new_port {
write!(&mut self.serialization, ":{}", port).unwrap();
}
}
let new_suffix_pos = to_u32(self.serialization.len()).unwrap();
self.serialization.push_str(&suffix);

self.host = match host {
Host::Domain(_) => HostInternal::Domain,
Host::Ipv4(address) => HostInternal::Ipv4(address),
Host::Ipv6(address) => HostInternal::Ipv6(address),
};
self.host_end = new_host_end;
let adjust = |index: &mut u32| {
*index -= old_host_end;
*index += new_host_end;
*index -= old_suffix_pos;
*index += new_suffix_pos;
};
adjust(&mut self.path_start);
if let Some(ref mut index) = self.query_start { adjust(index) }
@@ -687,7 +692,7 @@ impl Url {
return Err(())
}

self.set_host_internal(Host::Ipv4(address));
self.set_host_internal(Host::Ipv4(address), None);
Ok(())
}

@@ -701,7 +706,7 @@ impl Url {
return Err(())
}

self.set_host_internal(Host::Ipv6(address));
self.set_host_internal(Host::Ipv6(address), None);
Ok(())
}

@@ -11,7 +11,7 @@ use std::error::Error;
use std::fmt::{self, Formatter, Write};

use super::{Url, EncodingOverride};
use host::{self, HostInternal};
use host::{Host, HostInternal};
use percent_encoding::{
utf8_percent_encode, percent_encode,
SIMPLE_ENCODE_SET, DEFAULT_ENCODE_SET, USERINFO_ENCODE_SET, QUERY_ENCODE_SET,
@@ -599,7 +599,9 @@ impl<'a> Parser<'a> {
pub fn parse_host_and_port<'i>(&mut self, input: &'i str,
scheme_end: u32, scheme_type: SchemeType)
-> ParseResult<(u32, HostInternal, Option<u16>, &'i str)> {
let (host, remaining) = try!(self.parse_host(input, scheme_type));
let (host, remaining) = try!(
Parser::parse_host(input, scheme_type, |m| self.syntax_violation(m)));
write!(&mut self.serialization, "{}", host).unwrap();
let host_end = try!(to_u32(self.serialization.len()));
let (port, remaining) = if remaining.starts_with(":") {
let syntax_violation = |message| self.syntax_violation(message);
@@ -611,11 +613,12 @@ impl<'a> Parser<'a> {
if let Some(port) = port {
write!(&mut self.serialization, ":{}", port).unwrap()
}
Ok((host_end, host, port, remaining))
Ok((host_end, host.into(), port, remaining))
}

pub fn parse_host<'i>(&mut self, input: &'i str, scheme_type: SchemeType)
-> ParseResult<(HostInternal, &'i str)> {
pub fn parse_host<'i, S>(input: &'i str, scheme_type: SchemeType, syntax_violation: S)
-> ParseResult<(Host<String>, &'i str)>
where S: Fn(&'static str) {
let mut inside_square_brackets = false;
let mut has_ignored_chars = false;
let mut end = input.len();
@@ -634,7 +637,7 @@ impl<'a> Parser<'a> {
break
}
b'\t' | b'\n' | b'\r' => {
self.syntax_violation("invalid character");
syntax_violation("invalid character");
has_ignored_chars = true;
}
b'[' => inside_square_brackets = true,
@@ -652,7 +655,7 @@ impl<'a> Parser<'a> {
if scheme_type.is_special() && host_input.is_empty() {
return Err(ParseError::EmptyHost)
}
let host = try!(host::parse(&host_input, &mut self.serialization));
let host = try!(Host::parse(&host_input));
Ok((host, &input[end..]))
}

@@ -683,17 +686,17 @@ impl<'a> Parser<'a> {
if is_windows_drive_letter(host_input) {
return Ok((false, HostInternal::None, input))
}
let mut host;
if host_input.is_empty() {
host = HostInternal::None;
let host = if host_input.is_empty() {
HostInternal::None
} else {
let host_start = self.serialization.len();
host = try!(host::parse(&host_input, &mut self.serialization));
if &self.serialization[host_start..] == "localhost" {
host = HostInternal::None;
self.serialization.truncate(host_start);
match try!(Host::parse(&host_input)) {
Host::Domain(ref d) if d == "localhost" => HostInternal::None,
host => {
write!(&mut self.serialization, "{}", host).unwrap();
host.into()
}
}
}
};
Ok((true, host, &input[end..]))
}

@@ -9,7 +9,7 @@
use {Url, ParseError};
use host::Host;
use idna::domain_to_unicode;
use parser::{Parser, default_port};
use parser::{Parser, SchemeType, default_port};

/// https://url.spec.whatwg.org/#api
pub struct WebIdl;
@@ -89,9 +89,30 @@ impl WebIdl {
host
}

/// **Not implemented yet** Setter for https://url.spec.whatwg.org/#dom-url-host
pub fn set_host(_url: &mut Url, _new_host: &str) {
unimplemented!() // FIXME
/// Setter for https://url.spec.whatwg.org/#dom-url-host
pub fn set_host(url: &mut Url, new_host: &str) {
if url.non_relative() {
return
}
let host;
let opt_port;
{
let scheme = url.scheme();
let result = Parser::parse_host(new_host, SchemeType::from(scheme), |_| ());
match result {
Ok((h, remaining)) => {
host = h;
opt_port = if remaining.starts_with(':') {
Parser::parse_port(remaining, |_| (), || default_port(scheme))
.ok().map(|(port, _remaining)| port)
} else {
None
};
}
Err(_) => return
}
}
url.set_host_internal(host, opt_port)
}

/// Getter for https://url.spec.whatwg.org/#dom-url-hostname
@@ -100,9 +121,15 @@ impl WebIdl {
url.host_str().unwrap_or("")
}

/// **Not implemented yet** Setter for https://url.spec.whatwg.org/#dom-url-hostname
pub fn set_hostname(_url: &mut Url, _new_hostname: &str) {
unimplemented!() // FIXME
/// Setter for https://url.spec.whatwg.org/#dom-url-hostname
pub fn set_hostname(url: &mut Url, new_hostname: &str) {
if url.non_relative() {
return
}
let result = Parser::parse_host(new_hostname, SchemeType::from(url.scheme()), |_| ());
if let Ok((host, _remaining)) = result {
url.set_host_internal(host, None)
}
}

/// Getter for https://url.spec.whatwg.org/#dom-url-port
@@ -128,7 +155,7 @@ impl WebIdl {
result = Parser::parse_port(new_port, |_| (), || default_port(scheme))
}
if let Ok((new_port, _remaining)) = result {
url.set_port_inner(new_port)
url.set_port_internal(new_port)
}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.