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