1use self::Direction::{Incoming, Outgoing};
4use crate::graph::{Directed, Graph, Undirected};
5use crate::node::NodeTrait;
6use crate::traverse::Neighbors;
7use indexmap::map::Iter as IndexMapIter;
8use indexmap::IndexMap;
9use std::marker::PhantomData;
10
11pub trait EdgeType {
13 fn is_directed() -> bool;
14}
15
16impl EdgeType for Directed {
17 #[inline]
18 fn is_directed() -> bool {
19 true
20 }
21}
22
23impl EdgeType for Undirected {
24 #[inline]
25 fn is_directed() -> bool {
26 false
27 }
28}
29
30pub struct Edges<'a, N, E: 'a, Ty>
31where
32 N: 'a + NodeTrait,
33 Ty: EdgeType,
34{
35 from: N,
36 edges: &'a IndexMap<(N, N), E>,
37 iter: Neighbors<'a, N, Ty>,
38}
39
40impl<'a, N, E, Ty> Edges<'a, N, E, Ty>
41where
42 N: 'a + NodeTrait,
43 Ty: EdgeType,
44{
45 pub fn new(from: N, edges: &'a IndexMap<(N, N), E>, iter: Neighbors<'a, N, Ty>) -> Self {
46 Self { from, edges, iter }
47 }
48}
49
50impl<'a, N, E, Ty> Iterator for Edges<'a, N, E, Ty>
51where
52 N: 'a + NodeTrait,
53 E: 'a,
54 Ty: EdgeType,
55{
56 type Item = (N, N, &'a E);
57 fn next(&mut self) -> Option<Self::Item> {
58 match self.iter.next() {
59 None => None,
60 Some(b) => {
61 let a = self.from;
62 match self.edges.get(&Graph::<N, E, Ty>::edge_key(a, b)) {
63 None => unreachable!(),
64 Some(edge) => Some((a, b, edge)),
65 }
66 }
67 }
68 }
69}
70
71pub struct AllEdges<'a, N, E: 'a, Ty> {
72 inner: IndexMapIter<'a, (N, N), E>,
73 ty: PhantomData<Ty>,
74}
75
76impl<'a, N, E, Ty> AllEdges<'a, N, E, Ty>
77where
78 N: 'a + NodeTrait,
79{
80 pub fn new(inner: IndexMapIter<'a, (N, N), E>, ty: PhantomData<Ty>) -> Self {
81 Self { inner, ty }
82 }
83}
84
85impl<'a, N, E, Ty> Iterator for AllEdges<'a, N, E, Ty>
86where
87 N: 'a + NodeTrait,
88 E: 'a,
89 Ty: EdgeType,
90{
91 type Item = (N, N, &'a E);
92
93 fn next(&mut self) -> Option<Self::Item> {
95 match self.inner.next() {
96 None => None,
97 Some((&(a, b), v)) => Some((a, b, v)),
98 }
99 }
100
101 fn size_hint(&self) -> (usize, Option<usize>) {
126 self.inner.size_hint()
127 }
128
129 fn count(self) -> usize {
131 self.inner.count()
132 }
133
134 fn nth(&mut self, n: usize) -> Option<Self::Item> {
147 self.inner
148 .nth(n)
149 .map(|(&(n1, n2), weight)| (n1, n2, weight))
150 }
151
152 fn last(self) -> Option<Self::Item> {
154 self.inner
155 .last()
156 .map(|(&(n1, n2), weight)| (n1, n2, weight))
157 }
158}
159
160impl<'a, N, E, Ty> DoubleEndedIterator for AllEdges<'a, N, E, Ty>
161where
162 N: 'a + NodeTrait,
163 E: 'a,
164 Ty: EdgeType,
165{
166 fn next_back(&mut self) -> Option<Self::Item> {
170 self.inner
171 .next_back()
172 .map(|(&(n1, n2), weight)| (n1, n2, weight))
173 }
174}
175
176pub trait IntoWeightedEdge<E> {
180 type NodeId;
181 fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
182}
183
184impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
186where
187 E: Default,
188{
189 type NodeId = Ix;
190
191 fn into_weighted_edge(self) -> (Ix, Ix, E) {
192 let (s, t) = self;
193 (s, t, E::default())
194 }
195}
196
197impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E) {
201 type NodeId = Ix;
202
203 fn into_weighted_edge(self) -> (Ix, Ix, E) {
204 self
205 }
206}
207
208impl<'a, Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &'a E)
212where
213 E: Clone,
214{
215 type NodeId = Ix;
216
217 fn into_weighted_edge(self) -> (Ix, Ix, E) {
218 let (a, b, c) = self;
219 (a, b, c.clone())
220 }
221}
222
223impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix)
227where
228 Ix: Copy,
229 E: Default,
230{
231 type NodeId = Ix;
232
233 fn into_weighted_edge(self) -> (Ix, Ix, E) {
234 let (s, t) = *self;
235 (s, t, E::default())
236 }
237}
238
239impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix, E)
244where
245 Ix: Copy,
246 E: Clone,
247{
248 type NodeId = Ix;
249 fn into_weighted_edge(self) -> (Ix, Ix, E) {
250 self.clone()
251 }
252}
253
254#[derive(Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
256#[repr(usize)]
257pub enum Direction {
258 Outgoing = 0,
260 Incoming = 1,
262}
263
264copyclone!(Direction);
265
266impl Direction {
267 #[inline]
269 pub fn opposite(self) -> Direction {
270 match self {
271 Outgoing => Incoming,
272 Incoming => Outgoing,
273 }
274 }
275
276 #[inline]
278 pub fn index(self) -> usize {
279 (self as usize) & 0x1
280 }
281}
282
283#[derive(Copy, Clone, Debug, PartialEq)]
285pub enum CompactDirection {
286 Outgoing,
287 Incoming,
288}
289
290impl From<Direction> for CompactDirection {
291 fn from(d: Direction) -> Self {
292 match d {
293 Outgoing => CompactDirection::Outgoing,
294 Incoming => CompactDirection::Incoming,
295 }
296 }
297}
298
299impl PartialEq<Direction> for CompactDirection {
300 fn eq(&self, rhs: &Direction) -> bool {
301 (*self as usize) == (*rhs as usize)
302 }
303}
304
305#[cfg(test)]
306mod tests {
307 use crate::edge::{AllEdges, CompactDirection, Direction, EdgeType, Edges, IntoWeightedEdge};
308 use crate::graph::{Directed, Undirected};
309 use crate::traverse::Neighbors;
310 use indexmap::IndexMap;
311 use std::cmp::PartialEq;
312 use std::marker::PhantomData;
313
314 #[test]
315 fn edge_type_is_directed() {
316 assert_eq!(Directed::is_directed(), true);
317 assert_eq!(Undirected::is_directed(), false);
318 }
319
320 #[test]
321 fn edges_new() {
322 let from: u32 = 1;
324 let edges: IndexMap<(u32, u32), f32> = IndexMap::new();
325 let node_neighbors: Vec<(u32, CompactDirection)> = vec![];
326 let iter = node_neighbors.iter();
327 let neighbors: Neighbors<u32, Directed> = Neighbors::new(iter, PhantomData);
328
329 Edges::new(from, &edges, neighbors);
331 }
332
333 #[test]
334 fn edges_next() {
335 let from: u32 = 1;
337 let mut edges: IndexMap<(u32, u32), f32> = IndexMap::with_capacity(3);
338 edges.insert((2, 1), 2.0);
339 edges.insert((1, 3), 3.0);
340 edges.insert((1, 4), 4.0);
341 let node_neighbors: Vec<(u32, CompactDirection)> = vec![
342 (2, CompactDirection::Incoming),
343 (3, CompactDirection::Outgoing),
344 (4, CompactDirection::Outgoing),
345 ];
346 let neighbors: Neighbors<u32, Directed> =
347 Neighbors::new(node_neighbors.iter(), PhantomData);
348
349 let mut edges = Edges::new(from, &edges, neighbors);
352
353 assert_eq!(edges.next(), Some((1, 3, &3.0)));
355 assert_eq!(edges.next(), Some((1, 4, &4.0)));
356
357 assert_eq!(edges.next(), None);
359 }
360
361 #[test]
362 #[should_panic]
363 fn edges_next_unreachable() {
364 let from: u32 = 1;
366 let edges: IndexMap<(u32, u32), f32> = IndexMap::new();
367 let node_neighbors: Vec<(u32, CompactDirection)> = vec![(2, CompactDirection::Incoming)];
368 let neighbors: Neighbors<u32, Directed> =
369 Neighbors::new(node_neighbors.iter(), PhantomData);
370
371 let mut edges = Edges::new(from, &edges, neighbors);
373
374 assert_eq!(edges.next(), Some((1, 2, &0.0)));
375 }
376
377 #[test]
378 fn all_edges_new() {
379 let _all_edges: AllEdges<u32, f32, Directed> =
380 AllEdges::new(IndexMap::new().iter(), PhantomData);
381 }
382
383 #[test]
384 fn all_edges_next() {
385 let mut edges: IndexMap<(u32, u32), f32> = IndexMap::with_capacity(3);
386 edges.insert((2, 1), 2.0);
387 edges.insert((1, 3), 3.0);
388 edges.insert((1, 4), 4.0);
389
390 let mut all_edges: AllEdges<u32, f32, Directed> = AllEdges::new(edges.iter(), PhantomData);
391
392 assert_eq!(all_edges.next(), Some((2, 1, &2.0)));
393 assert_eq!(all_edges.next(), Some((1, 3, &3.0)));
394 assert_eq!(all_edges.next(), Some((1, 4, &4.0)));
395 assert_eq!(all_edges.next(), None);
396 }
397
398 #[test]
399 fn all_edges_size_hint() {
400 let mut edges: IndexMap<(u32, u32), f32> = IndexMap::with_capacity(3);
401 edges.insert((2, 1), 2.0);
402 edges.insert((1, 3), 3.0);
403 edges.insert((1, 4), 4.0);
404 let mut all_edges: AllEdges<u32, f32, Directed> = AllEdges::new(edges.iter(), PhantomData);
405
406 assert_eq!(all_edges.size_hint(), (3, Some(3)));
407
408 all_edges.next();
410
411 assert_eq!(all_edges.size_hint(), (2, Some(2)));
412
413 all_edges.next();
415
416 assert_eq!(all_edges.size_hint(), (1, Some(1)));
417
418 all_edges.next();
420
421 assert_eq!(all_edges.size_hint(), (0, Some(0)));
422 }
423
424 #[test]
425 fn all_edges_count() {
426 let mut edges: IndexMap<(u32, u32), f32> = IndexMap::with_capacity(3);
427 edges.insert((2, 1), 2.0);
428 edges.insert((1, 3), 3.0);
429 edges.insert((1, 4), 4.0);
430 let all_edges: AllEdges<u32, f32, Directed> = AllEdges::new(edges.iter(), PhantomData);
431
432 assert_eq!(all_edges.count(), 3);
433 }
434
435 #[test]
436 fn all_edges_nth() {
437 let mut edges: IndexMap<(u32, u32), f32> = IndexMap::with_capacity(3);
438 edges.insert((2, 1), 2.0);
439 edges.insert((1, 3), 3.0);
440 edges.insert((1, 4), 4.0);
441 let mut all_edges: AllEdges<u32, f32, Directed> = AllEdges::new(edges.iter(), PhantomData);
442
443 assert_eq!(all_edges.nth(2), Some((1, 4, &4.0)));
444 assert_eq!(all_edges.nth(0), None);
445 }
446
447 #[test]
448 fn all_edges_last() {
449 let mut edges: IndexMap<(u32, u32), f32> = IndexMap::with_capacity(3);
450 edges.insert((2, 1), 2.0);
451 edges.insert((1, 3), 3.0);
452 edges.insert((1, 4), 4.0);
453 let all_edges: AllEdges<u32, f32, Directed> = AllEdges::new(edges.iter(), PhantomData);
454
455 assert_eq!(all_edges.last(), Some((1, 4, &4.0)));
456 }
457
458 #[test]
459 fn all_edges_next_back() {
460 let mut edges: IndexMap<(u32, u32), f32> = IndexMap::with_capacity(3);
461 edges.insert((2, 1), 2.0);
462 edges.insert((1, 3), 3.0);
463 edges.insert((1, 4), 4.0);
464
465 let mut all_edges: AllEdges<u32, f32, Directed> = AllEdges::new(edges.iter(), PhantomData);
466
467 assert_eq!(all_edges.next_back(), Some((1, 4, &4.0)));
469 assert_eq!(all_edges.next_back(), Some((1, 3, &3.0)));
470 assert_eq!(all_edges.next_back(), Some((2, 1, &2.0)));
471 assert_eq!(all_edges.next_back(), None);
472 }
473
474 #[test]
475 fn into_weighted_edge() {
476 assert_eq!((1, 2).into_weighted_edge(), (1, 2, f32::default()));
478
479 assert_eq!((1, 2, 3).into_weighted_edge(), (1, 2, 3));
481
482 assert_eq!((1, 2, &3).into_weighted_edge(), (1, 2, 3));
484
485 assert_eq!((&(1, 2)).into_weighted_edge(), (1, 2, f32::default()));
487
488 assert_eq!((&(1, 2, 3)).into_weighted_edge(), (1, 2, 3));
490 }
491
492 #[test]
493 fn direction_opposite() {
494 assert_eq!(Direction::Incoming.opposite(), Direction::Outgoing);
495 assert_eq!(Direction::Outgoing.opposite(), Direction::Incoming);
496 }
497
498 #[test]
499 fn direction_index() {
500 assert_eq!(Direction::Incoming.index(), Direction::Incoming as usize);
501 assert_eq!(Direction::Outgoing.index(), Direction::Outgoing as usize);
502 }
503
504 #[test]
505 fn direction_clone() {
506 assert_eq!(Direction::Incoming.clone(), Direction::Incoming);
507 assert_eq!(Direction::Outgoing.clone(), Direction::Outgoing);
508 }
509
510 #[test]
511 fn compact_direction_from() {
512 assert_eq!(
513 CompactDirection::from(Direction::Incoming),
514 CompactDirection::Incoming
515 );
516 assert_eq!(
517 CompactDirection::from(Direction::Outgoing),
518 CompactDirection::Outgoing
519 );
520 }
521
522 #[test]
523 fn compact_direction_partial_equal_with_direction() {
524 assert_eq!(CompactDirection::Incoming.eq(&Direction::Incoming), true);
525 assert_eq!(CompactDirection::Incoming.eq(&Direction::Outgoing), false);
526
527 assert_eq!(CompactDirection::Outgoing.eq(&Direction::Outgoing), true);
528 assert_eq!(CompactDirection::Outgoing.eq(&Direction::Incoming), false);
529 }
530}