synapse-macros 0.0.1

Procedural macros for Synapse RPC (derive RpcError, arc_wrap)
Documentation
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Ident};

pub fn arc_wrap_inner(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let input = parse_macro_input!(item as DeriveInput);
    let struct_name = &input.ident;
    let inner_name = Ident::new(&format!("{}Inner", struct_name), struct_name.span());

    let vis = &input.vis;
    let generics = &input.generics;
    let where_clause = &generics.where_clause;

    // Extract the struct fields from the input
    let fields = if let syn::Data::Struct(syn::DataStruct { fields, .. }) = &input.data {
        fields
    } else {
        panic!("arc_wrap can only be used on structs");
    };

    let expanded = quote! {
        // The inner struct with the original fields
        #vis struct #inner_name #generics #where_clause #fields

        // The wrapper struct
        #vis struct #struct_name #generics (std::sync::Arc<#inner_name #generics>) #where_clause;

        impl #generics Clone for #struct_name #generics #where_clause {
            fn clone(&self) -> Self {
                Self(self.0.clone())
            }
        }

        impl #generics std::ops::Deref for #struct_name #generics #where_clause {
            type Target = #inner_name #generics;

            fn deref(&self) -> &Self::Target {
                &self.0
            }
        }

        impl #generics #struct_name #generics #where_clause {
            /// Create a new instance by wrapping the inner struct in an Arc
            #vis fn new(inner: #inner_name #generics) -> Self {
                Self(std::sync::Arc::new(inner))
            }

            /// Get a reference to the inner Arc
            #vis fn inner(&self) -> &std::sync::Arc<#inner_name #generics> {
                &self.0
            }
        }
    };

    TokenStream::from(expanded)
}