Skip to main content

bidirected_adjacency_array/
index.rs

1use std::{
2    fmt::{Debug, Display},
3    hash::Hash,
4};
5
6use num_traits::{Bounded, PrimInt};
7use optional_numeric_index::implement_generic_index;
8
9pub trait GraphIndexInteger:
10    PrimInt + Bounded + Hash + Debug + Display + From<u8> + TryFrom<usize> + TryInto<usize>
11{
12}
13
14impl<T: PrimInt + Bounded + Hash + Debug + Display + From<u8> + TryFrom<usize> + TryInto<usize>>
15    GraphIndexInteger for T
16{
17}
18
19implement_generic_index!(pub NodeIndex, pub OptionalNodeIndex);
20implement_generic_index!(pub EdgeIndex, pub OptionalEdgeIndex);
21
22implement_generic_index!(pub DirectedNodeIndex, pub OptionalDirectedNodeIndex);
23implement_generic_index!(pub DirectedEdgeIndex, pub OptionalDirectedEdgeIndex);
24
25impl<IndexType: GraphIndexInteger> NodeIndex<IndexType> {
26    pub fn into_directed(self, forward: bool) -> DirectedNodeIndex<IndexType> {
27        DirectedNodeIndex::from_bidirected(self, forward)
28    }
29
30    pub fn into_directed_forward(self) -> DirectedNodeIndex<IndexType> {
31        self.into_directed(true)
32    }
33
34    pub fn into_directed_reverse(self) -> DirectedNodeIndex<IndexType> {
35        self.into_directed(false)
36    }
37}
38
39impl<IndexType: GraphIndexInteger> EdgeIndex<IndexType> {
40    pub(crate) fn increment(&mut self) {
41        *self = Self::new(self.0 + 1u8.into());
42    }
43
44    pub(crate) fn sub(self, other: EdgeIndex<IndexType>) -> Self {
45        Self::new(self.0 - other.0)
46    }
47}
48
49impl<IndexType: GraphIndexInteger> DirectedNodeIndex<IndexType> {
50    pub fn from_bidirected(bidirected: NodeIndex<IndexType>, forward: bool) -> Self {
51        let base = bidirected.0 * 2u8.into();
52        if forward {
53            DirectedNodeIndex(base)
54        } else {
55            DirectedNodeIndex(base + 1u8.into())
56        }
57    }
58
59    pub fn into_bidirected(self) -> NodeIndex<IndexType> {
60        NodeIndex(self.0 / 2u8.into())
61    }
62
63    pub fn invert(self) -> Self {
64        DirectedNodeIndex(self.0 ^ 1u8.into())
65    }
66
67    pub fn is_forward(self) -> bool {
68        (self.0 & 1u8.into()) == 0u8.into()
69    }
70
71    pub fn is_reverse(self) -> bool {
72        !self.is_forward()
73    }
74
75    pub(crate) fn add(self, other: DirectedNodeIndex<IndexType>) -> DirectedNodeIndex<IndexType> {
76        Self::new(self.0 + other.0)
77    }
78
79    /// Changes the bidirected node index without affecting the direction.
80    pub fn with_bidirected_node_index(self, bidirected: NodeIndex<IndexType>) -> Self {
81        Self::from_bidirected(bidirected, self.is_forward())
82    }
83}
84
85impl<IndexType: GraphIndexInteger> DirectedEdgeIndex<IndexType> {
86    pub(crate) fn zero() -> Self {
87        Self::new(0u8.into())
88    }
89
90    pub(crate) fn increment(&mut self) {
91        *self = Self::new(self.0 + 1u8.into());
92    }
93
94    pub(crate) fn decrement(&mut self) {
95        *self = Self::new(self.0 - 1u8.into());
96    }
97
98    pub(crate) fn add(self, other: DirectedEdgeIndex<IndexType>) -> DirectedEdgeIndex<IndexType> {
99        Self::new(self.0 + other.0)
100    }
101
102    pub(crate) fn sub(self, other: DirectedEdgeIndex<IndexType>) -> DirectedEdgeIndex<IndexType> {
103        Self::new(self.0 - other.0)
104    }
105}