Simon Sapin 10 лет назад
Родитель
Сommit
0ac1ac59bb
2 измененных файлов с 44 добавлено и 6 удалено
  1. 37 3
      src/lib.rs
  2. 7 3
      src/webidl.rs

+ 37 - 3
src/lib.rs

@@ -397,7 +397,7 @@ impl Url {
         })
         })
     }
     }
 
 
-    fn mutate<F: FnOnce(&mut Parser)>(&mut self, f: F) {
+    fn mutate<F: FnOnce(&mut Parser) -> R, R>(&mut self, f: F) -> R {
         let mut parser = Parser {
         let mut parser = Parser {
             serialization: mem::replace(&mut self.serialization, String::new()),
             serialization: mem::replace(&mut self.serialization, String::new()),
             base_url: None,
             base_url: None,
@@ -405,19 +405,53 @@ impl Url {
             log_syntax_violation: None,
             log_syntax_violation: None,
             context: Context::Setter,
             context: Context::Setter,
         };
         };
-        f(&mut parser);
+        let result = f(&mut parser);
         self.serialization = parser.serialization;
         self.serialization = parser.serialization;
+        result
     }
     }
 
 
     /// Change this URL’s fragment identifier.
     /// Change this URL’s fragment identifier.
     pub fn set_fragment(&mut self, fragment: Option<&str>) {
     pub fn set_fragment(&mut self, fragment: Option<&str>) {
+        // Remove any previous fragment
         if let Some(start) = self.fragment_start {
         if let Some(start) = self.fragment_start {
             debug_assert!(self.byte_at(start) == b'#');
             debug_assert!(self.byte_at(start) == b'#');
             self.serialization.truncate(start as usize);
             self.serialization.truncate(start as usize);
         }
         }
+        // Write the new one
         if let Some(input) = fragment {
         if let Some(input) = fragment {
+            self.fragment_start = Some(to_u32(self.serialization.len()).unwrap());
             self.serialization.push('#');
             self.serialization.push('#');
-            self.mutate(|parser| parser.parse_fragment(input));
+            self.mutate(|parser| parser.parse_fragment(input))
+        } else {
+            self.fragment_start = None
+        }
+    }
+
+    /// Change this URL’s query string.
+    pub fn set_query(&mut self, query: Option<&str>) {
+        // Stash any fragment
+        let fragment = self.fragment_start.map(|start| {
+            let f = self.slice(start..).to_owned();
+            self.serialization.truncate(start as usize);
+            f
+        });
+        // Remove any previous query
+        if let Some(start) = self.query_start {
+            debug_assert!(self.byte_at(start) == b'?');
+            self.serialization.truncate(start as usize);
+        }
+        // Write the new one
+        if let Some(input) = query {
+            self.query_start = Some(to_u32(self.serialization.len()).unwrap());
+            self.serialization.push('?');
+            let scheme_end = self.scheme_end;
+            self.mutate(|parser| parser.parse_query(scheme_end, input));
+        }
+        // Restore the fragment, if any
+        if let Some(ref fragment) = fragment {
+            self.fragment_start = Some(to_u32(self.serialization.len()).unwrap());
+            debug_assert!(fragment.starts_with('#'));
+            self.serialization.push_str(fragment)  // It’s already been through the parser
         }
         }
     }
     }
 
 

+ 7 - 3
src/webidl.rs

@@ -139,9 +139,13 @@ impl WebIdl {
         }
         }
     }
     }
 
 
-    /// **Not implemented yet** Setter for https://url.spec.whatwg.org/#dom-url-search
-    pub fn set_search(_url: &mut Url, _new_search: &str) {
-        unimplemented!()  // FIXME
+    /// Setter for https://url.spec.whatwg.org/#dom-url-search
+    pub fn set_search(url: &mut Url, new_search: &str) {
+        url.set_query(match new_search {
+            "" => None,
+            _ if new_search.starts_with('?') => Some(&new_search[1..]),
+            _ => Some(new_search),
+        })
     }
     }
 
 
     /// **Not implemented yet** Getter for https://url.spec.whatwg.org/#dom-url-searchparams
     /// **Not implemented yet** Getter for https://url.spec.whatwg.org/#dom-url-searchparams