Skip to content

Commit

Permalink
PEP440 impl (not yet tested)
Browse files Browse the repository at this point in the history
  • Loading branch information
msarahan committed Oct 14, 2019
1 parent 6ed5dfe commit d3f3df0
Showing 1 changed file with 72 additions and 23 deletions.
95 changes: 72 additions & 23 deletions src/version_part.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,85 @@
//! `Version`.
use std::cmp::Ordering;
// use regex::Regex;
use regex::Regex;

#[derive(Debug, Copy, Clone)]
pub struct PEP440String {}
pub struct PEP440String<'a> {
pre: i16,
alpha: &'a str,
post: i16,
}

impl<'a> PEP440String<'a> {
fn new(input: &'a str) -> PEP440String {
lazy_static! {
static ref re: Regex = Regex::new("(\\d*)(post|dev|[a-zA-Z]+)(\\d*)").unwrap();
}

let caps = re.captures(input).unwrap();
let pre: i16 = caps.get(1).map_or(0, |m| m.as_str().parse().unwrap());
let alpha = caps.get(2).map_or("", |m| m.as_str());
let post: i16 = caps.get(3).map_or(0, |m| m.as_str().parse().unwrap());

PEP440String{pre, alpha, post }
}
}

fn compare_pep440_str<'a>(left: &'a str, right: &'a str) -> Option<Ordering> {
lazy_static! { static ref dev_re: Regex = Regex::new("dev").unwrap(); }
lazy_static! { static ref post_re: Regex = Regex::new("post").unwrap(); }

let is_dev = (dev_re.is_match(left), dev_re.is_match(right));
let is_post = (post_re.is_match(left), post_re.is_match(right));

let str_match = left.partial_cmp(right);
match str_match {
Some(Ordering::Equal) => Some(Ordering::Equal),
_ => match is_dev {
(false, true) => Some(Ordering::Greater),
(true, false) => Some(Ordering::Less),
_ => match is_post {
(true, true) => Some(Ordering::Equal),
(false, true) => Some(Ordering::Less),
(true, false) => Some(Ordering::Greater),
// this is the final fallback to lexicographic sorting, if neither
// dev nor post are in effect
(false, false) => left.partial_cmp(right),
_ => panic!(),
}
}
}
}

impl<'a> PartialOrd for PEP440String<'a> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match self.pre.partial_cmp(&other.pre) {
Some(Ordering::Greater) => Some(Ordering::Greater),
Some(Ordering::Less) => Some(Ordering::Less),
Some(Ordering::Equal) => match compare_pep440_str(self.alpha, &other.alpha) {
Some(Ordering::Equal) => self.post.partial_cmp(&other.post),
Some(Ordering::Greater) => Some(Ordering::Greater),
Some(Ordering::Less) => Some(Ordering::Less),
_ => panic!()
}
_ => panic!()
}
}
}

impl<'a> PartialEq for PEP440String<'a> {
fn eq(&self, other: &Self) -> bool {
self.partial_cmp(&other).unwrap() == Ordering::Equal
}
}


#[derive(Debug, Copy, Clone)]
pub enum VersionPart<'a> {
Epoch(i16),
Integer(i32),
LexicographicString(&'a str),
PEP440String(PEP440String),
PEP440String(&'a PEP440String<'a>),
Bool(bool),
}

Expand All @@ -39,7 +107,7 @@ impl<'a> PartialOrd for VersionPart<'a> {
&VersionPart::Epoch(a) => &0,
&VersionPart::Integer(a) => &1,
&VersionPart::LexicographicString(a) => &2,
&VersionPart::PEP440String(a) => &2,
&VersionPart::PEP440String(a) => &3,
&VersionPart::Bool(a) => &4,
_ => panic!()
}
Expand All @@ -54,25 +122,6 @@ impl<'a> PartialEq for VersionPart<'a> {
}
}


// impl<'a> PEP440StringComparator<'a> {
// fn pep440_order(&self, other: &'a str) -> Ordering {
// lazy_static! {
// static ref dev_re: Regex = Regex::new("(\\d*)(dev)(\\d*)").unwrap();
// }
// lazy_static! {
// static ref post_re: Regex = Regex::new("(\\d*)(post)(\\d*)").unwrap();
// }

// dev_re.is_match(self.value);
// Ordering::Equal
// }
// }

// Simplified comparison idea from
// https://internals.rust-lang.org/t/simplifying-custom-comparison-and-hashing/5108


//impl<'a> fmt::Display for VersionPart<'a> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// match self {
Expand Down

0 comments on commit d3f3df0

Please sign in to comment.