1 /// Define a trait as usual, and a macro that can be used to instantiate 2 /// implementations of it. 3 /// 4 /// There *must* be section markers in the trait definition: 5 /// @section type for associated types 6 /// @section self for methods 7 /// @section nodelegate for arbitrary tail that is not forwarded. 8 macro_rules! trait_template { 9 ($(#[$doc:meta])* pub trait $name:ident $($methods:tt)*) => { 10 macro_rules! $name { 11 ($m:ident $extra:tt) => { 12 $m! { 13 $extra 14 pub trait $name $($methods)* 15 } 16 } 17 } 18 19 remove_sections! { [] 20 $(#[$doc])* 21 pub trait $name $($methods)* 22 23 // This is where the trait definition is reproduced by the macro. 24 // It makes the source links point to this place! 25 // 26 // I'm sorry, you'll have to find the source by looking at the 27 // source of the module the trait is defined in. 28 // 29 // We use this nifty macro so that we can automatically generate 30 // delegation trait impls and implement the graph traits for more 31 // types and combinators. 32 } 33 } 34 } 35 36 macro_rules! remove_sections_inner { 37 ([$($stack:tt)*]) => { 38 $($stack)* 39 }; 40 // escape the following tt 41 ([$($stack:tt)*] @escape $_x:tt $($t:tt)*) => { 42 remove_sections_inner!([$($stack)*] $($t)*); 43 }; 44 ([$($stack:tt)*] @section $x:ident $($t:tt)*) => { 45 remove_sections_inner!([$($stack)*] $($t)*); 46 }; 47 ([$($stack:tt)*] $t:tt $($tail:tt)*) => { 48 remove_sections_inner!([$($stack)* $t] $($tail)*); 49 }; 50 } 51 52 // This is the outer layer, just find the { } of the actual trait definition 53 // recurse once into { }, but not more. 54 macro_rules! remove_sections { 55 ([$($stack:tt)*]) => { 56 $($stack)* 57 }; 58 ([$($stack:tt)*] { $($tail:tt)* }) => { 59 $($stack)* { 60 remove_sections_inner!([] $($tail)*); 61 } 62 }; 63 ([$($stack:tt)*] $t:tt $($tail:tt)*) => { 64 remove_sections!([$($stack)* $t] $($tail)*); 65 }; 66 } 67 68 macro_rules! deref { 69 ($e:expr) => { 70 *$e 71 }; 72 } 73 macro_rules! deref_twice { 74 ($e:expr) => { 75 **$e 76 }; 77 } 78 79 /// Implement a trait by delegation. By default as if we are delegating 80 /// from &G to G. 81 macro_rules! delegate_impl { 82 ([] $($rest:tt)*) => { 83 delegate_impl! { [['a, G], G, &'a G, deref] $($rest)* } 84 }; 85 ([[$($param:tt)*], $self_type:ident, $self_wrap:ty, $self_map:ident] 86 pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* { 87 88 // "Escaped" associated types. Stripped before making the `trait` 89 // itself, but forwarded when delegating impls. 90 $( 91 @escape [type $assoc_name_ext:ident] 92 // Associated types. Forwarded. 93 )* 94 $( 95 @section type 96 $( 97 $(#[$_assoc_attr:meta])* 98 type $assoc_name:ident $(: $assoc_bound:ty)*; 99 )+ 100 )* 101 // Methods. Forwarded. Using $self_map!(self) around the self argument. 102 // Methods must use receiver `self` or explicit type like `self: &Self` 103 // &self and &mut self are _not_ supported. 104 $( 105 @section self 106 $( 107 $(#[$_method_attr:meta])* 108 fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) $(-> $mret:ty)?; 109 )+ 110 )* 111 // Arbitrary tail that is ignored when forwarding. 112 $( 113 @section nodelegate 114 $($tail:tt)* 115 )* 116 }) => { 117 impl<$($param)*> $name for $self_wrap where $self_type: $name { 118 $( 119 $( 120 type $assoc_name = $self_type::$assoc_name; 121 )* 122 )* 123 $( 124 type $assoc_name_ext = $self_type::$assoc_name_ext; 125 )* 126 $( 127 $( 128 fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) $(-> $mret)? { 129 $self_map!(self).$method_name($($marg),*) 130 } 131 )* 132 )* 133 } 134 } 135 } 136