1

I'm trying to write a fairly complex macro in Rust. Here is what the macro would look like on the outside:

supported_messages![
    OpenSecureChannelRequest,
    OpenSecureChannelResponse,
    CloseSecureChannelRequest,
    CloseSecureChannelResponse,
    // This list will eventually have 100s of values
];

On the inside, it expands each id into something like this (plus a lot of other boiler plate):

ObjectId::Foo_Encoding_DefaultBinary => { SupportedMessage::Foo(Foo::decode()?) },

This pseudo-macro provides the gist of what I'm doing:

macro_rules! supported_messages {
    [ $( $x:ident ), * ] => {
       $( ObjectId::$x_Encoding_DefaultBinary => {
           SupportedMessage::$x($x::decode()?)
       }, )*
     }

The full macro and source is online to see here.

The macro takes an array of ids, and for each id spews out a set of match patterns similar to the example above.

I can't take the identifier $x, e.g. Foo and turn it into a new identifier Foo_Encoding_DefaultBinary.

Rust has a concat_idents!(), but from what I've read it's practically useless and it's deprecated. Is there another way? Procedural macros aren't available on the stable compiler yet and may not be easy to use either.

At present, I'm generating most of the other boilerplate automatically but have to write the code above by hand. It's very tedious.

Is there a way to do this?

In C, I'd just say Foo ## _Encoding_DefaultBinary and it would happen.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
locka
  • 5,809
  • 3
  • 33
  • 38
  • Is this not answered by ["How to prefix/suffix macro identifiers in Rust?"](http://stackoverflow.com/questions/39017871/how-to-prefix-suffix-macro-identifiers-in-rust/39018322#39018322)? – DK. Jan 21 '17 at 11:44
  • How do you define `ObjectId`? Do you list all possible variants manually there? Then it could be possible to combine definition and this match thingy into one macro. This at least avoids specifying the list twice. – Lukas Kalbertodt Jan 21 '17 at 11:51
  • Not really as its a different context and the answers basically say "you can't" rather than suggesting alternatives. – locka Jan 21 '17 at 12:15
  • @locka just because you don't *like* the answer doesn't mean that the answer is *incorrect* or that the question isn't a duplicate. If an existing question doesn't have the answer you like, the appropriate thing to do is to place a bounty on the existing question, soliciting additional answers. – Shepmaster Jan 21 '17 at 14:48
  • You've always got the possibility of a build script, as well. – Shepmaster Jan 21 '17 at 14:59
  • You could define a module that exposes ID's so instead of attempting to access `$x_Encoding_DefaultBinary`, it would access `some_module::$x::Encoding_DefaultBinary` - even if its a little tedious to define modules just to workaround this, it could be made to work. – ideasman42 Jan 22 '17 at 00:46

0 Answers0