| use proc_macro2::Ident; | 
 | use quote::quote; | 
 | use syn::parse::{Parse, ParseStream}; | 
 | use syn::punctuated::Punctuated; | 
 | use syn::spanned::Spanned; | 
 | use syn::{ | 
 |     Attribute, Generics, ImplItem, Pat, PatIdent, Path, Signature, Token, TraitItem, | 
 |     TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, Type, Visibility, WhereClause, | 
 |     braced, parse_macro_input, | 
 | }; | 
 |  | 
 | pub(crate) fn extension( | 
 |     attr: proc_macro::TokenStream, | 
 |     input: proc_macro::TokenStream, | 
 | ) -> proc_macro::TokenStream { | 
 |     let ExtensionAttr { vis, trait_ } = parse_macro_input!(attr as ExtensionAttr); | 
 |     let Impl { attrs, generics, self_ty, items, wc } = parse_macro_input!(input as Impl); | 
 |     let headers: Vec<_> = items | 
 |         .iter() | 
 |         .map(|item| match item { | 
 |             ImplItem::Fn(f) => TraitItem::Fn(TraitItemFn { | 
 |                 attrs: scrub_attrs(&f.attrs), | 
 |                 sig: scrub_header(f.sig.clone()), | 
 |                 default: None, | 
 |                 semi_token: Some(Token)), | 
 |             }), | 
 |             ImplItem::Const(ct) => TraitItem::Const(TraitItemConst { | 
 |                 attrs: scrub_attrs(&ct.attrs), | 
 |                 const_token: ct.const_token, | 
 |                 ident: ct.ident.clone(), | 
 |                 generics: ct.generics.clone(), | 
 |                 colon_token: ct.colon_token, | 
 |                 ty: ct.ty.clone(), | 
 |                 default: None, | 
 |                 semi_token: ct.semi_token, | 
 |             }), | 
 |             ImplItem::Type(ty) => TraitItem::Type(TraitItemType { | 
 |                 attrs: scrub_attrs(&ty.attrs), | 
 |                 type_token: ty.type_token, | 
 |                 ident: ty.ident.clone(), | 
 |                 generics: ty.generics.clone(), | 
 |                 colon_token: None, | 
 |                 bounds: Punctuated::new(), | 
 |                 default: None, | 
 |                 semi_token: ty.semi_token, | 
 |             }), | 
 |             ImplItem::Macro(mac) => TraitItem::Macro(TraitItemMacro { | 
 |                 attrs: scrub_attrs(&mac.attrs), | 
 |                 mac: mac.mac.clone(), | 
 |                 semi_token: mac.semi_token, | 
 |             }), | 
 |             ImplItem::Verbatim(stream) => TraitItem::Verbatim(stream.clone()), | 
 |             _ => unimplemented!(), | 
 |         }) | 
 |         .collect(); | 
 |  | 
 |     quote! { | 
 |         #(#attrs)* | 
 |         #vis trait #trait_ { | 
 |             #(#headers)* | 
 |         } | 
 |  | 
 |         impl #generics #trait_ for #self_ty #wc { | 
 |             #(#items)* | 
 |         } | 
 |     } | 
 |     .into() | 
 | } | 
 |  | 
 | /// Only keep `#[doc]` attrs. | 
 | fn scrub_attrs(attrs: &[Attribute]) -> Vec<Attribute> { | 
 |     attrs | 
 |         .into_iter() | 
 |         .cloned() | 
 |         .filter(|attr| { | 
 |             let ident = &attr.path().segments[0].ident; | 
 |             ident == "doc" || ident == "must_use" | 
 |         }) | 
 |         .collect() | 
 | } | 
 |  | 
 | /// Scrub arguments so that they're valid for trait signatures. | 
 | fn scrub_header(mut sig: Signature) -> Signature { | 
 |     for (idx, input) in sig.inputs.iter_mut().enumerate() { | 
 |         match input { | 
 |             syn::FnArg::Receiver(rcvr) => { | 
 |                 // `mut self` -> `self` | 
 |                 if rcvr.reference.is_none() { | 
 |                     rcvr.mutability.take(); | 
 |                 } | 
 |             } | 
 |             syn::FnArg::Typed(arg) => match &mut *arg.pat { | 
 |                 Pat::Ident(arg) => { | 
 |                     // `ref mut ident @ pat` -> `ident` | 
 |                     arg.by_ref.take(); | 
 |                     arg.mutability.take(); | 
 |                     arg.subpat.take(); | 
 |                 } | 
 |                 _ => { | 
 |                     // `pat` -> `__arg0` | 
 |                     arg.pat = Box::new( | 
 |                         PatIdent { | 
 |                             attrs: vec![], | 
 |                             by_ref: None, | 
 |                             mutability: None, | 
 |                             ident: Ident::new(&format!("__arg{idx}"), arg.pat.span()), | 
 |                             subpat: None, | 
 |                         } | 
 |                         .into(), | 
 |                     ) | 
 |                 } | 
 |             }, | 
 |         } | 
 |     } | 
 |     sig | 
 | } | 
 |  | 
 | struct ExtensionAttr { | 
 |     vis: Visibility, | 
 |     trait_: Path, | 
 | } | 
 |  | 
 | impl Parse for ExtensionAttr { | 
 |     fn parse(input: ParseStream<'_>) -> syn::Result<Self> { | 
 |         let vis = input.parse()?; | 
 |         let _: Token![trait] = input.parse()?; | 
 |         let trait_ = input.parse()?; | 
 |         Ok(ExtensionAttr { vis, trait_ }) | 
 |     } | 
 | } | 
 |  | 
 | struct Impl { | 
 |     attrs: Vec<Attribute>, | 
 |     generics: Generics, | 
 |     self_ty: Type, | 
 |     items: Vec<ImplItem>, | 
 |     wc: Option<WhereClause>, | 
 | } | 
 |  | 
 | impl Parse for Impl { | 
 |     fn parse(input: ParseStream<'_>) -> syn::Result<Self> { | 
 |         let attrs = input.call(Attribute::parse_outer)?; | 
 |         let _: Token![impl] = input.parse()?; | 
 |         let generics = input.parse()?; | 
 |         let self_ty = input.parse()?; | 
 |         let wc = input.parse()?; | 
 |  | 
 |         let content; | 
 |         let _brace_token = braced!(content in input); | 
 |         let mut items = Vec::new(); | 
 |         while !content.is_empty() { | 
 |             items.push(content.parse()?); | 
 |         } | 
 |  | 
 |         Ok(Impl { attrs, generics, self_ty, items, wc }) | 
 |     } | 
 | } |