How to implement quote::ToTokens for an enum?
Asked Answered
S

1

6

I am implementing a procedural macro and I need to provide my own structures to the outside. I need to implement quote::ToTokens trait for my structures, but I don't understand how. I have tried this code but did not succeed. This code is compilable, but it is not valid:

#[derive(Debug, Serialize, Clone)]
pub enum Enum {
    A,
    B,
}
impl quote::ToTokens for Enum {
    fn to_tokens(&self, tokens: &mut quote::Tokens) {
        tokens.append("Enum::B");
    }
}

The quote::ToTokens example does not explain this.

Saddletree answered 13/2, 2017 at 14:26 Comment(0)
E
2

I think you are looking for something like:

impl quote::ToTokens for Enum {
    fn to_tokens(&self, tokens: &mut quote::Tokens) {
        tokens.append("Enum");
        tokens.append("::");
        match *self {
           Enum::A => tokens.append("A"),
           Enum::B => tokens.append("B")
        }
    }
}

If you are concerned with how the enum has been imported, then you should re-import it to make sure it is not conflicting with anything else:

impl quote::ToTokens for Enum {
    fn to_tokens(&self, tokens: &mut quote::Tokens) {
        tokens.append("{");
        tokens.append("use");
        tokens.append_separated(&["module_name", "Enum"], "::");
        tokens.append(";");
        tokens.append("Enum");
        tokens.append("::");
        match *self {
           Enum::A => tokens.append("A"),
           Enum::B => tokens.append("B")
        }
        tokens.append("}");
    }
}

Which will produce:

 { use module_name::Enum; Enum::A }
Extinguisher answered 13/2, 2017 at 14:37 Comment(6)
What if we have "use Enum as E;" in our code or we did not even provided use for it so it must be prepended with "cratename::" ? Personally I think there must be a method of getting fully qualified name for the requested item. P.S. My question implies that your code in your answer is incorrect too :)Saddletree
Probably you should always use the fully qualified name, including crate, just to be safe. It's quite ugly though. I'll update the answer.Extinguisher
You can use it once inside the function, then you would only need to FQN it in the impl and in the use itself.Madlin
This answer is out of date. tokens.append(&str) no longer works.Quirinus
@FordO. what is the alternative now? just ran into this issueDonata
I'm also running into this. I think we're now supposed to use quote::TokenStreamExt ("TokenStream extension trait with methods for appending tokens") but I haven't made it work, I get: "the trait cannot be made into an object because method append has generic type parameters"Floriaflorian

© 2022 - 2024 — McMap. All rights reserved.