diff --git a/src/compiler/rust/proc/from_variants.rs b/src/compiler/rust/proc/from_variants.rs new file mode 100644 index 00000000000..9c79986381d --- /dev/null +++ b/src/compiler/rust/proc/from_variants.rs @@ -0,0 +1,42 @@ +// Copyright © 2023 Collabora, Ltd. +// SPDX-License-Identifier: MIT + +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; +use syn::*; + +pub fn derive_from_variants(input: TokenStream) -> TokenStream { + let DeriveInput { ident, data, .. } = parse_macro_input!(input); + let enum_type = ident; + + let mut impls = TokenStream2::new(); + + if let Data::Enum(e) = data { + for v in e.variants { + let var_ident = v.ident; + let from_type = match v.fields { + Fields::Named(_) => { + panic!("FromVariants does not support named fields") + } + Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => unnamed, + Fields::Unit => continue, + }; + + assert!( + from_type.len() == 1, + "FromVariants does not support multiple unnamed fields" + ); + let from_type = &from_type.first().unwrap().ty; + + impls.extend(quote! { + impl From<#from_type> for #enum_type { + fn from (v: #from_type) -> #enum_type { + #enum_type::#var_ident(v) + } + } + }); + } + } + + impls.into() +} diff --git a/src/compiler/rust/proc/lib.rs b/src/compiler/rust/proc/lib.rs index 144658e1b0b..cb4f9940fd5 100644 --- a/src/compiler/rust/proc/lib.rs +++ b/src/compiler/rust/proc/lib.rs @@ -8,3 +8,4 @@ extern crate quote; extern crate syn; pub mod as_slice; +pub mod from_variants; diff --git a/src/nouveau/compiler/nak/ir_proc.rs b/src/nouveau/compiler/nak/ir_proc.rs index 34ca9253bc5..3fd9dccaa04 100644 --- a/src/nouveau/compiler/nak/ir_proc.rs +++ b/src/nouveau/compiler/nak/ir_proc.rs @@ -147,33 +147,5 @@ pub fn enum_derive_display_op(input: TokenStream) -> TokenStream { #[proc_macro_derive(FromVariants)] pub fn derive_from_variants(input: TokenStream) -> TokenStream { - let DeriveInput { ident, data, .. } = parse_macro_input!(input); - let enum_type = ident; - - let mut impls = TokenStream2::new(); - - if let Data::Enum(e) = data { - for v in e.variants { - let var_ident = v.ident; - let from_type = match v.fields { - Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => unnamed, - _ => panic!("Expected Op(OpFoo)"), - }; - - assert!(from_type.len() == 1, "Expected Op(OpFoo)"); - let from_type = &from_type.first().unwrap().ty; - - let quote = quote! { - impl From<#from_type> for #enum_type { - fn from (op: #from_type) -> #enum_type { - #enum_type::#var_ident(op) - } - } - }; - - impls.extend(quote); - } - } - - impls.into() + compiler_proc::from_variants::derive_from_variants(input) }