urlutils.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. let mut new_password = String::new();
  60. utf8_percent_encode_to(input, PASSWORD_ENCODE_SET, &mut new_password);
  61. *password = Some(new_password);
  62. Ok(())
  63. },
  64. SchemeData::NonRelative(_) => Err(ParseError::CannotSetPasswordWithNonRelativeScheme)
  65. }
  66. }
  67. /// `URLUtils.host` setter
  68. fn set_host_and_port(&mut self, input: &str) -> ParseResult<()> {
  69. match self.url.scheme_data {
  70. SchemeData::Relative(RelativeSchemeData {
  71. ref mut host, ref mut port, ref mut default_port, ..
  72. }) => {
  73. let scheme_type = self.parser.get_scheme_type(&self.url.scheme);
  74. let (new_host, new_port, new_default_port, _) = try!(::parser::parse_host(
  75. input, scheme_type, self.parser));
  76. *host = new_host;
  77. *port = new_port;
  78. *default_port = new_default_port;
  79. Ok(())
  80. },
  81. SchemeData::NonRelative(_) => Err(ParseError::CannotSetHostPortWithNonRelativeScheme)
  82. }
  83. }
  84. /// `URLUtils.hostname` setter
  85. fn set_host(&mut self, input: &str) -> ParseResult<()> {
  86. match self.url.scheme_data {
  87. SchemeData::Relative(RelativeSchemeData { ref mut host, .. }) => {
  88. let (new_host, _) = try!(::parser::parse_hostname(input, self.parser));
  89. *host = new_host;
  90. Ok(())
  91. },
  92. SchemeData::NonRelative(_) => Err(ParseError::CannotSetHostWithNonRelativeScheme)
  93. }
  94. }
  95. /// `URLUtils.port` setter
  96. fn set_port(&mut self, input: &str) -> ParseResult<()> {
  97. match self.url.scheme_data {
  98. SchemeData::Relative(RelativeSchemeData { ref mut port, ref mut default_port, .. }) => {
  99. let scheme_type = self.parser.get_scheme_type(&self.url.scheme);
  100. if scheme_type == SchemeType::FileLike {
  101. return Err(ParseError::CannotSetPortWithFileLikeScheme);
  102. }
  103. let (new_port, new_default_port, _) = try!(::parser::parse_port(
  104. input, scheme_type, self.parser));
  105. *port = new_port;
  106. *default_port = new_default_port;
  107. Ok(())
  108. },
  109. SchemeData::NonRelative(_) => Err(ParseError::CannotSetPortWithNonRelativeScheme)
  110. }
  111. }
  112. /// `URLUtils.pathname` setter
  113. fn set_path(&mut self, input: &str) -> ParseResult<()> {
  114. match self.url.scheme_data {
  115. SchemeData::Relative(RelativeSchemeData { ref mut path, .. }) => {
  116. let scheme_type = self.parser.get_scheme_type(&self.url.scheme);
  117. let (new_path, _) = try!(::parser::parse_path_start(
  118. input, Context::Setter, scheme_type, self.parser));
  119. *path = new_path;
  120. Ok(())
  121. },
  122. SchemeData::NonRelative(_) => Err(ParseError::CannotSetPathWithNonRelativeScheme)
  123. }
  124. }
  125. /// `URLUtils.search` setter
  126. fn set_query(&mut self, input: &str) -> ParseResult<()> {
  127. self.url.query = if input.is_empty() {
  128. None
  129. } else {
  130. let input = if input.starts_with("?") { &input[1..] } else { input };
  131. let (new_query, _) = try!(::parser::parse_query(
  132. input, Context::Setter, self.parser));
  133. Some(new_query)
  134. };
  135. Ok(())
  136. }
  137. /// `URLUtils.hash` setter
  138. fn set_fragment(&mut self, input: &str) -> ParseResult<()> {
  139. if self.url.scheme == "javascript" {
  140. return Err(ParseError::CannotSetJavascriptFragment)
  141. }
  142. self.url.fragment = if input.is_empty() {
  143. None
  144. } else {
  145. let input = if input.starts_with("#") { &input[1..] } else { input };
  146. Some(try!(::parser::parse_fragment(input, self.parser)))
  147. };
  148. Ok(())
  149. }
  150. }