machine_check_macros/
lib.rs

1#![doc = include_str!("../README.md")]
2
3extern crate proc_macro;
4
5use machine_check_bitmask_switch::BitmaskSwitch;
6use proc_macro::TokenStream;
7use quote::ToTokens;
8use syn::{parse_macro_input, spanned::Spanned, Item};
9
10#[proc_macro_attribute]
11pub fn machine_description(_attr: TokenStream, item: TokenStream) -> TokenStream {
12    let item = parse_macro_input!(item as Item);
13    let Item::Mod(module) = item else {
14        return syn::Error::new(
15            item.span(),
16            String::from("machine_description macro must be used on a module"),
17        )
18        .to_compile_error()
19        .into();
20    };
21
22    match machine_check_machine::process_module(module) {
23        Ok(ok) => ok.into_token_stream().into(),
24        Err(err) => {
25            let (first_error, other_errors) = err.into_errors().split_off_first();
26            let mut current_error = first_error.into_syn_error();
27            for error in other_errors {
28                current_error.combine(error.into_syn_error());
29            }
30            current_error.to_compile_error().into()
31        }
32    }
33}
34
35#[proc_macro]
36pub fn bitmask_switch(stream: TokenStream) -> TokenStream {
37    let switch = parse_macro_input!(stream as BitmaskSwitch);
38    match machine_check_bitmask_switch::generate(switch) {
39        Ok(ok) => TokenStream::from(ok),
40        Err(error) => match error {
41            machine_check_bitmask_switch::Error::Parse(error) => error.into_compile_error().into(),
42            machine_check_bitmask_switch::Error::Process(msg, span) => {
43                syn::Error::new(span, msg).into_compile_error().into()
44            }
45        },
46    }
47}