@@ -10,6 +10,8 @@ extern crate alloc;
1010#[ cfg( feature = "no_std" ) ]
1111use alloc:: vec:: Vec ;
1212
13+ const PANIC_MSG : & str = "graph contains cycle(s)" ;
14+
1315#[ derive( Debug ) ]
1416/// Topological Iterator
1517pub struct Topo < ' a , T > {
@@ -43,7 +45,7 @@ impl<'a, T> Topo<'a, T> {
4345 /// Will return None if:
4446 ///
4547 /// * No vertices are left.
46- fn process_vertex ( & mut self ) -> Option < & ' a VertexId > {
48+ fn process_vertex ( & mut self , check_cyclic : bool ) -> Option < & ' a VertexId > {
4749 match self . roots . pop ( ) {
4850 Some ( node) => {
4951 self . vertices . push ( node) ;
@@ -64,7 +66,12 @@ impl<'a, T> Topo<'a, T> {
6466 }
6567 Some ( node)
6668 } ,
67- None => None ,
69+ None => {
70+ if check_cyclic && self . vertices . len ( ) != self . iterable . vertex_count ( ) {
71+ panic ! ( PANIC_MSG ) ;
72+ }
73+ None
74+ } ,
6875 }
6976 }
7077
@@ -76,7 +83,7 @@ impl<'a, T> Topo<'a, T> {
7683 /// It is a logic error to use this iterator after calling this function.
7784 pub fn is_cyclic ( & mut self ) -> bool {
7885 //Search until an answer is found.
79- while self . process_vertex ( ) . is_some ( ) { }
86+ while self . process_vertex ( false ) . is_some ( ) { }
8087
8188 self . vertices . len ( ) != self . iterable . vertex_count ( )
8289 }
@@ -92,7 +99,7 @@ impl<'a, T> Iterator for Topo<'a, T> {
9299 }
93100 fn next ( & mut self ) -> Option < Self :: Item > {
94101 ( 0 ..self . size_hint ( ) . 1 . unwrap ( ) )
95- . filter_map ( move |_| self . process_vertex ( ) )
102+ . filter_map ( move |_| self . process_vertex ( true ) )
96103 . next ( )
97104 }
98105}
@@ -153,4 +160,39 @@ mod tests {
153160
154161 assert ! ( topo. is_cyclic( ) ) ;
155162 }
163+
164+ #[ test]
165+ #[ should_panic( expected = "graph contains cycle(s)" ) ]
166+ fn is_cyclic_and_panic ( ) {
167+ let mut graph: Graph < usize > = Graph :: new ( ) ;
168+
169+ let v1 = graph. add_vertex ( 1 ) ;
170+ let v2 = graph. add_vertex ( 2 ) ;
171+ let v3 = graph. add_vertex ( 3 ) ;
172+ let v4 = graph. add_vertex ( 4 ) ;
173+ let v5 = graph. add_vertex ( 5 ) ;
174+ let v6 = graph. add_vertex ( 6 ) ;
175+ let v7 = graph. add_vertex ( 7 ) ;
176+
177+ graph. add_edge ( & v1, & v4) . unwrap ( ) ;
178+ graph. add_edge ( & v2, & v4) . unwrap ( ) ;
179+ graph. add_edge ( & v2, & v5) . unwrap ( ) ;
180+ graph. add_edge ( & v3, & v5) . unwrap ( ) ;
181+ graph. add_edge ( & v4, & v6) . unwrap ( ) ;
182+ graph. add_edge ( & v4, & v7) . unwrap ( ) ;
183+ graph. add_edge ( & v5, & v6) . unwrap ( ) ;
184+ graph. add_edge ( & v6, & v7) . unwrap ( ) ;
185+ graph. add_edge ( & v7, & v2) . unwrap ( ) ;
186+
187+ let mut topo = graph. topo ( ) ;
188+
189+ topo. next ( ) ;
190+ topo. next ( ) ;
191+ topo. next ( ) ;
192+ topo. next ( ) ;
193+ topo. next ( ) ;
194+ topo. next ( ) ;
195+ topo. next ( ) ;
196+ }
197+
156198}
0 commit comments