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.
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"),
// ...
}