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;
}
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>() {
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;
}
}
if self.0.len() == other.0.len() {
return Ordering::Equal;
}
if self.0.len() > other.0.len() {
return Ordering::Greater;
}
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);
}
}