urlutils.rs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright 2013-2014 Simon Sapin.
  2. //
  3. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  4. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  5. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  6. // option. This file may not be copied, modified, or distributed
  7. // except according to those terms.
  8. //! These methods are not meant for use in Rust code,
  9. //! only to help implement the JavaScript URLUtils API: http://url.spec.whatwg.org/#urlutils
  10. use super::{Url, UrlParser, SchemeType, SchemeData, RelativeSchemeData};
  11. use parser::{ParseError, ParseResult, Context};
  12. use percent_encoding::{utf8_percent_encode_to, USERNAME_ENCODE_SET, PASSWORD_ENCODE_SET};
  13. #[allow(dead_code)]
  14. pub struct UrlUtilsWrapper<'a> {
  15. pub url: &'a mut Url,
  16. pub parser: &'a UrlParser<'a>,
  17. }
  18. #[doc(hidden)]
  19. pub trait UrlUtils {
  20. fn set_scheme(&mut self, input: &str) -> ParseResult<()>;
  21. fn set_username(&mut self, input: &str) -> ParseResult<()>;
  22. fn set_password(&mut self, input: &str) -> ParseResult<()>;
  23. fn set_host_and_port(&mut self, input: &str) -> ParseResult<()>;
  24. fn set_host(&mut self, input: &str) -> ParseResult<()>;
  25. fn set_port(&mut self, input: &str) -> ParseResult<()>;
  26. fn set_path(&mut self, input: &str) -> ParseResult<()>;
  27. fn set_query(&mut self, input: &str) -> ParseResult<()>;
  28. fn set_fragment(&mut self, input: &str) -> ParseResult<()>;
  29. }
  30. impl<'a> UrlUtils for UrlUtilsWrapper<'a> {
  31. /// `URLUtils.protocol` setter
  32. fn set_scheme(&mut self, input: &str) -> ParseResult<()> {
  33. match ::parser::parse_scheme(input, Context::Setter) {
  34. Some((scheme, _)) => {
  35. if self.parser.get_scheme_type(&self.url.scheme).same_as(self.parser.get_scheme_type(&scheme)) {
  36. return Err(ParseError::InvalidScheme);
  37. }
  38. self.url.scheme = scheme;
  39. Ok(())
  40. },
  41. None => Err(ParseError::InvalidScheme),
  42. }
  43. }
  44. /// `URLUtils.username` setter
  45. fn set_username(&mut self, input: &str) -> ParseResult<()> {
  46. match self.url.scheme_data {
  47. SchemeData::Relative(RelativeSchemeData { ref mut username, .. }) => {
  48. username.truncate(0);
  49. utf8_percent_encode_to(input, USERNAME_ENCODE_SET, username);
  50. Ok(())
  51. },
  52. SchemeData::NonRelative(_) => Err(ParseError::CannotSetUsernameWithNonRelativeScheme)
  53. }
  54. }
  55. /// `URLUtils.password` setter
  56. fn set_password(&mut self, input: &str) -> ParseResult<()> {
  57. match self.url.scheme_data {
  58. SchemeData::Relative(RelativeSchemeData { ref mut password, .. }) => {
  59. if input.len() == 0 {
  60. *password = None;
  61. return Ok(());
  62. }
  63. let mut new_password = String::new();
  64. utf8_percent_encode_to(input, PASSWORD_ENCODE_SET, &mut new_password);
  65. *password = Some(new_password);
  66. Ok(())
  67. },
  68. SchemeData::NonRelative(_) => Err(ParseError::CannotSetPasswordWithNonRelativeScheme)
  69. }
  70. }
  71. /// `URLUtils.host` setter
  72. fn set_host_and_port(&mut self, input: &str) -> ParseResult<()> {
  73. match self.url.scheme_data {
  74. SchemeData::Relative(RelativeSchemeData {
  75. ref mut host, ref mut port, ref mut default_port, ..
  76. }) => {
  77. let scheme_type = self.parser.get_scheme_type(&self.url.scheme);
  78. let (new_host, new_port, new_default_port, _) = try!(::parser::parse_host(
  79. input, scheme_type, self.parser));
  80. *host = new_host;
  81. *port = new_port;
  82. *default_port = new_default_port;
  83. Ok(())
  84. },
  85. SchemeData::NonRelative(_) => Err(ParseError::CannotSetHostPortWithNonRelativeScheme)
  86. }
  87. }
  88. /// `URLUtils.hostname` setter
  89. fn set_host(&mut self, input: &str) -> ParseResult<()> {
  90. match self.url.scheme_data {
  91. SchemeData::Relative(RelativeSchemeData { ref mut host, .. }) => {
  92. let (new_host, _) = try!(::parser::parse_hostname(input, self.parser));
  93. *host = new_host;
  94. Ok(())
  95. },
  96. SchemeData::NonRelative(_) => Err(ParseError::CannotSetHostWithNonRelativeScheme)
  97. }
  98. }
  99. /// `URLUtils.port` setter
  100. fn set_port(&mut self, input: &str) -> ParseResult<()> {
  101. match self.url.scheme_data {
  102. SchemeData::Relative(RelativeSchemeData { ref mut port, ref mut default_port, .. }) => {
  103. let scheme_type = self.parser.get_scheme_type(&self.url.scheme);
  104. if scheme_type == SchemeType::FileLike {
  105. return Err(ParseError::CannotSetPortWithFileLikeScheme);
  106. }
  107. let (new_port, new_default_port, _) = try!(::parser::parse_port(
  108. input, scheme_type, self.parser));
  109. *port = new_port;
  110. *default_port = new_default_port;
  111. Ok(())
  112. },
  113. SchemeData::NonRelative(_) => Err(ParseError::CannotSetPortWithNonRelativeScheme)
  114. }
  115. }
  116. /// `URLUtils.pathname` setter
  117. fn set_path(&mut self, input: &str) -> ParseResult<()> {
  118. match self.url.scheme_data {
  119. SchemeData::Relative(RelativeSchemeData { ref mut path, .. }) => {
  120. let scheme_type = self.parser.get_scheme_type(&self.url.scheme);
  121. let (new_path, _) = try!(::parser::parse_path_start(
  122. input, Context::Setter, scheme_type, self.parser));
  123. *path = new_path;
  124. Ok(())
  125. },
  126. SchemeData::NonRelative(_) => Err(ParseError::CannotSetPathWithNonRelativeScheme)
  127. }
  128. }
  129. /// `URLUtils.search` setter
  130. fn set_query(&mut self, input: &str) -> ParseResult<()> {
  131. self.url.query = if input.is_empty() {
  132. None
  133. } else {
  134. let input = if input.starts_with("?") { &input[1..] } else { input };
  135. let (new_query, _) = try!(::parser::parse_query(
  136. input, Context::Setter, self.parser));
  137. Some(new_query)
  138. };
  139. Ok(())
  140. }
  141. /// `URLUtils.hash` setter
  142. fn set_fragment(&mut self, input: &str) -> ParseResult<()> {
  143. if self.url.scheme == "javascript" {
  144. return Err(ParseError::CannotSetJavascriptFragment)
  145. }
  146. self.url.fragment = if input.is_empty() {
  147. None
  148. } else {
  149. let input = if input.starts_with("#") { &input[1..] } else { input };
  150. Some(try!(::parser::parse_fragment(input, self.parser)))
  151. };
  152. Ok(())
  153. }
  154. }