cxx_build/syntax/
repr.rs

1use crate::syntax::Atom::{self, *};
2use proc_macro2::{Ident, Span};
3use syn::parse::{Error, Parse, ParseStream, Result};
4use syn::{parenthesized, Expr, LitInt};
5
6pub(crate) enum Repr {
7    Align(LitInt),
8    Atom(Atom, Span),
9}
10
11impl Parse for Repr {
12    fn parse(input: ParseStream) -> Result<Self> {
13        let begin = input.cursor();
14        let ident: Ident = input.parse()?;
15        if let Some(atom) = Atom::from(&ident) {
16            match atom {
17                U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize if input.is_empty() => {
18                    return Ok(Repr::Atom(atom, ident.span()));
19                }
20                _ => {}
21            }
22        } else if ident == "align" {
23            let content;
24            match ::syn::__private::parse_parens(&input) {
    ::syn::__private::Ok(parens) => { content = parens.content; parens.token }
    ::syn::__private::Err(error) => { return ::syn::__private::Err(error); }
};parenthesized!(content in input);
25            let align_expr: Expr = content.fork().parse()?;
26            if !#[allow(non_exhaustive_omitted_patterns)] match align_expr {
    Expr::Lit(_) => true,
    _ => false,
}matches!(align_expr, Expr::Lit(_)) {
27                return Err(Error::new_spanned(
28                    align_expr,
29                    "invalid repr(align) attribute: an arithmetic expression is not supported",
30                ));
31            }
32            let align_lit: LitInt = content.parse()?;
33            let align: u32 = align_lit.base10_parse()?;
34            if !align.is_power_of_two() {
35                return Err(Error::new_spanned(
36                    align_lit,
37                    "invalid repr(align) attribute: not a power of two",
38                ));
39            }
40            if align > 2u32.pow(13) {
41                return Err(Error::new_spanned(
42                    align_lit,
43                    "invalid repr(align) attribute: larger than 2^13",
44                ));
45            }
46            return Ok(Repr::Align(align_lit));
47        }
48        Err(Error::new_spanned(
49            begin.token_stream(),
50            "unrecognized repr",
51        ))
52    }
53}