aboutsummaryrefslogtreecommitdiff
path: root/mingling_macros/src/func/pack.rs
diff options
context:
space:
mode:
Diffstat (limited to 'mingling_macros/src/func/pack.rs')
-rw-r--r--mingling_macros/src/func/pack.rs149
1 files changed, 149 insertions, 0 deletions
diff --git a/mingling_macros/src/func/pack.rs b/mingling_macros/src/func/pack.rs
new file mode 100644
index 0000000..a1a7e6b
--- /dev/null
+++ b/mingling_macros/src/func/pack.rs
@@ -0,0 +1,149 @@
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::parse::{Parse, ParseStream};
+use syn::{Attribute, Ident, Result as SynResult, Token, Type};
+
+struct PackInput {
+ attrs: Vec<Attribute>,
+ type_name: Ident,
+ inner_type: Type,
+}
+
+impl Parse for PackInput {
+ fn parse(input: ParseStream) -> SynResult<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let type_name: Ident = input.parse()?;
+ input.parse::<Token![=]>()?;
+ let inner_type: Type = input.parse()?;
+
+ Ok(PackInput {
+ attrs,
+ type_name,
+ inner_type,
+ })
+ }
+}
+
+#[allow(clippy::too_many_lines)]
+pub(crate) fn pack(input: TokenStream) -> TokenStream {
+ let pack_input = syn::parse_macro_input!(input as PackInput);
+
+ let group_name = crate::default_program_path();
+ let type_name = pack_input.type_name;
+ let inner_type = pack_input.inner_type;
+ let attrs = pack_input.attrs;
+
+ // Generate the struct definition
+ // Note: No longer derives Serialize under structural_renderer.
+ // Use pack_structual! for structured output support.
+ let struct_def = quote! {
+ #(#attrs)*
+ pub struct #type_name {
+ pub(crate) inner: #inner_type,
+ }
+ };
+
+ // Generate the new() method
+ let new_impl = quote! {
+ impl #type_name {
+ /// Creates a new instance of the wrapper type
+ pub fn new(inner: #inner_type) -> Self {
+ Self { inner }
+ }
+ }
+ };
+
+ // Generate From and Into implementations
+ let from_into_impl = quote! {
+ impl From<#inner_type> for #type_name {
+ fn from(inner: #inner_type) -> Self {
+ Self::new(inner)
+ }
+ }
+
+ impl From<#type_name> for #inner_type {
+ fn from(wrapper: #type_name) -> #inner_type {
+ wrapper.inner
+ }
+ }
+ };
+
+ // Generate AsRef and AsMut implementations
+ let as_ref_impl = quote! {
+ impl ::std::convert::AsRef<#inner_type> for #type_name {
+ fn as_ref(&self) -> &#inner_type {
+ &self.inner
+ }
+ }
+
+ impl ::std::convert::AsMut<#inner_type> for #type_name {
+ fn as_mut(&mut self) -> &mut #inner_type {
+ &mut self.inner
+ }
+ }
+ };
+
+ // Generate Deref and DerefMut implementations
+ let deref_impl = quote! {
+ impl ::std::ops::Deref for #type_name {
+ type Target = #inner_type;
+
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+ }
+
+ impl ::std::ops::DerefMut for #type_name {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.inner
+ }
+ }
+ };
+
+ // Check if the inner type implements Default by generating conditional code
+ let default_impl = quote! {
+ impl ::std::default::Default for #type_name
+ where
+ #inner_type: ::std::default::Default,
+ {
+ fn default() -> Self {
+ Self::new(::std::default::Default::default())
+ }
+ }
+ };
+
+ let register_impl = quote! {
+ ::mingling::macros::register_type!(#type_name);
+ };
+
+ let expanded = quote! {
+ #struct_def
+
+ #new_impl
+ #from_into_impl
+ #as_ref_impl
+ #deref_impl
+ #default_impl
+ #register_impl
+
+ impl Into<mingling::AnyOutput<#group_name>> for #type_name {
+ fn into(self) -> mingling::AnyOutput<#group_name> {
+ mingling::AnyOutput::new(self)
+ }
+ }
+
+ impl Into<mingling::ChainProcess<#group_name>> for #type_name {
+ fn into(self) -> mingling::ChainProcess<#group_name> {
+ mingling::AnyOutput::new(self).route_chain()
+ }
+ }
+
+ impl ::mingling::Grouped<#group_name> for #type_name {
+ fn member_id() -> #group_name {
+ #group_name::#type_name
+ }
+ }
+ };
+
+ expanded.into()
+}