rustversion_msrv/
expr.rs

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}