1use proc_macro2::{Span, TokenStream};
2use quote::ToTokens;
3use syn::parse::{Error, Parse, ParseStream, Result};
4use syn::token::Brace;
5use syn::{Attribute, Generics, ImplItem, ItemImpl, Path, Token, Type};
6
7#[derive(Clone)]
8pub struct TraitImpl {
9 pub attrs: Vec<Attribute>,
10 pub defaultness: Option<Token![default]>,
11 pub unsafety: Option<Token![unsafe]>,
12 pub impl_token: Token![impl],
13 pub generics: Generics,
14 pub trait_: Path,
15 pub for_token: Token![for],
16 pub self_ty: Type,
17 pub brace_token: Brace,
18 pub items: Vec<ImplItem>,
19}
20
21impl Parse for TraitImpl {
22 fn parse(input: ParseStream) -> Result<Self> {
23 let imp: ItemImpl = input.parse()?;
24
25 let (trait_, for_token) = match imp.trait_ {
26 Some((_bang_token, trait_, for_token)) => (trait_, for_token),
27 None => {
28 return Err(Error::new(
29 Span::call_site(),
30 "must be placed on a trait impl",
31 ))
32 }
33 };
34
35 Ok(TraitImpl {
36 attrs: imp.attrs,
37 defaultness: imp.defaultness,
38 unsafety: imp.unsafety,
39 impl_token: imp.impl_token,
40 generics: imp.generics,
41 trait_,
42 for_token,
43 self_ty: *imp.self_ty,
44 brace_token: imp.brace_token,
45 items: imp.items,
46 })
47 }
48}
49
50impl ToTokens for TraitImpl {
51 fn to_tokens(&self, tokens: &mut TokenStream) {
52 let imp = self.clone();
53
54 ItemImpl::to_tokens(
55 &ItemImpl {
56 attrs: imp.attrs,
57 defaultness: imp.defaultness,
58 unsafety: imp.unsafety,
59 impl_token: imp.impl_token,
60 generics: imp.generics,
61 trait_: Some((None, imp.trait_, imp.for_token)),
62 self_ty: Box::new(imp.self_ty),
63 brace_token: imp.brace_token,
64 items: imp.items,
65 },
66 tokens,
67 );
68 }
69}