1
use std::slice::SliceIndex;
2

            
3
/// An enum used to indicate an edge or a self loop.
4
pub enum Edge<T> {
5
    Regular(T, T),
6

            
7
    /// For a self loop we only provide a mutable reference to the single state.
8
    Selfloop(T),
9
}
10

            
11
/// Index two locations (from, to) of an edge, returns mutable references to it.
12
pub fn index_edge<T, I: PartialEq + PartialOrd<usize> + SliceIndex<[T], Output = T>>(
13
    slice: &mut [T],
14
    a: I,
15
    b: I,
16
) -> Edge<&mut T> {
17
    if a == b {
18
        assert!(a <= slice.len());
19
        Edge::Selfloop(slice.get_mut(a).unwrap())
20
    } else {
21
        assert!(a <= slice.len() && b < slice.len());
22

            
23
        // safe because a, b are in bounds and distinct
24
        unsafe {
25
            let ar = &mut *(slice.get_unchecked_mut(a) as *mut _);
26
            let br = &mut *(slice.get_unchecked_mut(b) as *mut _);
27
            Edge::Regular(ar, br)
28
        }
29
    }
30
}