1extern crate proc_macro;
5
6use proc_macro::TokenStream;
7
8use syn::{
9 Data,
10 Fields,
11};
12
13use quote::quote;
14
15#[proc_macro_derive(NewType)]
20pub fn newtype(input: TokenStream) -> TokenStream {
21 let input = syn::parse::<syn::DeriveInput>(input).expect("syn parse derive input");
22
23 gen_impl(input).into()
24}
25
26fn gen_impl(input: syn::DeriveInput) -> proc_macro2::TokenStream {
27 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
28 let name = input.ident;
29
30 let st = match input.data {
31 Data::Struct(st) => st,
32 _ => panic!("NewType can only be derived for single-field tuple structs"),
33 };
34
35 let fields = match st.fields {
36 Fields::Unnamed(fields) => fields,
37 _ => panic!("NewType can only be derived for single-field tuple structs"),
38 };
39
40 if fields.unnamed.len() != 1 {
41 panic!("NewType can only be derived for single-field tuple structs")
42 }
43
44 let field_ty = fields.unnamed.into_iter().nth(0).unwrap().ty;
45
46 let from = quote! {
47 impl #impl_generics From<#field_ty> for #name #ty_generics #where_clause {
48 fn from(other: #field_ty) -> #name #ty_generics {
49 #name (other)
50 }
51 }
52 };
53
54 let deref = quote! {
55 impl #impl_generics ::core::ops::Deref for #name #ty_generics #where_clause {
56 type Target = #field_ty;
57
58 fn deref(&self) -> &Self::Target {
59 &self.0
60 }
61 }
62 };
63
64 let deref_mut = quote! {
65 impl #impl_generics ::core::ops::DerefMut for #name #ty_generics #where_clause {
66 fn deref_mut(&mut self) -> &mut Self::Target {
67 &mut self.0
68 }
69 }
70 };
71
72 let into_inner = quote! {
73 impl #impl_generics #name #ty_generics #where_clause {
74 pub fn into_inner(self) -> #field_ty {
76 self.0
77 }
78 }
79 };
80
81 quote! {
82 #from #deref #deref_mut #into_inner
83 }
84}