1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parenthesized, parse, Attribute, Field, Generics, Ident, Token, Visibility};
struct ItemNewType {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub type_token: Token![type],
pub ident: Ident,
pub generics: Generics,
pub inner: Field,
pub semi: Option<Token![;]>,
}
impl parse::Parse for ItemNewType {
fn parse(input: parse::ParseStream) -> parse::Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let vis = input.parse()?;
let type_token = input.parse()?;
let ident = input.parse()?;
let generics = input.parse()?;
let inner = {
let content;
parenthesized!(content in input);
content.call(Field::parse_unnamed)?
};
let where_clause = input.parse()?;
let semi = input.parse()?;
Ok(ItemNewType {
attrs,
vis,
type_token,
ident,
generics: Generics {
where_clause,
..generics
},
inner,
semi,
})
}
}
#[proc_macro]
pub fn newtype(item: TokenStream) -> TokenStream {
let ItemNewType {
attrs: attributes,
vis,
ident: name,
inner,
generics,
..
} = syn::parse_macro_input!(item as ItemNewType);
let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
let def = quote! {
#(#attributes
)*
#[repr(transparent)]
#vis struct #name #generics (#inner) #where_clause;
unsafe impl #impl_generics trapper::Wrapper for #name #type_generics #where_clause {
type Inner = #inner;
fn wrap(inner: Self::Inner) -> Self { Self(inner) }
fn unwrap(self) -> Self::Inner { self.0 }
}
};
TokenStream::from(def)
}