Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
f52e2bd3
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f52e2bd3
编写于
10月 22, 2014
作者:
M
Michael Sproul
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement collection views API for TrieMap.
上级
a30b72bb
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
589 addition
and
102 deletion
+589
-102
src/libcollections/trie/map.rs
src/libcollections/trie/map.rs
+589
-102
未找到文件。
src/libcollections/trie/map.rs
浏览文件 @
f52e2bd3
...
...
@@ -8,13 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Maps are collections of unique keys with corresponding values, and sets are
//! just unique keys without a corresponding value. The `Map` and `Set` traits in
//! `std::container` define the basic interface.
//!
//! This crate defines `TrieMap` and `TrieSet`, which require `uint` keys.
//!
//! `TrieMap` is ordered.
//! Ordered maps and sets, implemented as simple tries.
use
core
::
prelude
::
*
;
...
...
@@ -24,9 +18,10 @@
use
core
::
fmt
::
Show
;
use
core
::
mem
::
zeroed
;
use
core
::
mem
;
use
core
::
ops
::{
Slice
,
SliceMut
};
use
core
::
ops
::{
Slice
,
SliceMut
};
use
core
::
uint
;
use
core
::
iter
;
use
core
::
ptr
;
use
std
::
hash
::{
Writer
,
Hash
};
use
slice
::{
Items
,
MutItems
};
...
...
@@ -36,21 +31,27 @@
// FIXME(conventions): implement into_iter
// FIXME(conventions): replace each_reverse by making iter DoubleEnded
// FIXME: #5244: need to manually update the
Trie
Node constructor
// FIXME: #5244: need to manually update the
Internal
Node constructor
const
SHIFT
:
uint
=
4
;
const
SIZE
:
uint
=
1
<<
SHIFT
;
const
MASK
:
uint
=
SIZE
-
1
;
const
NUM_CHUNKS
:
uint
=
uint
::
BITS
/
SHIFT
;
#[deriving(Clone)]
enum
Child
<
T
>
{
Internal
(
Box
<
TrieNode
<
T
>>
),
External
(
uint
,
T
),
Nothing
}
// The number of chunks that the key is divided into. Also the maximum depth of the TrieMap.
const
MAX_DEPTH
:
uint
=
uint
::
BITS
/
SHIFT
;
/// A map implemented as a radix trie.
///
/// Keys are split into sequences of 4 bits, which are used to place elements in
/// 16-entry arrays which are nested to form a tree structure. Inserted elements are placed
/// as close to the top of the tree as possible. The most significant bits of the key are used to
/// assign the key to a node/bucket in the first layer. If there are no other elements keyed by
/// the same 4 bits in the first layer, a leaf node will be created in the first layer.
/// When keys coincide, the next 4 bits are used to assign the node to a bucket in the next layer,
/// with this process continuing until an empty spot is found or there are no more bits left in the
/// key. As a result, the maximum depth using 32-bit `uint` keys is 8. The worst collisions occur
/// for very small numbers. For example, 1 and 2 are identical in all but their least significant
/// 4 bits. If both numbers are used as keys, a chain of maximum length will be created to
/// differentiate them.
///
/// # Example
///
/// ```
...
...
@@ -89,10 +90,29 @@ enum Child<T> {
/// ```
#[deriving(Clone)]
pub
struct
TrieMap
<
T
>
{
root
:
Trie
Node
<
T
>
,
root
:
Internal
Node
<
T
>
,
length
:
uint
}
// An internal node holds SIZE child nodes, which may themselves contain more internal nodes.
//
// Throughout this implementation, "idx" is used to refer to a section of key that is used
// to access a node. The layer of the tree directly below the root corresponds to idx 0.
struct
InternalNode
<
T
>
{
// The number of direct children which are external (i.e. that store a value).
count
:
uint
,
children
:
[
TrieNode
<
T
>
,
..
SIZE
]
}
// Each child of an InternalNode may be internal, in which case nesting continues,
// external (containing a value), or empty.
#[deriving(Clone)]
enum
TrieNode
<
T
>
{
Internal
(
Box
<
InternalNode
<
T
>>
),
External
(
uint
,
T
),
Nothing
}
impl
<
T
:
PartialEq
>
PartialEq
for
TrieMap
<
T
>
{
fn
eq
(
&
self
,
other
:
&
TrieMap
<
T
>
)
->
bool
{
self
.len
()
==
other
.len
()
&&
...
...
@@ -146,7 +166,7 @@ impl<T> TrieMap<T> {
#[inline]
#[unstable
=
"matches collection reform specification, waiting for dust to settle"
]
pub
fn
new
()
->
TrieMap
<
T
>
{
TrieMap
{
root
:
Trie
Node
::
new
(),
length
:
0
}
TrieMap
{
root
:
Internal
Node
::
new
(),
length
:
0
}
}
/// Visits all key-value pairs in reverse order. Aborts traversal when `f` returns `false`.
...
...
@@ -284,7 +304,7 @@ pub fn is_empty(&self) -> bool { self.len() == 0 }
#[inline]
#[unstable
=
"matches collection reform specification, waiting for dust to settle"
]
pub
fn
clear
(
&
mut
self
)
{
self
.root
=
Trie
Node
::
new
();
self
.root
=
Internal
Node
::
new
();
self
.length
=
0
;
}
...
...
@@ -396,11 +416,11 @@ pub fn swap(&mut self, key: uint, value: T) -> Option<T> {
/// ```
#[unstable
=
"matches collection reform specification, waiting for dust to settle"
]
pub
fn
insert
(
&
mut
self
,
key
:
uint
,
value
:
T
)
->
Option
<
T
>
{
let
ret
=
insert
(
&
mut
self
.root.count
,
let
(
_
,
old_val
)
=
insert
(
&
mut
self
.root.count
,
&
mut
self
.root.children
[
chunk
(
key
,
0
)],
key
,
value
,
1
);
if
ret
.is_none
()
{
self
.length
+=
1
}
ret
if
old_val
.is_none
()
{
self
.length
+=
1
}
old_val
}
/// Deprecated: Renamed to `remove`.
...
...
@@ -467,14 +487,14 @@ pub fn remove(&mut self, key: &uint) -> Option<T> {
// place that mutation is can actually occur is of the actual
// values of the TrieMap (as the return value of the
// iterator), i.e. we can never cause a deallocation of any
//
Trie
Nodes so the raw pointer is always valid.
//
Internal
Nodes so the raw pointer is always valid.
//
// # For non-`mut`
// We like sharing code so much that even a little unsafe won't
// stop us.
let
this
=
$this
;
let
mut
node
=
unsafe
{
mem
::
transmute
::
<
_
,
uint
>
(
&
this
.root
)
as
*
mut
Trie
Node
<
T
>
mem
::
transmute
::
<
_
,
uint
>
(
&
this
.root
)
as
*
mut
Internal
Node
<
T
>
};
let
key
=
$key
;
...
...
@@ -493,7 +513,7 @@ pub fn remove(&mut self, key: &uint) -> Option<T> {
Internal
(
ref
$
(
$mut_
)
*
n
)
=>
{
node
=
unsafe
{
mem
::
transmute
::
<
_
,
uint
>
(
&**
n
)
as
*
mut
Trie
Node
<
T
>
as
*
mut
Internal
Node
<
T
>
};
(
child_id
+
1
,
false
)
}
...
...
@@ -658,16 +678,11 @@ fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut T {
}
}
struct
TrieNode
<
T
>
{
count
:
uint
,
children
:
[
Child
<
T
>
,
..
SIZE
]
}
impl
<
T
:
Clone
>
Clone
for
TrieNode
<
T
>
{
impl
<
T
:
Clone
>
Clone
for
InternalNode
<
T
>
{
#[inline]
fn
clone
(
&
self
)
->
Trie
Node
<
T
>
{
fn
clone
(
&
self
)
->
Internal
Node
<
T
>
{
let
ch
=
&
self
.children
;
Trie
Node
{
Internal
Node
{
count
:
self
.count
,
children
:
[
ch
[
0
]
.clone
(),
ch
[
1
]
.clone
(),
ch
[
2
]
.clone
(),
ch
[
3
]
.clone
(),
ch
[
4
]
.clone
(),
ch
[
5
]
.clone
(),
ch
[
6
]
.clone
(),
ch
[
7
]
.clone
(),
...
...
@@ -676,12 +691,12 @@ fn clone(&self) -> TrieNode<T> {
}
}
impl
<
T
>
Trie
Node
<
T
>
{
impl
<
T
>
Internal
Node
<
T
>
{
#[inline]
fn
new
()
->
Trie
Node
<
T
>
{
fn
new
()
->
Internal
Node
<
T
>
{
// FIXME: #5244: [Nothing, ..SIZE] should be possible without implicit
// copyability
Trie
Node
{
count
:
0
,
Internal
Node
{
count
:
0
,
children
:
[
Nothing
,
Nothing
,
Nothing
,
Nothing
,
Nothing
,
Nothing
,
Nothing
,
Nothing
,
Nothing
,
Nothing
,
Nothing
,
Nothing
,
...
...
@@ -689,7 +704,7 @@ fn new() -> TrieNode<T> {
}
}
impl
<
T
>
Trie
Node
<
T
>
{
impl
<
T
>
Internal
Node
<
T
>
{
fn
each_reverse
<
'a
>
(
&
'a
self
,
f
:
|
&
uint
,
&
'a
T
|
->
bool
)
->
bool
{
for
elt
in
self
.children
.iter
()
.rev
()
{
match
*
elt
{
...
...
@@ -709,7 +724,7 @@ fn chunk(n: uint, idx: uint) -> uint {
(
n
>>
sh
)
&
MASK
}
fn
find_mut
<
'r
,
T
>
(
child
:
&
'r
mut
Child
<
T
>
,
key
:
uint
,
idx
:
uint
)
->
Option
<&
'r
mut
T
>
{
fn
find_mut
<
'r
,
T
>
(
child
:
&
'r
mut
TrieNode
<
T
>
,
key
:
uint
,
idx
:
uint
)
->
Option
<&
'r
mut
T
>
{
match
*
child
{
External
(
stored
,
ref
mut
value
)
if
stored
==
key
=>
Some
(
value
),
External
(
..
)
=>
None
,
...
...
@@ -718,58 +733,72 @@ fn find_mut<'r, T>(child: &'r mut Child<T>, key: uint, idx: uint) -> Option<&'r
}
}
fn
insert
<
T
>
(
count
:
&
mut
uint
,
child
:
&
mut
Child
<
T
>
,
key
:
uint
,
value
:
T
,
idx
:
uint
)
->
Option
<
T
>
{
// we branch twice to avoid having to do the `replace` when we
/// Inserts a new node for the given key and value, at or below `start_node`.
///
/// The index (`idx`) is the index of the next node, such that the start node
/// was accessed via parent.children[chunk(key, idx - 1)].
///
/// The count is the external node counter for the start node's parent,
/// which will be incremented only if `start_node` is transformed into a *new* external node.
///
/// Returns a mutable reference to the inserted value and an optional previous value.
fn
insert
<
'a
,
T
>
(
count
:
&
mut
uint
,
start_node
:
&
'a
mut
TrieNode
<
T
>
,
key
:
uint
,
value
:
T
,
idx
:
uint
)
->
(
&
'a
mut
T
,
Option
<
T
>
)
{
// We branch twice to avoid having to do the `replace` when we
// don't need to; this is much faster, especially for keys that
// have long shared prefixes.
match
*
child
{
match
*
start_node
{
Nothing
=>
{
*
count
+=
1
;
*
child
=
External
(
key
,
value
);
return
None
;
*
start_node
=
External
(
key
,
value
);
match
*
start_node
{
External
(
_
,
ref
mut
value_ref
)
=>
return
(
value_ref
,
None
),
_
=>
unreachable!
()
}
}
Internal
(
box
ref
mut
x
)
=>
{
return
insert
(
&
mut
x
.count
,
&
mut
x
.children
[
chunk
(
key
,
idx
)],
key
,
value
,
idx
+
1
);
}
External
(
stored_key
,
ref
mut
stored_value
)
if
stored_key
==
key
=>
{
// swap in the new value and return the old.
return
Some
(
mem
::
replace
(
stored_value
,
value
));
// Swap in the new value and return the old.
let
old_value
=
mem
::
replace
(
stored_value
,
value
);
return
(
stored_value
,
Some
(
old_value
));
}
_
=>
{}
}
// conflict, an external node with differing keys: we have to
// split the node, so we need the old value by value; hence we
// have to move out of `child`.
match
mem
::
replace
(
child
,
Nothing
)
{
// Conflict, an external node with differing keys.
// We replace the old node by an internal one, then re-insert the two values beneath it.
match
mem
::
replace
(
start_node
,
Internal
(
box
InternalNode
::
new
()))
{
External
(
stored_key
,
stored_value
)
=>
{
let
mut
new
=
box
TrieNode
::
new
();
let
ret
=
{
let
new_interior
=
&
mut
*
new
;
insert
(
&
mut
new_interior
.count
,
&
mut
new_interior
.children
[
chunk
(
stored_key
,
idx
)],
match
*
start_node
{
Internal
(
box
ref
mut
new_node
)
=>
{
// Re-insert the old value.
insert
(
&
mut
new_node
.count
,
&
mut
new_node
.children
[
chunk
(
stored_key
,
idx
)],
stored_key
,
stored_value
,
idx
+
1
);
insert
(
&
mut
new_interior
.count
,
&
mut
new_interior
.children
[
chunk
(
key
,
idx
)],
key
,
value
,
idx
+
1
)
};
*
child
=
Internal
(
new
);
return
ret
;
// Insert the new value, and return a reference to it directly.
insert
(
&
mut
new_node
.count
,
&
mut
new_node
.children
[
chunk
(
key
,
idx
)],
key
,
value
,
idx
+
1
)
}
// Value that was just copied disappeared.
_
=>
unreachable!
()
}
}
_
=>
panic!
(
"unreachable code"
),
// Logic error in previous match.
_
=>
unreachable!
(),
}
}
fn
remove
<
T
>
(
count
:
&
mut
uint
,
child
:
&
mut
Child
<
T
>
,
key
:
uint
,
fn
remove
<
T
>
(
count
:
&
mut
uint
,
child
:
&
mut
TrieNode
<
T
>
,
key
:
uint
,
idx
:
uint
)
->
Option
<
T
>
{
let
(
ret
,
this
)
=
match
*
child
{
External
(
stored
,
_
)
if
stored
==
key
=>
{
match
mem
::
replace
(
child
,
Nothing
)
{
External
(
_
,
value
)
=>
(
Some
(
value
),
true
),
_
=>
panic
!
()
_
=>
unreachable
!
()
}
}
External
(
..
)
=>
(
None
,
false
),
...
...
@@ -788,9 +817,264 @@ fn remove<T>(count: &mut uint, child: &mut Child<T>, key: uint,
return
ret
;
}
/// A view into a single entry in a TrieMap, which may be vacant or occupied.
pub
enum
Entry
<
'a
,
T
:
'a
>
{
/// An occupied entry.
Occupied
(
OccupiedEntry
<
'a
,
T
>
),
/// A vacant entry.
Vacant
(
VacantEntry
<
'a
,
T
>
)
}
/// A view into an occupied entry in a TrieMap.
pub
struct
OccupiedEntry
<
'a
,
T
:
'a
>
{
search_stack
:
SearchStack
<
'a
,
T
>
}
/// A view into a vacant entry in a TrieMap.
pub
struct
VacantEntry
<
'a
,
T
:
'a
>
{
search_stack
:
SearchStack
<
'a
,
T
>
}
/// A list of nodes encoding a path from the root of a TrieMap to a node.
///
/// Invariants:
/// * The last node is either `External` or `Nothing`.
/// * Pointers at indexes less than `length` can be safely dereferenced.
struct
SearchStack
<
'a
,
T
:
'a
>
{
map
:
&
'a
mut
TrieMap
<
T
>
,
length
:
uint
,
key
:
uint
,
items
:
[
*
mut
TrieNode
<
T
>
,
..
MAX_DEPTH
]
}
impl
<
'a
,
T
>
SearchStack
<
'a
,
T
>
{
/// Creates a new search-stack with empty entries.
fn
new
(
map
:
&
'a
mut
TrieMap
<
T
>
,
key
:
uint
)
->
SearchStack
<
'a
,
T
>
{
SearchStack
{
map
:
map
,
length
:
0
,
key
:
key
,
items
:
[
ptr
::
null_mut
(),
..
MAX_DEPTH
]
}
}
fn
push
(
&
mut
self
,
node
:
*
mut
TrieNode
<
T
>
)
{
self
.length
+=
1
;
self
.items
[
self
.length
-
1
]
=
node
;
}
fn
peek
(
&
self
)
->
*
mut
TrieNode
<
T
>
{
self
.items
[
self
.length
-
1
]
}
fn
peek_ref
(
&
self
)
->
&
'a
mut
TrieNode
<
T
>
{
unsafe
{
&
mut
*
self
.items
[
self
.length
-
1
]
}
}
fn
pop_ref
(
&
mut
self
)
->
&
'a
mut
TrieNode
<
T
>
{
self
.length
-=
1
;
unsafe
{
&
mut
*
self
.items
[
self
.length
]
}
}
fn
is_empty
(
&
self
)
->
bool
{
self
.length
==
0
}
fn
get_ref
(
&
self
,
idx
:
uint
)
->
&
'a
mut
TrieNode
<
T
>
{
assert
!
(
idx
<
self
.length
);
unsafe
{
&
mut
*
self
.items
[
idx
]
}
}
}
// Implementation of SearchStack creation logic.
// Once a SearchStack has been created the Entry methods are relatively straight-forward.
impl
<
T
>
TrieMap
<
T
>
{
/// Gets the given key's corresponding entry in the map for in-place manipulation.
#[inline]
pub
fn
entry
<
'a
>
(
&
'a
mut
self
,
key
:
uint
)
->
Entry
<
'a
,
T
>
{
// Create an empty search stack.
let
mut
search_stack
=
SearchStack
::
new
(
self
,
key
);
// Unconditionally add the corresponding node from the first layer.
let
first_node
=
&
mut
search_stack
.map.root.children
[
chunk
(
key
,
0
)]
as
*
mut
_
;
search_stack
.push
(
first_node
);
// While no appropriate slot is found, keep descending down the Trie,
// adding nodes to the search stack.
let
search_successful
:
bool
;
loop
{
match
unsafe
{
next_child
(
search_stack
.peek
(),
key
,
search_stack
.length
)
}
{
(
Some
(
child
),
_
)
=>
search_stack
.push
(
child
),
(
None
,
success
)
=>
{
search_successful
=
success
;
break
;
}
}
}
if
search_successful
{
Occupied
(
OccupiedEntry
{
search_stack
:
search_stack
})
}
else
{
Vacant
(
VacantEntry
{
search_stack
:
search_stack
})
}
}
}
/// Get a mutable pointer to the next child of a node, given a key and an idx.
///
/// The idx is the index of the next child, such that `node` was accessed via
/// parent.children[chunk(key, idx - 1)].
///
/// Returns a tuple with an optional mutable pointer to the next child, and
/// a boolean flag to indicate whether the external key node was found.
///
/// This function is safe only if `node` points to a valid `TrieNode`.
#[inline]
unsafe
fn
next_child
<
'a
,
T
>
(
node
:
*
mut
TrieNode
<
T
>
,
key
:
uint
,
idx
:
uint
)
->
(
Option
<*
mut
TrieNode
<
T
>>
,
bool
)
{
match
*
node
{
// If the node is internal, tell the caller to descend further.
Internal
(
box
ref
mut
node_internal
)
=>
{
(
Some
(
&
mut
node_internal
.children
[
chunk
(
key
,
idx
)]
as
*
mut
_
),
false
)
},
// If the node is external or empty, the search is complete.
// If the key doesn't match, node expansion will be done upon
// insertion. If it does match, we've found our node.
External
(
stored_key
,
_
)
if
stored_key
==
key
=>
(
None
,
true
),
External
(
..
)
|
Nothing
=>
(
None
,
false
)
}
}
// NB: All these methods assume a correctly constructed occupied entry (matching the given key).
impl
<
'a
,
T
>
OccupiedEntry
<
'a
,
T
>
{
/// Gets a reference to the value in the entry.
#[inline]
pub
fn
get
(
&
self
)
->
&
T
{
match
*
self
.search_stack
.peek_ref
()
{
External
(
_
,
ref
value
)
=>
value
,
// Invalid SearchStack, non-external last node.
_
=>
unreachable!
()
}
}
/// Gets a mutable reference to the value in the entry.
#[inline]
pub
fn
get_mut
(
&
mut
self
)
->
&
mut
T
{
match
*
self
.search_stack
.peek_ref
()
{
External
(
_
,
ref
mut
value
)
=>
value
,
// Invalid SearchStack, non-external last node.
_
=>
unreachable!
()
}
}
/// Converts the OccupiedEntry into a mutable reference to the value in the entry,
/// with a lifetime bound to the map itself.
#[inline]
pub
fn
into_mut
(
self
)
->
&
'a
mut
T
{
match
*
self
.search_stack
.peek_ref
()
{
External
(
_
,
ref
mut
value
)
=>
value
,
// Invalid SearchStack, non-external last node.
_
=>
unreachable!
()
}
}
/// Sets the value of the entry, and returns the entry's old value.
#[inline]
pub
fn
set
(
&
mut
self
,
value
:
T
)
->
T
{
match
*
self
.search_stack
.peek_ref
()
{
External
(
_
,
ref
mut
stored_value
)
=>
{
mem
::
replace
(
stored_value
,
value
)
}
// Invalid SearchStack, non-external last node.
_
=>
unreachable!
()
}
}
/// Takes the value out of the entry, and returns it.
#[inline]
pub
fn
take
(
self
)
->
T
{
// This function removes the external leaf-node, then unwinds the search-stack
// deleting now-childless ancestors.
let
mut
search_stack
=
self
.search_stack
;
// Extract the value from the leaf-node of interest.
let
leaf_node
=
mem
::
replace
(
search_stack
.pop_ref
(),
Nothing
);
let
value
=
match
leaf_node
{
External
(
_
,
value
)
=>
value
,
// Invalid SearchStack, non-external last node.
_
=>
unreachable!
()
};
// Iterate backwards through the search stack, deleting nodes if they are childless.
// We compare each ancestor's parent count to 1 because each ancestor reached has just
// had one of its children deleted.
while
!
search_stack
.is_empty
()
{
let
ancestor
=
search_stack
.pop_ref
();
match
*
ancestor
{
Internal
(
ref
mut
internal
)
=>
{
// If stopping deletion, update the child count and break.
if
internal
.count
!=
1
{
internal
.count
-=
1
;
break
;
}
}
// Invalid SearchStack, non-internal ancestor node.
_
=>
unreachable!
()
}
*
ancestor
=
Nothing
;
}
// Decrement the length of the entire TrieMap, for the removed node.
search_stack
.map.length
-=
1
;
value
}
}
impl
<
'a
,
T
>
VacantEntry
<
'a
,
T
>
{
/// Set the vacant entry to the given value.
pub
fn
set
(
self
,
value
:
T
)
->
&
'a
mut
T
{
let
search_stack
=
self
.search_stack
;
let
old_length
=
search_stack
.length
;
let
key
=
search_stack
.key
;
// Update the TrieMap's length for the new element.
search_stack
.map.length
+=
1
;
// If there's only 1 node in the search stack, insert a new node below it at idx 1.
if
old_length
==
1
{
// Note: Small hack to appease the borrow checker. Can't mutably borrow root.count
let
mut
temp
=
search_stack
.map.root.count
;
let
(
value_ref
,
_
)
=
insert
(
&
mut
temp
,
search_stack
.get_ref
(
0
),
key
,
value
,
1
);
search_stack
.map.root.count
=
temp
;
value_ref
}
// Otherwise, find the predeccessor of the last stack node, and insert as normal.
else
{
match
*
search_stack
.get_ref
(
old_length
-
2
)
{
Internal
(
box
ref
mut
parent
)
=>
{
let
(
value_ref
,
_
)
=
insert
(
&
mut
parent
.count
,
&
mut
parent
.children
[
chunk
(
key
,
old_length
-
1
)],
key
,
value
,
old_length
);
value_ref
}
// Invalid SearchStack, non-internal ancestor node.
_
=>
unreachable!
()
}
}
}
}
/// A forward iterator over a map.
pub
struct
Entries
<
'a
,
T
:
'a
>
{
stack
:
[
slice
::
Items
<
'a
,
Child
<
T
>>
,
..
NUM_CHUNKS
],
stack
:
[
slice
::
Items
<
'a
,
TrieNode
<
T
>>
,
..
MAX_DEPTH
],
length
:
uint
,
remaining_min
:
uint
,
remaining_max
:
uint
...
...
@@ -799,7 +1083,7 @@ pub struct Entries<'a, T:'a> {
/// A forward iterator over the key-value pairs of a map, with the
/// values being mutable.
pub
struct
MutEntries
<
'a
,
T
:
'a
>
{
stack
:
[
slice
::
MutItems
<
'a
,
Child
<
T
>>
,
..
NUM_CHUNKS
],
stack
:
[
slice
::
MutItems
<
'a
,
TrieNode
<
T
>>
,
..
MAX_DEPTH
],
length
:
uint
,
remaining_min
:
uint
,
remaining_max
:
uint
...
...
@@ -937,9 +1221,10 @@ mod test {
use
std
::
uint
;
use
std
::
hash
;
use
super
::{
TrieMap
,
TrieNode
,
Internal
,
External
,
Nothing
};
use
super
::{
TrieMap
,
InternalNode
,
Internal
,
External
,
Nothing
};
use
super
::{
Occupied
,
Vacant
};
fn
check_integrity
<
T
>
(
trie
:
&
Trie
Node
<
T
>
)
{
fn
check_integrity
<
T
>
(
trie
:
&
Internal
Node
<
T
>
)
{
assert
!
(
trie
.count
!=
0
);
let
mut
sum
=
0
;
...
...
@@ -1344,6 +1629,135 @@ fn test_index_nonexistent() {
map
[
4
];
}
// Number of items to insert into the map during entry tests.
// The tests rely on it being even.
const
SQUARES_UPPER_LIM
:
uint
=
128
;
/// Make a TrieMap storing i^2 for i in [0, 128)
fn
squares_map
()
->
TrieMap
<
uint
>
{
let
mut
map
=
TrieMap
::
new
();
for
i
in
range
(
0
,
SQUARES_UPPER_LIM
)
{
map
.insert
(
i
,
i
*
i
);
}
map
}
#[test]
fn
test_entry_get
()
{
let
mut
map
=
squares_map
();
for
i
in
range
(
0
,
SQUARES_UPPER_LIM
)
{
match
map
.entry
(
i
)
{
Occupied
(
slot
)
=>
assert_eq!
(
slot
.get
(),
&
(
i
*
i
)),
Vacant
(
_
)
=>
panic!
(
"Key not found."
)
}
}
check_integrity
(
&
map
.root
);
}
#[test]
fn
test_entry_get_mut
()
{
let
mut
map
=
squares_map
();
// Change the entries to cubes.
for
i
in
range
(
0
,
SQUARES_UPPER_LIM
)
{
match
map
.entry
(
i
)
{
Occupied
(
mut
e
)
=>
{
*
e
.get_mut
()
=
i
*
i
*
i
;
}
Vacant
(
_
)
=>
panic!
(
"Key not found."
)
}
assert_eq!
(
map
.get
(
&
i
)
.unwrap
(),
&
(
i
*
i
*
i
));
}
check_integrity
(
&
map
.root
);
}
#[test]
fn
test_entry_into_mut
()
{
let
mut
map
=
TrieMap
::
new
();
map
.insert
(
3
,
6u
);
let
value_ref
=
match
map
.entry
(
3
)
{
Occupied
(
e
)
=>
e
.into_mut
(),
Vacant
(
_
)
=>
panic!
(
"Entry not found."
)
};
assert_eq!
(
*
value_ref
,
6u
);
}
#[test]
fn
test_entry_take
()
{
let
mut
map
=
squares_map
();
assert_eq!
(
map
.len
(),
SQUARES_UPPER_LIM
);
// Remove every odd key, checking that the correct value is returned.
for
i
in
range_step
(
1
,
SQUARES_UPPER_LIM
,
2
)
{
match
map
.entry
(
i
)
{
Occupied
(
e
)
=>
assert_eq!
(
e
.take
(),
i
*
i
),
Vacant
(
_
)
=>
panic!
(
"Key not found."
)
}
}
check_integrity
(
&
map
.root
);
// Check that the values for even keys remain unmodified.
for
i
in
range_step
(
0
,
SQUARES_UPPER_LIM
,
2
)
{
assert_eq!
(
map
.get
(
&
i
)
.unwrap
(),
&
(
i
*
i
));
}
assert_eq!
(
map
.len
(),
SQUARES_UPPER_LIM
/
2
);
}
#[test]
fn
test_occupied_entry_set
()
{
let
mut
map
=
squares_map
();
// Change all the entries to cubes.
for
i
in
range
(
0
,
SQUARES_UPPER_LIM
)
{
match
map
.entry
(
i
)
{
Occupied
(
mut
e
)
=>
assert_eq!
(
e
.set
(
i
*
i
*
i
),
i
*
i
),
Vacant
(
_
)
=>
panic!
(
"Key not found."
)
}
assert_eq!
(
map
.get
(
&
i
)
.unwrap
(),
&
(
i
*
i
*
i
));
}
check_integrity
(
&
map
.root
);
}
#[test]
fn
test_vacant_entry_set
()
{
let
mut
map
=
TrieMap
::
new
();
for
i
in
range
(
0
,
SQUARES_UPPER_LIM
)
{
match
map
.entry
(
i
)
{
Vacant
(
e
)
=>
{
// Insert i^2.
let
inserted_val
=
e
.set
(
i
*
i
);
assert_eq!
(
*
inserted_val
,
i
*
i
);
// Update it to i^3 using the returned mutable reference.
*
inserted_val
=
i
*
i
*
i
;
},
_
=>
panic!
(
"Non-existant key found."
)
}
assert_eq!
(
map
.get
(
&
i
)
.unwrap
(),
&
(
i
*
i
*
i
));
}
check_integrity
(
&
map
.root
);
assert_eq!
(
map
.len
(),
SQUARES_UPPER_LIM
);
}
#[test]
fn
test_single_key
()
{
let
mut
map
=
TrieMap
::
new
();
map
.insert
(
1
,
2u
);
match
map
.entry
(
1
)
{
Occupied
(
e
)
=>
{
e
.take
();
},
_
=>
()
}
}
}
#[cfg(test)]
...
...
@@ -1352,16 +1766,22 @@ mod bench {
use
std
::
rand
::{
weak_rng
,
Rng
};
use
test
::{
Bencher
,
black_box
};
use
super
::
TrieMap
;
use
super
::
{
TrieMap
,
Occupied
,
Vacant
}
;
fn
bench_iter
(
b
:
&
mut
Bencher
,
size
:
uint
)
{
const
MAP_SIZE
:
uint
=
1000
;
fn
random_map
(
size
:
uint
)
->
TrieMap
<
uint
>
{
let
mut
map
=
TrieMap
::
<
uint
>
::
new
();
let
mut
rng
=
weak_rng
();
for
_
in
range
(
0
,
size
)
{
map
.insert
(
rng
.gen
(),
rng
.gen
());
}
map
}
fn
bench_iter
(
b
:
&
mut
Bencher
,
size
:
uint
)
{
let
map
=
random_map
(
size
);
b
.iter
(||
{
for
entry
in
map
.iter
()
{
black_box
(
entry
);
...
...
@@ -1388,7 +1808,7 @@ pub fn iter_100000(b: &mut Bencher) {
fn
bench_lower_bound
(
b
:
&
mut
Bencher
)
{
let
mut
m
=
TrieMap
::
<
uint
>
::
new
();
let
mut
rng
=
weak_rng
();
for
_
in
range
(
0u
,
1000
)
{
for
_
in
range
(
0u
,
MAP_SIZE
)
{
m
.insert
(
rng
.gen
(),
rng
.gen
());
}
...
...
@@ -1403,7 +1823,7 @@ fn bench_lower_bound(b: &mut Bencher) {
fn
bench_upper_bound
(
b
:
&
mut
Bencher
)
{
let
mut
m
=
TrieMap
::
<
uint
>
::
new
();
let
mut
rng
=
weak_rng
();
for
_
in
range
(
0u
,
1000
)
{
for
_
in
range
(
0u
,
MAP_SIZE
)
{
m
.insert
(
rng
.gen
(),
rng
.gen
());
}
...
...
@@ -1420,22 +1840,38 @@ fn bench_insert_large(b: &mut Bencher) {
let
mut
rng
=
weak_rng
();
b
.iter
(||
{
for
_
in
range
(
0u
,
1000
)
{
for
_
in
range
(
0u
,
MAP_SIZE
)
{
m
.insert
(
rng
.gen
(),
[
1
,
..
10
]);
}
})
});
}
#[bench]
fn
bench_insert_large_entry
(
b
:
&
mut
Bencher
)
{
let
mut
m
=
TrieMap
::
<
[
uint
,
..
10
]
>
::
new
();
let
mut
rng
=
weak_rng
();
b
.iter
(||
{
for
_
in
range
(
0u
,
MAP_SIZE
)
{
match
m
.entry
(
rng
.gen
())
{
Occupied
(
mut
e
)
=>
{
e
.set
([
1
,
..
10
]);
},
Vacant
(
e
)
=>
{
e
.set
([
1
,
..
10
]);
}
}
}
});
}
#[bench]
fn
bench_insert_large_low_bits
(
b
:
&
mut
Bencher
)
{
let
mut
m
=
TrieMap
::
<
[
uint
,
..
10
]
>
::
new
();
let
mut
rng
=
weak_rng
();
b
.iter
(||
{
for
_
in
range
(
0u
,
1000
)
{
for
_
in
range
(
0u
,
MAP_SIZE
)
{
// only have the last few bits set.
m
.insert
(
rng
.gen
::
<
uint
>
()
&
0xff_ff
,
[
1
,
..
10
]);
}
})
});
}
#[bench]
...
...
@@ -1444,21 +1880,72 @@ fn bench_insert_small(b: &mut Bencher) {
let
mut
rng
=
weak_rng
();
b
.iter
(||
{
for
_
in
range
(
0u
,
1000
)
{
for
_
in
range
(
0u
,
MAP_SIZE
)
{
m
.insert
(
rng
.gen
(),
());
}
})
});
}
#[bench]
fn
bench_insert_small_low_bits
(
b
:
&
mut
Bencher
)
{
let
mut
m
=
TrieMap
::
<
()
>
::
new
();
let
mut
rng
=
weak_rng
();
b
.iter
(||
{
for
_
in
range
(
0u
,
1000
)
{
for
_
in
range
(
0u
,
MAP_SIZE
)
{
// only have the last few bits set.
m
.insert
(
rng
.gen
::
<
uint
>
()
&
0xff_ff
,
());
}
})
});
}
#[bench]
fn
bench_get
(
b
:
&
mut
Bencher
)
{
let
map
=
random_map
(
MAP_SIZE
);
let
keys
:
Vec
<
uint
>
=
map
.keys
()
.collect
();
b
.iter
(||
{
for
key
in
keys
.iter
()
{
black_box
(
map
.get
(
key
));
}
});
}
#[bench]
fn
bench_get_entry
(
b
:
&
mut
Bencher
)
{
let
mut
map
=
random_map
(
MAP_SIZE
);
let
keys
:
Vec
<
uint
>
=
map
.keys
()
.collect
();
b
.iter
(||
{
for
key
in
keys
.iter
()
{
match
map
.entry
(
*
key
)
{
Occupied
(
e
)
=>
{
black_box
(
e
.get
());
},
_
=>
()
}
}
});
}
#[bench]
fn
bench_remove
(
b
:
&
mut
Bencher
)
{
b
.iter
(||
{
let
mut
map
=
random_map
(
MAP_SIZE
);
let
keys
:
Vec
<
uint
>
=
map
.keys
()
.collect
();
for
key
in
keys
.iter
()
{
black_box
(
map
.remove
(
key
));
}
});
}
#[bench]
fn
bench_remove_entry
(
b
:
&
mut
Bencher
)
{
b
.iter
(||
{
let
mut
map
=
random_map
(
MAP_SIZE
);
let
keys
:
Vec
<
uint
>
=
map
.keys
()
.collect
();
for
key
in
keys
.iter
()
{
match
map
.entry
(
*
key
)
{
Occupied
(
e
)
=>
{
black_box
(
e
.take
());
},
_
=>
()
}
}
});
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录