-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
85 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use template::EnumFrom; | ||
|
||
#[allow(unused)] | ||
#[derive(Debug, EnumFrom)] | ||
enum Direction { | ||
Up(DirectionUp), | ||
Down, | ||
Left(u32), | ||
Right(u32, u32), | ||
} | ||
|
||
#[allow(unused)] | ||
#[derive(Debug)] | ||
struct DirectionUp { | ||
speed: u32, | ||
} | ||
|
||
impl DirectionUp { | ||
fn new(speed: u32) -> Self { | ||
Self { speed } | ||
} | ||
} | ||
|
||
fn main() { | ||
let up: Direction = DirectionUp::new(42).into(); | ||
let left: Direction = 10.into(); | ||
println!("Up: {:?}, Left: {:?}", up, left); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,49 @@ | ||
// empty | ||
// proc macro crate | ||
|
||
use proc_macro::TokenStream; | ||
use quote::quote; | ||
|
||
// for enum, we'd like to generate From impls for each variant | ||
#[proc_macro_derive(EnumFrom)] | ||
pub fn derive_enum_from(input: TokenStream) -> TokenStream { | ||
let input = syn::parse_macro_input!(input as syn::DeriveInput); | ||
// println!("{:#?}", input); | ||
|
||
// get the ident | ||
let ident = input.ident; | ||
//get enum variants | ||
let variants = match input.data { | ||
syn::Data::Enum(data) => data.variants, | ||
_ => panic!("EnumFrom can only be applied to enums"), | ||
}; | ||
//for each variant, get the ident and fields | ||
let from_impls = variants.iter().map(|v| { | ||
let var = &v.ident; | ||
match &v.fields { | ||
syn::Fields::Unnamed(fields) => { | ||
// only support one field | ||
if fields.unnamed.len() != 1 { | ||
quote! {} | ||
} else { | ||
let field = fields.unnamed.first().expect("Should have 1 field"); | ||
let ty = &field.ty; | ||
quote! { | ||
impl From<#ty> for #ident { | ||
fn from(v: #ty) -> Self { | ||
#ident::#var(v) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
syn::Fields::Unit => quote! {}, | ||
syn::Fields::Named(_fields) => quote! {}, | ||
} | ||
}); | ||
|
||
// quote return proc-macro2 TokenStream so we need to convert it to TokenStream | ||
quote! { | ||
#(#from_impls)* | ||
} | ||
.into() | ||
} |