github.com/gopherd/gonum@v0.0.4/graph/nodes_edges.go (about) 1 // Copyright ©2018 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package graph 6 7 // Iterator is an item iterator. 8 type Iterator interface { 9 // Next advances the iterator and returns whether 10 // the next call to the item method will return a 11 // non-nil item. 12 // 13 // Next should be called prior to any call to the 14 // iterator's item retrieval method after the 15 // iterator has been obtained or reset. 16 // 17 // The order of iteration is implementation 18 // dependent. 19 Next() bool 20 21 // Len returns the number of items remaining in the 22 // iterator. 23 // 24 // If the number of items in the iterator is unknown, 25 // too large to materialize or too costly to calculate 26 // then Len may return a negative value. 27 // In this case the consuming function must be able 28 // to operate on the items of the iterator directly 29 // without materializing the items into a slice. 30 // The magnitude of a negative length has 31 // implementation-dependent semantics. 32 Len() int 33 34 // Reset returns the iterator to its start position. 35 Reset() 36 } 37 38 // Nodes is a Node iterator. 39 type Nodes interface { 40 Iterator 41 42 // Node returns the current Node from the iterator. 43 Node() Node 44 } 45 46 // NodeSlicer wraps the NodeSlice method. 47 type NodeSlicer interface { 48 // NodeSlice returns the set of nodes remaining 49 // to be iterated by a Nodes iterator. 50 // The holder of the iterator may arbitrarily 51 // change elements in the returned slice, but 52 // those changes may be reflected to other 53 // iterators. 54 NodeSlice() []Node 55 } 56 57 // NodesOf returns it.Len() nodes from it. If it is a NodeSlicer, the NodeSlice method 58 // is used to obtain the nodes. It is safe to pass a nil Nodes to NodesOf. 59 func NodesOf(it Nodes) []Node { 60 if it == nil { 61 return nil 62 } 63 n := it.Len() 64 switch { 65 case n == 0: 66 return nil 67 case n < 0: 68 n = 0 69 } 70 switch it := it.(type) { 71 case NodeSlicer: 72 return it.NodeSlice() 73 } 74 nodes := make([]Node, 0, n) 75 for it.Next() { 76 nodes = append(nodes, it.Node()) 77 } 78 if len(nodes) == 0 { 79 return nil 80 } 81 return nodes 82 } 83 84 // Edges is an Edge iterator. 85 type Edges interface { 86 Iterator 87 88 // Edge returns the current Edge from the iterator. 89 Edge() Edge 90 } 91 92 // EdgeSlicer wraps the EdgeSlice method. 93 type EdgeSlicer interface { 94 // EdgeSlice returns the set of edges remaining 95 // to be iterated by an Edges iterator. 96 // The holder of the iterator may arbitrarily 97 // change elements in the returned slice, but 98 // those changes may be reflected to other 99 // iterators. 100 EdgeSlice() []Edge 101 } 102 103 // EdgesOf returns it.Len() nodes from it. If it is an EdgeSlicer, the EdgeSlice method is used 104 // to obtain the edges. It is safe to pass a nil Edges to EdgesOf. 105 func EdgesOf(it Edges) []Edge { 106 if it == nil { 107 return nil 108 } 109 n := it.Len() 110 switch { 111 case n == 0: 112 return nil 113 case n < 0: 114 n = 0 115 } 116 switch it := it.(type) { 117 case EdgeSlicer: 118 return it.EdgeSlice() 119 } 120 edges := make([]Edge, 0, n) 121 for it.Next() { 122 edges = append(edges, it.Edge()) 123 } 124 if len(edges) == 0 { 125 return nil 126 } 127 return edges 128 } 129 130 // WeightedEdges is a WeightedEdge iterator. 131 type WeightedEdges interface { 132 Iterator 133 134 // Edge returns the current Edge from the iterator. 135 WeightedEdge() WeightedEdge 136 } 137 138 // WeightedEdgeSlicer wraps the WeightedEdgeSlice method. 139 type WeightedEdgeSlicer interface { 140 // EdgeSlice returns the set of edges remaining 141 // to be iterated by an Edges iterator. 142 // The holder of the iterator may arbitrarily 143 // change elements in the returned slice, but 144 // those changes may be reflected to other 145 // iterators. 146 WeightedEdgeSlice() []WeightedEdge 147 } 148 149 // WeightedEdgesOf returns it.Len() weighted edge from it. If it is a WeightedEdgeSlicer, the 150 // WeightedEdgeSlice method is used to obtain the edges. It is safe to pass a nil WeightedEdges 151 // to WeightedEdgesOf. 152 func WeightedEdgesOf(it WeightedEdges) []WeightedEdge { 153 if it == nil { 154 return nil 155 } 156 n := it.Len() 157 switch { 158 case n == 0: 159 return nil 160 case n < 0: 161 n = 0 162 } 163 switch it := it.(type) { 164 case WeightedEdgeSlicer: 165 return it.WeightedEdgeSlice() 166 } 167 edges := make([]WeightedEdge, 0, n) 168 for it.Next() { 169 edges = append(edges, it.WeightedEdge()) 170 } 171 if len(edges) == 0 { 172 return nil 173 } 174 return edges 175 } 176 177 // Lines is a Line iterator. 178 type Lines interface { 179 Iterator 180 181 // Line returns the current Line from the iterator. 182 Line() Line 183 } 184 185 // LineSlicer wraps the LineSlice method. 186 type LineSlicer interface { 187 // LineSlice returns the set of lines remaining 188 // to be iterated by an Lines iterator. 189 // The holder of the iterator may arbitrarily 190 // change elements in the returned slice, but 191 // those changes may be reflected to other 192 // iterators. 193 LineSlice() []Line 194 } 195 196 // LinesOf returns it.Len() nodes from it. If it is a LineSlicer, the LineSlice method is used 197 // to obtain the lines. It is safe to pass a nil Lines to LinesOf. 198 func LinesOf(it Lines) []Line { 199 if it == nil { 200 return nil 201 } 202 n := it.Len() 203 switch { 204 case n == 0: 205 return nil 206 case n < 0: 207 n = 0 208 } 209 switch it := it.(type) { 210 case LineSlicer: 211 return it.LineSlice() 212 } 213 lines := make([]Line, 0, n) 214 for it.Next() { 215 lines = append(lines, it.Line()) 216 } 217 if len(lines) == 0 { 218 return nil 219 } 220 return lines 221 } 222 223 // WeightedLines is a WeightedLine iterator. 224 type WeightedLines interface { 225 Iterator 226 227 // Line returns the current Line from the iterator. 228 WeightedLine() WeightedLine 229 } 230 231 // WeightedLineSlicer wraps the WeightedLineSlice method. 232 type WeightedLineSlicer interface { 233 // LineSlice returns the set of lines remaining 234 // to be iterated by an Lines iterator. 235 // The holder of the iterator may arbitrarily 236 // change elements in the returned slice, but 237 // those changes may be reflected to other 238 // iterators. 239 WeightedLineSlice() []WeightedLine 240 } 241 242 // WeightedLinesOf returns it.Len() weighted line from it. If it is a WeightedLineSlicer, the 243 // WeightedLineSlice method is used to obtain the lines. It is safe to pass a nil WeightedLines 244 // to WeightedLinesOf. 245 func WeightedLinesOf(it WeightedLines) []WeightedLine { 246 if it == nil { 247 return nil 248 } 249 n := it.Len() 250 switch { 251 case n == 0: 252 return nil 253 case n < 0: 254 n = 0 255 } 256 switch it := it.(type) { 257 case WeightedLineSlicer: 258 return it.WeightedLineSlice() 259 } 260 lines := make([]WeightedLine, 0, n) 261 for it.Next() { 262 lines = append(lines, it.WeightedLine()) 263 } 264 if len(lines) == 0 { 265 return nil 266 } 267 return lines 268 } 269 270 // Empty is an empty set of nodes, edges or lines. It should be used when 271 // a graph returns a zero-length Iterator. Empty implements the slicer 272 // interfaces for nodes, edges and lines, returning nil for each of these. 273 const Empty = nothing 274 275 var ( 276 _ Iterator = Empty 277 _ Nodes = Empty 278 _ NodeSlicer = Empty 279 _ Edges = Empty 280 _ EdgeSlicer = Empty 281 _ WeightedEdges = Empty 282 _ WeightedEdgeSlicer = Empty 283 _ Lines = Empty 284 _ LineSlicer = Empty 285 _ WeightedLines = Empty 286 _ WeightedLineSlicer = Empty 287 ) 288 289 const nothing = empty(0) 290 291 type empty int 292 293 func (empty) Next() bool { return false } 294 func (empty) Len() int { return 0 } 295 func (empty) Reset() {} 296 func (empty) Node() Node { return nil } 297 func (empty) NodeSlice() []Node { return nil } 298 func (empty) Edge() Edge { return nil } 299 func (empty) EdgeSlice() []Edge { return nil } 300 func (empty) WeightedEdge() WeightedEdge { return nil } 301 func (empty) WeightedEdgeSlice() []WeightedEdge { return nil } 302 func (empty) Line() Line { return nil } 303 func (empty) LineSlice() []Line { return nil } 304 func (empty) WeightedLine() WeightedLine { return nil } 305 func (empty) WeightedLineSlice() []WeightedLine { return nil } 306 307 func (empty) String() string { return "<empty>" } 308 func (empty) GoString() string { return "graph.Empty" }