Search code examples
rustcompiler-construction

How to store a dynamically typed variable in a Rust struct?


I disclaim that I'm a beginner in Rust and this is my first project. I'm trying to code a SQL compiler in Rust. I have to create a Token struct that represents a syntactical unit of a SQL query. In C/C++ I would write a structure like this:

typedef unsigned long Value;

// Represents the type of the token (e.g. number, string, identifier...)
typedef enum class TokenType { ... }

struct Token {
  TokenType type;
  unsigned char priority;
  Value value;
}

Using this approach I use the Value type to store any kind of value. If it's a number, value is interpreted as an integer, float..., whereas when value represents a string or an identifier, it is cast to a string pointer and then used to access the heap-allocated data it points to.
To decide how to handle the value property of Token, I use the type field. For example, if type tells me the token is an integer, I cast value to an int. If type tells me the token is an identifier, I cast value to a string pointer.

My question is, is it possible to do something similar in safe Rust? If not, then what would be a nice way of achieving a dynamically typed variable that can be interpreted in multiple ways based on the TokenType? Or is there a neater approach to creating a syntactical token that works well in Rust?

Thanks in advance.


Solution

  • In Rust, where you have a closed set of possible types, you should use an enum. Enums in Rust are not like in C: they can carry payload (i.e. they're sum types).

    enum TokenType {
        Number(i32),
        Identifier(String),
        String(String),
        Plus,
        Minus,
        // ...
    }
    

    And then match against it:

    let e: TokenType = ...;
    match e {
        TokenType::Number(n) => println!("number: {n}"),
        TokenType::String(s) => println!("string: {s}"),
        TokenType::Plus => println!("plus"),
        // ...
    }