Some C function that I use return a struct with union inside it. This struct is basically tagged union with the first field act as discriminant value and the second act as its content. Currently what I do is just write the C struct (Foo) and enum (FooEnum) like this:
use std::mem;
#[repr(C)]
#[derive(Debug)]
struct Bar{
value: i64
}
#[repr(C)]
#[derive(Debug)]
struct Baz{
value: i8
}
#[repr(C)]
#[derive(Debug)]
struct Foo{
discriminant: i32,
content: Bar // Bar is the largest variant
}
#[derive(Debug)]
enum FooEnum{
Bar(Bar),
Baz(Baz)
}
impl Foo {
fn get_enum(&self) -> FooEnum{
match self.discriminant {
0 => FooEnum::Bar(Bar{value: unsafe{mem::transmute_copy(&self.content)}}),
1 => FooEnum::Baz(Baz{value: unsafe{mem::transmute_copy(&self.content)}}),
_ => unreachable!()
}
}
}
fn main(){
let x = Foo{discriminant: 1, content: Bar{value: 9}};
let y = x.get_enum();
println!("x = {:?}", x); // y = Baz(Baz { value: 9 })
println!("y = {:?}", y); // print "y = Baz(Baz { value: 9 })"
}
However, I not sure if this strategy is good or not.
I am curious about what the others do to solve this union problem because I have seen many c libraries use union to represent its value.
C Structure with its first field as discriminant:
- INPUT_RECORD [link: INPUT_RECORD structure - Windows Console | Microsoft Docs]
C Union which encoded the discriminant as first field of each structs:
- SDL_Event, link: SDL_Event