digraph-rs 0.1.0

a handful of algorithms for digraphs
Documentation
use std::cmp::Ordering;
use std::ops::Add;
use Score::{Inf, Value, Zero};

#[derive(Debug, Clone)]
pub enum Score<ScoreValue> {
    Inf,
    Zero,
    Value(ScoreValue),
}

impl<ScoreValue> Add for Score<ScoreValue>
where
    ScoreValue: Add<Output = ScoreValue> + Clone,
{
    type Output = Score<ScoreValue>;

    fn add(self, rhs: Self) -> Self::Output {
        match (self,rhs) {
            (Inf,_) | (_,Inf) => Inf,
            (Zero,res)|(res,Zero) => res,
            (Value(lhs),Value(rhs)) => Value(lhs + rhs),
        }
    }

}

impl<ScoreValue:ToString> ToString for Score<ScoreValue> {
    fn to_string(&self) -> String {
        match self{
            Inf => "inf".to_string(),
            Zero => "zero".to_string(),
            Value(v) => v.to_string(),
        }
    }
}





impl<ScoreValue> Score<ScoreValue>
where
    ScoreValue: Add<Output = ScoreValue> + Clone,
{
    pub fn add_score_v(&self, score: ScoreValue) -> Score<ScoreValue> {
        match &self {
            Inf => Inf,
            Zero => Value(score),
            Value(left) => Value(left.clone() + score),
        }
    }
}

impl<'a, ScoreValue: Eq> Eq for Score<ScoreValue> {}
impl<'a, ScoreValue: Eq> PartialEq for Score<ScoreValue> {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Inf, Inf) | (Zero, Zero) => true,
            (Value(lhs), Value(rhs)) => lhs.eq(rhs),
            _ => false,
        }
    }
}
impl<ScoreValue: Ord> PartialOrd for Score<ScoreValue> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self == other {
            Some(Ordering::Equal)
        } else {
            match (self, other) {
                (Inf, _) => Some(Ordering::Greater),
                (Value(_), Inf) => Some(Ordering::Less),
                (Zero, _) => Some(Ordering::Less),
                (Value(lhs), Value(rhs)) => Some(lhs.cmp(rhs)),
                _ => None,
            }
        }
    }
}

#[derive(Debug, Clone)]
pub struct MinWeight<'a, Id, ScoreValue>(pub &'a Id, pub Score<ScoreValue>);

impl<'a, Id, ScoreValue: Ord> Eq for MinWeight<'a, Id, ScoreValue> {}
impl<'a, Id, ScoreValue: Ord> PartialEq<Self> for MinWeight<'a, Id, ScoreValue> {
    fn eq(&self, other: &Self) -> bool {
        match (&self.1, &other.1) {
            (Inf, Inf) | (Zero, Zero) => true,
            (Value(l), Value(r)) => l.cmp(r) == Ordering::Equal,
            _ => false,
        }
    }
}

impl<'a, Id, ScoreValue: Ord> PartialOrd<Self> for MinWeight<'a, Id, ScoreValue> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a, Id, ScoreValue: Ord> Ord for MinWeight<'a, Id, ScoreValue> {
    fn cmp(&self, other: &Self) -> Ordering {
        if self.eq(other) {
            Ordering::Equal
        } else {
            match (&self.1, &other.1) {
                (Inf, _) | (_, Zero) => Ordering::Less,
                (Zero, _) | (_, Inf) => Ordering::Greater,
                (Value(lhs), Value(rhs)) => {
                    if lhs < rhs {
                        Ordering::Greater
                    } else if lhs > rhs {
                        Ordering::Less
                    } else if lhs.ne(lhs) && rhs.ne(rhs) {
                        Ordering::Equal
                    } else if lhs.ne(lhs) {
                        Ordering::Less
                    } else {
                        Ordering::Greater
                    }
                }
            }
        }
    }
}