1 use crate::date::{self, Date};
2 use crate::error::{Error, Result};
3 use crate::iter::Iter;
4 use crate::release::{self, Release};
5 use crate::time;
6 use crate::version::{Channel::*, Version};
7 use proc_macro::{Group, TokenTree};
8 use std::cmp::Ordering;
9
10 pub enum Bound {
11 Nightly(Date),
12 Stable(Release),
13 }
14
parse(paren: Group, iter: Iter) -> Result<Bound>15 pub fn parse(paren: Group, iter: Iter) -> Result<Bound> {
16 if let Some(TokenTree::Literal(literal)) = iter.peek() {
17 let repr = literal.to_string();
18 if repr.starts_with(|ch: char| ch.is_ascii_digit()) {
19 if repr.contains('.') {
20 return release::parse(paren, iter).map(Bound::Stable);
21 } else {
22 return date::parse(paren, iter).map(Bound::Nightly);
23 }
24 }
25 }
26 let msg = format!(
27 "expected rustc release number like 1.31, or nightly date like {}",
28 time::today(),
29 );
30 Err(Error::group(paren, msg))
31 }
32
33 impl PartialEq<Bound> for Version {
eq(&self, rhs: &Bound) -> bool34 fn eq(&self, rhs: &Bound) -> bool {
35 match rhs {
36 Bound::Nightly(date) => match self.channel {
37 Stable | Beta | Dev => false,
38 Nightly(nightly) => nightly == *date,
39 },
40 Bound::Stable(release) => {
41 self.minor == release.minor
42 && release.patch.map_or(true, |patch| self.patch == patch)
43 }
44 }
45 }
46 }
47
48 impl PartialOrd<Bound> for Version {
partial_cmp(&self, rhs: &Bound) -> Option<Ordering>49 fn partial_cmp(&self, rhs: &Bound) -> Option<Ordering> {
50 match rhs {
51 Bound::Nightly(date) => match self.channel {
52 Stable | Beta => Some(Ordering::Less),
53 Nightly(nightly) => Some(nightly.cmp(date)),
54 Dev => Some(Ordering::Greater),
55 },
56 Bound::Stable(release) => {
57 let version = (self.minor, self.patch);
58 let bound = (release.minor, release.patch.unwrap_or(0));
59 Some(version.cmp(&bound))
60 }
61 }
62 }
63 }
64