Procházet zdrojové kódy

Add a fragment setter

Simon Sapin před 10 roky
rodič
revize
44b601b453
3 změnil soubory, kde provedl 41 přidání a 9 odebrání
  1. 31 5
      src/lib.rs
  2. 1 1
      src/parser.rs
  3. 9 3
      src/webidl.rs

+ 31 - 5
src/lib.rs

@@ -126,11 +126,13 @@ assert_eq!(css_url.as_str(), "http://servo.github.io/rust-url/main.css")
 extern crate idna;
 extern crate idna;
 
 
 use host::HostInternal;
 use host::HostInternal;
+use parser::{Parser, Context};
 use percent_encoding::{PATH_SEGMENT_ENCODE_SET, percent_encode, percent_decode};
 use percent_encoding::{PATH_SEGMENT_ENCODE_SET, percent_encode, percent_decode};
 use std::cmp;
 use std::cmp;
 use std::fmt;
 use std::fmt;
 use std::hash;
 use std::hash;
 use std::io;
 use std::io;
+use std::mem;
 use std::net::ToSocketAddrs;
 use std::net::ToSocketAddrs;
 use std::ops::{Range, RangeFrom, RangeTo};
 use std::ops::{Range, RangeFrom, RangeTo};
 use std::path::{Path, PathBuf};
 use std::path::{Path, PathBuf};
@@ -139,7 +141,7 @@ use std::str;
 pub use encoding::EncodingOverride;
 pub use encoding::EncodingOverride;
 pub use origin::Origin;
 pub use origin::Origin;
 pub use host::{Host, HostAndPort, SocketAddrs};
 pub use host::{Host, HostAndPort, SocketAddrs};
-pub use parser::ParseError;
+pub use parser::{ParseError, to_u32};
 pub use slicing::Position;
 pub use slicing::Position;
 pub use webidl::WebIdl;
 pub use webidl::WebIdl;
 
 
@@ -194,12 +196,12 @@ impl Url {
                       encoding_override: EncodingOverride,
                       encoding_override: EncodingOverride,
                       log_syntax_violation: Option<&Fn(&'static str)>)
                       log_syntax_violation: Option<&Fn(&'static str)>)
                       -> Result<Url, ::ParseError> {
                       -> Result<Url, ::ParseError> {
-        parser::Parser {
+        Parser {
             serialization: String::with_capacity(input.len()),
             serialization: String::with_capacity(input.len()),
             base_url: base_url,
             base_url: base_url,
             query_encoding_override: encoding_override,
             query_encoding_override: encoding_override,
             log_syntax_violation: log_syntax_violation,
             log_syntax_violation: log_syntax_violation,
-            context: parser::Context::UrlParser,
+            context: Context::UrlParser,
         }.parse_url(input)
         }.parse_url(input)
     }
     }
 
 
@@ -386,8 +388,8 @@ impl Url {
 
 
     /// Return this URL’s fragment identifier, if any.
     /// Return this URL’s fragment identifier, if any.
     ///
     ///
-    /// **Note:** the parser does *not* percent-encode this component,
-    /// but the input may be percent-encoded already.
+    /// **Note:** the parser did *not* percent-encode this component,
+    /// but the input may have been percent-encoded already.
     pub fn fragment(&self) -> Option<&str> {
     pub fn fragment(&self) -> Option<&str> {
         self.fragment_start.map(|start| {
         self.fragment_start.map(|start| {
             debug_assert!(self.byte_at(start) == b'#');
             debug_assert!(self.byte_at(start) == b'#');
@@ -395,6 +397,30 @@ impl Url {
         })
         })
     }
     }
 
 
+    fn mutate<F: FnOnce(&mut Parser)>(&mut self, f: F) {
+        let mut parser = Parser {
+            serialization: mem::replace(&mut self.serialization, String::new()),
+            base_url: None,
+            query_encoding_override: EncodingOverride::utf8(),
+            log_syntax_violation: None,
+            context: Context::Setter,
+        };
+        f(&mut parser);
+        self.serialization = parser.serialization;
+    }
+
+    /// Change this URL’s fragment identifier.
+    pub fn set_fragment(&mut self, fragment: Option<&str>) {
+        if let Some(start) = self.fragment_start {
+            debug_assert!(self.byte_at(start) == b'#');
+            self.serialization.truncate(start as usize);
+        }
+        if let Some(input) = fragment {
+            self.serialization.push('#');
+            self.mutate(|parser| parser.parse_fragment(input));
+        }
+    }
+
     /// Convert a file name as `std::path::Path` into an URL in the `file` scheme.
     /// Convert a file name as `std::path::Path` into an URL in the `file` scheme.
     ///
     ///
     /// This returns `Err` if the given path is not absolute or,
     /// This returns `Err` if the given path is not absolute or,

+ 1 - 1
src/parser.rs

@@ -1053,7 +1053,7 @@ pub fn ascii_alpha(ch: char) -> bool {
 }
 }
 
 
 #[inline]
 #[inline]
-fn to_u32(i: usize) -> ParseResult<u32> {
+pub fn to_u32(i: usize) -> ParseResult<u32> {
     if i <= ::std::u32::MAX as usize {
     if i <= ::std::u32::MAX as usize {
         Ok(i as u32)
         Ok(i as u32)
     } else {
     } else {

+ 9 - 3
src/webidl.rs

@@ -161,8 +161,14 @@ impl WebIdl {
         }
         }
     }
     }
 
 
-    /// **Not implemented yet** Setter for https://url.spec.whatwg.org/#dom-url-hash
-    pub fn set_hash(_url: &mut Url, _new_hash: &str) {
-        unimplemented!()  // FIXME
+    /// Setter for https://url.spec.whatwg.org/#dom-url-hash
+    pub fn set_hash(url: &mut Url, new_hash: &str) {
+        if url.scheme() != "javascript" {
+            url.set_fragment(match new_hash {
+                "" => None,
+                _ if new_hash.starts_with('#') => Some(&new_hash[1..]),
+                _ => Some(new_hash),
+            })
+        }
     }
     }
 }
 }