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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//!This module provides the implementation of the Edge type, the Vertex type and
//! the edges' key type, to use with the AdjacencyGraph type
//!
//!The implementation of the Vertex type consist of a simple rename of the SimpleVertex type,
//! as said type is suitable for this implementation

use crate::Edge;
pub use crate::SimpleVertex as DirectedVertex;
use std::hash::Hash;
use std::ops::{Add, Sub};

///The CompoundKey type is the type designated as edge key. It consist of two generic keys of the
/// same type, representing the key of two adjacent Vertexes.
///
///For two CompoundKey to be equal, the corresponding vertex key of the two must be equal as well.
/// If two CompoundKey contain the same vertex key, but in different order they are not considered equal
///
///This type can be constructed only via the `generate_key()` function associated to the type DirectedEdge
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub struct CompoundKey<K: Hash + Eq + Clone> {
    left: K,
    right: K,
}

///The DirectedEdge type is the implementation an implementation od the Edge trait that uses
/// CompoundKey as type, as such it also indicates the direction of the edge which lead from the
/// left vertex to the right one.
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct DirectedEdge<K, W>
    where K: Hash + Eq + Clone,
          W: Add + Sub + Eq + Ord + Copy,
{
    left: K,
    right: K,
    weight: W,
}

impl<K: Hash + Eq + Clone, W: Add + Sub + Eq + Ord + Copy> DirectedEdge<K, W> {

    ///Returns an instance of Directed edge with the specified weight and pair of vertex keys
    pub fn new(left: K, right: K, weight: W) -> DirectedEdge<K, W> {
        DirectedEdge {
            left,
            right,
            weight,
        }
    }
}

///`DirectedEdge` implement the Edge trait Specifying the edge key type (CompoundKey). But the vertex key type
/// and the edge weight type remain generics.
impl<K: Hash + Eq + Clone, W: Add + Sub + Eq + Ord + Copy> Edge<K, W, CompoundKey<K>> for DirectedEdge<K, W> {

    ///Returns a copy of the weight (the weight type is required to implement Copy)
    fn get_weight(&self) -> W {
        self.weight
    }

    ///change the value of weight
    fn set_weight(&mut self, weight: W) {
        self.weight = weight;
    }

    ///Returns a reference to the key of the left hand vertex
    fn left(&self) -> &K {
        &self.left
    }

    ///Returns a reference to the key of the right hand vertex
    fn right(&self) -> &K {
        &self.right
    }

    ///Returns a pair of reference to the vertex keys. Ordered from left to right
    fn get_pair(&self) -> (&K, &K) {
        (&self.left, &self.right)
    }

    ///Returns a new instance of CompoundKey from a pair of reference to vertex keys
    ///
    /// # Example
    /// ```rust
    /// use generic_graph::adjacency_list::elements::DirectedEdge;
    /// use generic_graph::Edge;
    ///
    /// let edge = DirectedEdge::new(1, 2, 3);
    /// let key = DirectedEdge::<i32, i32>::generate_key(edge.get_pair());
    ///
    /// assert_eq!(key, edge.key());
    /// ```
    fn generate_key(pair: (&K, &K)) -> CompoundKey<K> {
        CompoundKey {
            left: pair.0.clone(),
            right: pair.1.clone()
        }
    }

    ///Returns an new instance of CompoundKey generated from the pair of keys stored isn the edge
    ///
    /// # Example
    /// ```rust
    /// use generic_graph::adjacency_list::elements::DirectedEdge;
    /// use generic_graph::Edge;
    ///
    /// let edge = DirectedEdge::new(1, 2, 3);
    /// let key = DirectedEdge::<i32, i32>::generate_key(edge.get_pair());
    ///
    /// assert_eq!(key, edge.key());
    /// ```
    fn key(&self) -> CompoundKey<K> {
        CompoundKey {
            left: self.left.clone(),
            right: self.right.clone()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn edge_construction() {
        let edge = DirectedEdge::new(1, 2, 3);

        assert_eq!(edge,
        DirectedEdge{ left: 1, right: 2, weight: 3});
    }

    #[test]
    fn edge_getters_setters() {
        let mut edge = DirectedEdge::new(1, 2, 3);
        assert_eq!((&1, &2, 3),
                   (edge.left(), edge.right(), edge.get_weight()));
        assert_eq!((&1, &2), edge.get_pair());

        edge.set_weight(4);
        assert_eq!(4, edge.get_weight());
    }

    #[test]
    fn key_generation() {
        let edge = DirectedEdge::new(1, 2, 3);
        let key = CompoundKey{left: 1, right: 2};

        assert_eq!(key, edge.key());
        assert_eq!(key, DirectedEdge::<i32, i32>::generate_key((&1, &2)));
    }

    #[test]
    fn key_equality() {
        let key1 = CompoundKey{left: 1, right: 2};
        let key2 = CompoundKey{left: 1, right: 2};
        let key3 = CompoundKey{left: 2, right: 1};

        assert_eq!(key1, key2);
        assert_ne!(key1, key3);
    }
}