1
1
use std:: borrow:: Borrow ;
2
- use std:: collections:: { HashMap , HashSet } ;
2
+ use std:: collections:: BTreeSet ;
3
3
use std:: fmt;
4
- use std:: hash:: Hash ;
5
4
6
- pub struct Graph < N , E > {
7
- nodes : HashMap < N , HashMap < N , E > > ,
5
+ use im_rc;
6
+
7
+ pub struct Graph < N : Clone , E : Clone > {
8
+ nodes : im_rc:: OrdMap < N , im_rc:: OrdMap < N , E > > ,
8
9
}
9
10
10
- impl < N : Eq + Hash + Clone , E : Default > Graph < N , E > {
11
+ impl < N : Eq + Ord + Clone , E : Default + Clone > Graph < N , E > {
11
12
pub fn new ( ) -> Graph < N , E > {
12
13
Graph {
13
- nodes : HashMap :: new ( ) ,
14
+ nodes : im_rc :: OrdMap :: new ( ) ,
14
15
}
15
16
}
16
17
17
18
pub fn add ( & mut self , node : N ) {
18
- self . nodes . entry ( node) . or_insert_with ( HashMap :: new) ;
19
+ self . nodes . entry ( node) . or_insert_with ( im_rc :: OrdMap :: new) ;
19
20
}
20
21
21
22
pub fn link ( & mut self , node : N , child : N ) -> & mut E {
22
23
self . nodes
23
24
. entry ( node)
24
- . or_insert_with ( HashMap :: new)
25
+ . or_insert_with ( im_rc :: OrdMap :: new)
25
26
. entry ( child)
26
27
. or_insert_with ( Default :: default)
27
28
}
28
29
29
30
pub fn contains < Q : ?Sized > ( & self , k : & Q ) -> bool
30
31
where
31
32
N : Borrow < Q > ,
32
- Q : Hash + Eq ,
33
+ Q : Ord + Eq ,
33
34
{
34
35
self . nodes . contains_key ( k)
35
36
}
@@ -38,14 +39,14 @@ impl<N: Eq + Hash + Clone, E: Default> Graph<N, E> {
38
39
self . nodes . get ( from) ?. get ( to)
39
40
}
40
41
41
- pub fn edges ( & self , from : & N ) -> impl Iterator < Item = ( & N , & E ) > {
42
+ pub fn edges ( & self , from : & N ) -> impl Iterator < Item = & ( N , E ) > {
42
43
self . nodes . get ( from) . into_iter ( ) . flat_map ( |x| x. iter ( ) )
43
44
}
44
45
45
46
/// A topological sort of the `Graph`
46
47
pub fn sort ( & self ) -> Vec < N > {
47
48
let mut ret = Vec :: new ( ) ;
48
- let mut marks = HashSet :: new ( ) ;
49
+ let mut marks = BTreeSet :: new ( ) ;
49
50
50
51
for node in self . nodes . keys ( ) {
51
52
self . sort_inner_visit ( node, & mut ret, & mut marks) ;
@@ -54,7 +55,7 @@ impl<N: Eq + Hash + Clone, E: Default> Graph<N, E> {
54
55
ret
55
56
}
56
57
57
- fn sort_inner_visit ( & self , node : & N , dst : & mut Vec < N > , marks : & mut HashSet < N > ) {
58
+ fn sort_inner_visit ( & self , node : & N , dst : & mut Vec < N > , marks : & mut BTreeSet < N > ) {
58
59
if !marks. insert ( node. clone ( ) ) {
59
60
return ;
60
61
}
@@ -70,6 +71,23 @@ impl<N: Eq + Hash + Clone, E: Default> Graph<N, E> {
70
71
self . nodes . keys ( )
71
72
}
72
73
74
+ /// Resolves one of the paths from the given dependent package down to
75
+ /// a leaf.
76
+ pub fn path_to_bottom < ' a > ( & ' a self , mut pkg : & ' a N ) -> Vec < & ' a N > {
77
+ let mut result = vec ! [ pkg] ;
78
+ while let Some ( p) = self . nodes . get ( pkg) . and_then ( |p| {
79
+ p. iter ( )
80
+ // Note that we can have "cycles" introduced through dev-dependency
81
+ // edges, so make sure we don't loop infinitely.
82
+ . find ( |& ( node, _) | !result. contains ( & node) )
83
+ . map ( |( ref p, _) | p)
84
+ } ) {
85
+ result. push ( p) ;
86
+ pkg = p;
87
+ }
88
+ result
89
+ }
90
+
73
91
/// Resolves one of the paths from the given dependent package up to
74
92
/// the root.
75
93
pub fn path_to_top < ' a > ( & ' a self , mut pkg : & ' a N ) -> Vec < & ' a N > {
@@ -84,7 +102,7 @@ impl<N: Eq + Hash + Clone, E: Default> Graph<N, E> {
84
102
// Note that we can have "cycles" introduced through dev-dependency
85
103
// edges, so make sure we don't loop infinitely.
86
104
. find ( |& ( node, _) | !res. contains ( & node) )
87
- . map ( |p | p. 0 )
105
+ . map ( |( ref p , _ ) | p)
88
106
} ;
89
107
while let Some ( p) = first_pkg_depending_on ( pkg, & result) {
90
108
result. push ( p) ;
@@ -94,13 +112,13 @@ impl<N: Eq + Hash + Clone, E: Default> Graph<N, E> {
94
112
}
95
113
}
96
114
97
- impl < N : Eq + Hash + Clone , E : Default > Default for Graph < N , E > {
115
+ impl < N : Eq + Ord + Clone , E : Default + Clone > Default for Graph < N , E > {
98
116
fn default ( ) -> Graph < N , E > {
99
117
Graph :: new ( )
100
118
}
101
119
}
102
120
103
- impl < N : fmt:: Display + Eq + Hash , E > fmt:: Debug for Graph < N , E > {
121
+ impl < N : fmt:: Display + Eq + Ord + Clone , E : Clone > fmt:: Debug for Graph < N , E > {
104
122
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
105
123
writeln ! ( fmt, "Graph {{" ) ?;
106
124
@@ -118,14 +136,14 @@ impl<N: fmt::Display + Eq + Hash, E> fmt::Debug for Graph<N, E> {
118
136
}
119
137
}
120
138
121
- impl < N : Eq + Hash , E : Eq > PartialEq for Graph < N , E > {
139
+ impl < N : Eq + Ord + Clone , E : Eq + Clone > PartialEq for Graph < N , E > {
122
140
fn eq ( & self , other : & Graph < N , E > ) -> bool {
123
141
self . nodes . eq ( & other. nodes )
124
142
}
125
143
}
126
- impl < N : Eq + Hash , E : Eq > Eq for Graph < N , E > { }
144
+ impl < N : Eq + Ord + Clone , E : Eq + Clone > Eq for Graph < N , E > { }
127
145
128
- impl < N : Eq + Hash + Clone , E : Clone > Clone for Graph < N , E > {
146
+ impl < N : Eq + Ord + Clone , E : Clone > Clone for Graph < N , E > {
129
147
fn clone ( & self ) -> Graph < N , E > {
130
148
Graph {
131
149
nodes : self . nodes . clone ( ) ,
0 commit comments