1use std::env;
2
3use proc_macro::{Span, TokenTree};
4
5use crate::{
6 error::{Error, Result},
7 iter::Iter,
8 version::{Channel, Version},
9};
10
11pub enum Expr {
12 Msrv,
13}
14
15impl Expr {
16 pub fn eval(&self, rustc: Version) -> bool {
17 use self::Expr::*;
18
19 match self {
20 Msrv => {
21 let cargo_rust_version = env::var("CARGO_PKG_RUST_VERSION")
22 .expect("manifest should specify a rust-version to use the msrv macro");
23 let mut cargo_rust_version = cargo_rust_version.splitn(3, '.');
24
25 let _maj = cargo_rust_version.next().unwrap();
26 let min = cargo_rust_version.next().unwrap().parse::<u16>().unwrap();
27 let patch = cargo_rust_version
28 .next()
29 .map_or(0, |val| val.parse().unwrap());
30
31 rustc.channel == Channel::Stable && rustc.minor == min && rustc.patch >= patch
32 }
33 }
34 }
35}
36
37pub fn parse(iter: Iter) -> Result<Expr> {
38 match &iter.next() {
39 Some(TokenTree::Ident(i)) if i.to_string() == "msrv" => Ok(Expr::Msrv),
40 unexpected => {
41 let span = unexpected
42 .as_ref()
43 .map_or_else(Span::call_site, TokenTree::span);
44 Err(Error::new(span, "expected `msrv`"))
45 }
46 }
47}