masterror_derive/
lib.rs

1// SPDX-FileCopyrightText: 2025 RAprogramm <andrey.rozanov.vl@gmail.com>
2//
3// SPDX-License-Identifier: MIT
4
5//! Derive macro for `masterror::Error`.
6//!
7//! This crate is not intended to be used directly. Re-exported as
8//! `masterror::Error`.
9
10mod app_error_impl;
11mod display;
12mod error_trait;
13mod from_impl;
14mod input;
15mod masterror_impl;
16mod span;
17mod template_support;
18
19use proc_macro::TokenStream;
20use quote::quote;
21use syn::{DeriveInput, Error, parse_macro_input};
22
23#[proc_macro_derive(Error, attributes(error, source, from, backtrace, app_error, provide))]
24pub fn derive_error(tokens: TokenStream) -> TokenStream {
25    let input = parse_macro_input!(tokens as DeriveInput);
26    match expand(input) {
27        Ok(stream) => stream.into(),
28        Err(err) => err.to_compile_error().into()
29    }
30}
31
32#[proc_macro_derive(
33    Masterror,
34    attributes(error, source, from, backtrace, masterror, provide)
35)]
36pub fn derive_masterror(tokens: TokenStream) -> TokenStream {
37    let input = parse_macro_input!(tokens as DeriveInput);
38    match expand_masterror(input) {
39        Ok(stream) => stream.into(),
40        Err(err) => err.to_compile_error().into()
41    }
42}
43
44fn expand(input: DeriveInput) -> Result<proc_macro2::TokenStream, Error> {
45    let parsed = input::parse_input(input)?;
46    let display_impl = display::expand(&parsed)?;
47    let error_impl = error_trait::expand(&parsed)?;
48    let from_impls = from_impl::expand(&parsed)?;
49    let app_error_impls = app_error_impl::expand(&parsed)?;
50
51    Ok(quote! {
52        #display_impl
53        #error_impl
54        #(#from_impls)*
55        #(#app_error_impls)*
56    })
57}
58
59fn expand_masterror(input: DeriveInput) -> Result<proc_macro2::TokenStream, Error> {
60    let parsed = input::parse_input(input)?;
61    let display_impl = display::expand(&parsed)?;
62    let error_impl = error_trait::expand(&parsed)?;
63    let from_impls = from_impl::expand(&parsed)?;
64    let masterror_impl = masterror_impl::expand(&parsed)?;
65
66    Ok(quote! {
67        #display_impl
68        #error_impl
69        #(#from_impls)*
70        #masterror_impl
71    })
72}