| |
| /// Define a trait as usual, and a macro that can be used to instantiate |
| /// implementations of it. |
| /// |
| /// There *must* be section markers in the trait defition: |
| /// @section type for associated types |
| /// @section self for methods |
| /// @section nodelegate for arbitrary tail that is not forwarded. |
| macro_rules! trait_template { |
| ($(#[$doc:meta])* pub trait $name:ident $($methods:tt)*) => { |
| macro_rules! $name { |
| ($m:ident $extra:tt) => { |
| $m! { |
| $extra |
| pub trait $name $($methods)* |
| } |
| } |
| } |
| |
| remove_sections! { [] |
| $(#[$doc])* |
| pub trait $name $($methods)* |
| |
| // This is where the trait definition is reproduced by the macro. |
| // It makes the source links point to this place! |
| // |
| // I'm sorry, you'll have to find the source by looking at the |
| // source of the module the trait is defined in. |
| // |
| // We use this nifty macro so that we can automatically generate |
| // delegation trait impls and implement the graph traits for more |
| // types and combinators. |
| } |
| } |
| } |
| |
| macro_rules! remove_sections_inner { |
| ([$($stack:tt)*]) => { |
| $($stack)* |
| }; |
| // escape the following tt |
| ([$($stack:tt)*] @escape $_x:tt $($t:tt)*) => { |
| remove_sections_inner!([$($stack)*] $($t)*); |
| }; |
| ([$($stack:tt)*] @section $x:ident $($t:tt)*) => { |
| remove_sections_inner!([$($stack)*] $($t)*); |
| }; |
| ([$($stack:tt)*] $t:tt $($tail:tt)*) => { |
| remove_sections_inner!([$($stack)* $t] $($tail)*); |
| }; |
| } |
| |
| // This is the outer layer, just find the { } of the actual trait definition |
| // recurse once into { }, but not more. |
| macro_rules! remove_sections { |
| ([$($stack:tt)*]) => { |
| $($stack)* |
| }; |
| ([$($stack:tt)*] { $($tail:tt)* }) => { |
| $($stack)* { |
| remove_sections_inner!([] $($tail)*); |
| } |
| }; |
| ([$($stack:tt)*] $t:tt $($tail:tt)*) => { |
| remove_sections!([$($stack)* $t] $($tail)*); |
| }; |
| } |
| |
| macro_rules! deref { |
| ($e:expr) => (*$e); |
| } |
| macro_rules! deref_twice { |
| ($e:expr) => (**$e); |
| } |
| |
| /// Implement a trait by delegation. By default as if we are delegating |
| /// from &G to G. |
| macro_rules! delegate_impl { |
| ([] $($rest:tt)*) => { |
| delegate_impl! { [['a, G], G, &'a G, deref] $($rest)* } |
| }; |
| ([[$($param:tt)*], $self_type:ident, $self_wrap:ty, $self_map:ident] |
| pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* { |
| |
| // "Escaped" associated types. Stripped before making the `trait` |
| // itself, but forwarded when delegating impls. |
| $( |
| @escape [type $assoc_name_ext:ident] |
| // Associated types. Forwarded. |
| )* |
| $( |
| @section type |
| $( |
| $(#[$_assoc_attr:meta])* |
| type $assoc_name:ident $(: $assoc_bound:ty)*; |
| )+ |
| )* |
| // Methods. Forwarded. Using $self_map!(self) around the self argument. |
| // Methods must use receiver `self` or explicit type like `self: &Self` |
| // &self and &mut self are _not_ supported. |
| $( |
| @section self |
| $( |
| $(#[$_method_attr:meta])* |
| fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) -> $mret:ty; |
| )+ |
| )* |
| // Arbitrary tail that is ignored when forwarding. |
| $( |
| @section nodelegate |
| $($tail:tt)* |
| )* |
| }) => { |
| impl<$($param)*> $name for $self_wrap where $self_type: $name { |
| $( |
| $( |
| type $assoc_name = $self_type::$assoc_name; |
| )* |
| )* |
| $( |
| type $assoc_name_ext = $self_type::$assoc_name_ext; |
| )* |
| $( |
| $( |
| fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) -> $mret { |
| $self_map!(self).$method_name($($marg),*) |
| } |
| )* |
| )* |
| } |
| } |
| } |
| |