1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//!
//! # Dependency-Ordering Trait and Helpers
//!
// Std-lib
use HashSet;
use PhantomData;
///
/// # Dependency-Ordering Trait
///
/// Many layout-types include a graph-like structure of dependencies between items.
/// Libraries in which cells instantiate other cells serve as prime examples.
/// Graph nodes are commonly stored unordered, but must occassionally be dependency-ordered
/// to perform processing tasks.
///
/// The [DepOrder] trait aids these orderings.
/// It requires a single user-defined method `process`, which processes a single `Item`.
/// The associated `Item` type is commonly a pointer to a graph node.
/// The implementation of `process` is responsible for iterating over `item`'s (direct) dependencies,
/// and passing each as an argument to `orderer.push`.
/// The `push` method, implemented on local helper-type [DepOrderer], recursively traverses
/// dependencies, calling `process` on each.
/// `push` also monitors for graph-cycles and returns the associated `Error` type if one is detected.
///
/// Typical usage:
///
/// ```text
/// struct MyGraphOrder;
/// impl DepOrder for MyGraphOrder {
/// type Item = Ptr<Node>;
/// type Error = MyError;
///
/// /// Process a single `item`
/// fn process(item: &Self::Item, orderer: &mut DepOrderer<Self>) -> Result<(), Self::Error> {
/// // Push each dependency
/// for dep in item.dependencies() {
/// orderer.push(dep);
/// }
/// // And return
/// Ok(())
/// }
/// fn fail() -> Result<(), Self::Error> {
/// Err(MyError::new())
/// }
/// }
/// ```
///
/// The default-implemented [DepOrder::order] creates and returns a dependency-ordered vector of `Item`s.
/// This method serves as the primary entrypoint for typical usage:
///
/// ```text
/// for item in MyGraphOrder::order(MyGraph::random()) {
/// // Do something with item
/// }
/// ```
///
/// # Dependency Order Helper
/// Should not be used directly.
/// Public solely for use in the call-signature of [DepOrder::process].