1extern crate proc_macro;
4
5use proc_macro::TokenStream;
6use proc_macro2::Span;
7use proc_macro_hack::proc_macro_hack;
8use quote::quote;
9use syn::{
10 parse::{Parse, ParseStream, Result},
11 parse_macro_input, Error, LitInt,
12};
13
14struct Power {
15 power: u32,
16 base_type: syn::Ident,
17}
18
19impl Parse for Power {
20 fn parse(input: ParseStream) -> Result<Self> {
21 let lit: LitInt = input.parse()?;
22 let power = lit.base10_parse::<u32>()?;
23
24 let mut base_type = syn::Ident::new("usize", Span::call_site());
25 if let Some(_comma) = input.parse::<Option<syn::Token![,]>>()? {
26 if let Some(type_) = input.parse::<Option<syn::Ident>>()? {
27 base_type = type_;
28 }
29 }
30
31 Ok(Power { power, base_type })
32 }
33}
34
35#[proc_macro_hack]
40pub fn power_of_two(input: TokenStream) -> TokenStream {
41 let Power { power, base_type } = parse_macro_input!(input);
43
44 let expanded = if base_type == "usize" {
45 let value = 2usize.pow(power);
46 quote!(#value)
47 } else if base_type == "u8" {
48 let value = 2u8.pow(power);
49 quote!(#value)
50 } else if base_type == "i8" {
51 let value = 2i8.pow(power);
52 quote!(#value)
53 } else if base_type == "u16" {
54 let value = 2u16.pow(power);
55 quote!(#value)
56 } else if base_type == "i16" {
57 let value = 2i16.pow(power);
58 quote!(#value)
59 } else if base_type == "u32" {
60 let value = 2u32.pow(power);
61 quote!(#value)
62 } else if base_type == "i32" {
63 let value = 2i32.pow(power);
64 quote!(#value)
65 } else if base_type == "u128" {
66 let value = 2u128.pow(power);
67 quote!(#value)
68 } else if base_type == "i128" {
69 let value = 2i128.pow(power);
70 quote!(#value)
71 } else if base_type == "usize" {
72 let value = 2usize.pow(power);
73 quote!(#value)
74 } else if base_type == "isize" {
75 let value = 2isize.pow(power);
76 quote!(#value)
77 } else {
78 Error::new_spanned(base_type, "Unknown integer type").to_compile_error()
79 };
80
81 TokenStream::from(expanded)
83}