Complex enumerations

If you know about C/C++ enumerations, you know that each element represents a value, and that you can use them to avoid remembering the proper integers from the set of possible values. They are not strongly typed, though, so you can mix different enumerations. And they can only store one integer.

Once again, Rust can do better, and we can create complex enumerations where we cannot only have strong typing (we won't mix enumerations) but we will even be able to have more than integers in enumerations. As you can see in the following Color enumeration, we can have inner data, and even attributes:

enum Color {
Red,
Blue,
Green,
Other { r: u32, g: u32, b: u32 },
}

As you can see, in this case, the enumeration can have one of four values, but in the case of the last one, it will have three numbers associated. This gives you almost infinite possibilities, where you can safely represent any data structure. Check out, for instance, this implementation of any JSON value by the Serde crate, one of the most-used crates in the ecosystem:

pub enum Value {
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(Map<String, Value>),
}

A value in a JSON structure can either be null, a Boolean (and with the information whether it's true or false), a number (that will be another enumeration to know whether it's positive, negative, or float point), a string, with the text information, an array of values, or a whole JSON object with its keys as strings and values.

There are two caveats with this approach, though. For comparison between the different variants of an enumeration, they must be tagged. This means that they will need to occupy some extra space just to differentiate between them at runtime.

The second problem is that the size of the enumeration type (without taking into account the tag) will be the size of the biggest option. So if you have 10 options that can be stored in 1 byte, but another one needs 10 bytes, the enumeration will have 10 bytes (plus the tag) independently of the variant being stored. This works this way because it works as a union (in C/C++ language), where all variants share the same representation.

To mitigate this, an option is for big objects to be references. We can do this in two ways. The first way is by borrowing the color, in which case the compiler will force us to not return the enumeration from any function where the color was created (remember, the reference would be destroyed at the end of the scope):

enum Color<'c> {
Red,
Blue,
Green,
Other(&'c Rgb),
}

struct Rgb {
r: u32,
g: u32,
b: u32,
}

And if we want to avoid that, we can simply store that element in the heap by boxing it (yes, this will slow performance). It depends whether you require a lower RAM consumption or an improved speed. To store an element in the heap, you will need to use the Box type, as you can see here:

enum Color {
Red,
Blue,
Green,
Other(Box<Rgb>),
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.77.63