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
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, parse_quote};
#[proc_macro_attribute]
pub fn sealed(_args: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as syn::Item);
TokenStream::from(match parse_sealed(input) {
Ok(ts) => {
ts
},
Err(err) => err.to_compile_error(),
})
}
fn parse_sealed(item: syn::Item) -> syn::Result<proc_macro2::TokenStream> {
match item {
syn::Item::Struct(item_struct) => parse_sealed_struct(item_struct),
syn::Item::Trait(item_trait) => parse_sealed_trait(item_trait),
_ => Err(syn::Error::new(
proc_macro2::Span::call_site(),
"expected struct or trait",
)),
}
}
fn parse_sealed_struct(strct: syn::ItemStruct) -> syn::Result<proc_macro2::TokenStream> {
let ident = &strct.ident;
Ok(quote!(
#strct
impl private::Sealed for #ident {}
))
}
fn parse_sealed_trait(mut trt: syn::ItemTrait) -> syn::Result<proc_macro2::TokenStream> {
trt.supertraits.push(parse_quote!(private::Sealed));
Ok(quote!(
#trt
mod private {
pub trait Sealed {}
}
))
}