|
12 | 12 |
|
13 | 13 | use prelude::*;
|
14 | 14 | use uint;
|
15 |
| -use util::{swap, replace}; |
| 15 | +use util::replace; |
16 | 16 | use vec;
|
17 | 17 |
|
18 | 18 | // FIXME: #5244: need to manually update the TrieNode constructor
|
@@ -415,39 +415,41 @@ fn find_mut<'r, T>(child: &'r mut Child<T>, key: uint, idx: uint) -> Option<&'r
|
415 | 415 |
|
416 | 416 | fn insert<T>(count: &mut uint, child: &mut Child<T>, key: uint, value: T,
|
417 | 417 | idx: uint) -> Option<T> {
|
418 |
| - let mut tmp = Nothing; |
419 |
| - let ret; |
420 |
| - swap(&mut tmp, child); |
421 |
| - |
422 |
| - *child = match tmp { |
423 |
| - External(stored_key, stored_value) => { |
424 |
| - if stored_key == key { |
425 |
| - ret = Some(stored_value); |
426 |
| - External(stored_key, value) |
427 |
| - } else { |
428 |
| - // conflict - split the node |
429 |
| - let mut new = ~TrieNode::new(); |
430 |
| - insert(&mut new.count, |
431 |
| - &mut new.children[chunk(stored_key, idx)], |
432 |
| - stored_key, stored_value, idx + 1); |
433 |
| - ret = insert(&mut new.count, &mut new.children[chunk(key, idx)], |
434 |
| - key, value, idx + 1); |
435 |
| - Internal(new) |
436 |
| - } |
437 |
| - } |
438 |
| - Internal(x) => { |
439 |
| - let mut x = x; |
440 |
| - ret = insert(&mut x.count, &mut x.children[chunk(key, idx)], key, |
441 |
| - value, idx + 1); |
442 |
| - Internal(x) |
443 |
| - } |
444 |
| - Nothing => { |
445 |
| - *count += 1; |
446 |
| - ret = None; |
447 |
| - External(key, value) |
448 |
| - } |
449 |
| - }; |
450 |
| - return ret; |
| 418 | + // we branch twice to avoid having to do the `replace` when we |
| 419 | + // don't need to; this is much faster, especially for keys that |
| 420 | + // have long shared prefixes. |
| 421 | + match *child { |
| 422 | + Nothing => { |
| 423 | + *count += 1; |
| 424 | + *child = External(key, value); |
| 425 | + return None; |
| 426 | + } |
| 427 | + Internal(ref mut x) => { |
| 428 | + return insert(&mut x.count, &mut x.children[chunk(key, idx)], key, value, idx + 1); |
| 429 | + } |
| 430 | + External(stored_key, ref mut stored_value) if stored_key == key => { |
| 431 | + // swap in the new value and return the old. |
| 432 | + return Some(replace(stored_value, value)); |
| 433 | + } |
| 434 | + _ => {} |
| 435 | + } |
| 436 | + |
| 437 | + // conflict, an external node with differing keys: we have to |
| 438 | + // split the node, so we need the old value by value; hence we |
| 439 | + // have to move out of `child`. |
| 440 | + match replace(child, Nothing) { |
| 441 | + External(stored_key, stored_value) => { |
| 442 | + let mut new = ~TrieNode::new(); |
| 443 | + insert(&mut new.count, |
| 444 | + &mut new.children[chunk(stored_key, idx)], |
| 445 | + stored_key, stored_value, idx + 1); |
| 446 | + let ret = insert(&mut new.count, &mut new.children[chunk(key, idx)], |
| 447 | + key, value, idx + 1); |
| 448 | + *child = Internal(new); |
| 449 | + return ret; |
| 450 | + } |
| 451 | + _ => unreachable!() |
| 452 | + } |
451 | 453 | }
|
452 | 454 |
|
453 | 455 | fn remove<T>(count: &mut uint, child: &mut Child<T>, key: uint,
|
|
0 commit comments