vercomp 0.5.0

A library for comparing versions.
Documentation
use std::cmp::Ordering;

#[derive(Eq, Debug)]
pub struct Number(Vec<u32>);

impl Number {
    #[deprecated(since = "0.5.0", note = "superseded by `from`")]
    pub fn new(input: &str) -> Self {
        Self::from(input)
    }
}

impl From<&str> for Number {
    fn from(input: &str) -> Self {
        let mut number = Self(Vec::new());
        let mut section: Vec<u32> = Vec::new();
        for c in input.chars() {
            if c.to_string().parse::<u32>().is_err() {
                if section.is_empty() {
                    continue;
                }
                // sectionに数字があり、数字以外が来たら区切る。
                let number_string: String = section.drain(..).map(|c| c.to_string()).collect();
                number.0.push(number_string.parse::<u32>().unwrap());
            }
            if let Ok(v) = c.to_string().parse::<u32>() {
                // 連続した数字をVecにする。
                section.push(v);
            }
        }
        if !section.is_empty() {
            let version_string: String = section.drain(..).map(|c| c.to_string()).collect();
            number.0.push(version_string.parse::<u32>().unwrap());
        }
        number
    }
}

impl Ord for Number {
    fn cmp(&self, other: &Self) -> Ordering {
        let depth = if self.0.len() >= other.0.len() {
            other.0.len()
        } else {
            self.0.len()
        };
        for i in 0..depth {
            if self.0[i] == other.0[i] {
                continue;
            }
            if self.0[i] > other.0[i] {
                return Ordering::Greater;
            }
            if self.0[i] < other.0[i] {
                return Ordering::Less;
            }
        }
        // 1.2.3 == 1.2.3
        if self.0.len() == other.0.len() {
            return Ordering::Equal;
        }
        // 1.2.3 > 1.2
        if self.0.len() > other.0.len() {
            return Ordering::Greater;
        }
        // 1.2 < 1.2.3
        if self.0.len() < other.0.len() {
            return Ordering::Less;
        }
        panic!("Failed to compare {:?} and {:?}", self.0, other.0);
    }
}

impl PartialOrd for Number {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for Number {
    fn eq(&self, other: &Self) -> bool {
        if self.cmp(other) == Ordering::Equal {
            return true;
        }
        false
    }
}

#[cfg(test)]
mod tests {
    use crate::number::Number;
    #[test]
    fn init_check() {
        let version = Number::from("1.2.3");
        assert_eq!(vec![1, 2, 3], version.0);
    }
    use std::cmp::Ordering;
    #[test]
    fn equal_check() {
        let version_1 = Number::from("1.2.3");
        let version_2 = Number::from("1.2.3");
        assert_eq!(version_1.cmp(&version_2), Ordering::Equal);
    }
    #[test]
    fn greeter_check() {
        let version_1 = Number::from("1.2.3");
        let version_2 = Number::from("1.2");
        assert_eq!(version_1.cmp(&version_2), Ordering::Greater);
    }
    #[test]
    fn less_check() {
        let version_1 = Number::from("1.2");
        let version_2 = Number::from("1.2.3");
        assert_eq!(version_1.cmp(&version_2), Ordering::Less);
    }
}