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