aboutsummaryrefslogtreecommitdiff
path: root/src/utils.rs
blob: 30b04aa557b784ce62cb5ed27d807bff56d00ed7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use std::iter::FromIterator;

use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};

use crate::Result;

macro_rules! error {
    ($span:expr, $msg:expr) => {{
        crate::error::Error::new($span, $msg)
    }};
    ($span:expr, $($tt:tt)*) => {
        error!($span, format!($($tt)*))
    };
}

pub(crate) fn tt_span(tt: Option<&TokenTree>) -> Span {
    tt.map_or_else(Span::call_site, TokenTree::span)
}

pub(crate) fn parse_as_empty(mut tokens: impl Iterator<Item = TokenTree>) -> Result<()> {
    match tokens.next() {
        Some(tt) => Err(error!(tt.span(), "unexpected token `{}`", tt)),
        None => Ok(()),
    }
}

// (`#[cfg(<tokens>)]`, `#[cfg(not(<tokens>))]`)
pub(crate) fn cfg_attrs(tokens: TokenStream) -> (TokenStream, TokenStream) {
    let f = |tokens| {
        let tokens = TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("cfg", Span::call_site())),
            TokenTree::Group(Group::new(Delimiter::Parenthesis, tokens)),
        ]);
        TokenStream::from_iter(vec![
            TokenTree::Punct(Punct::new('#', Spacing::Alone)),
            TokenTree::Group(Group::new(Delimiter::Bracket, tokens)),
        ])
    };

    let cfg_not = TokenTree::Group(Group::new(Delimiter::Parenthesis, tokens.clone()));
    let cfg_not = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("not", Span::call_site())),
        cfg_not,
    ]);

    (f(tokens), f(cfg_not))
}