A have a struct with attributes that could have different types
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct A {
pub foo: B | C
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct B {
pub bar: usize
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct C {
pub bar2: usize
}
Is it possible in rust to achieve something like pub foo: B | C, so the type will be determined on runtime?
Is it possible in rust to achieve something like pub foo: B | C, so the type will be determined on runtime?
The way to do this in Rust is with an enum storing items of either:
#[derive(Debug, Deserialize, Serialize, Clone)]
pub enum A {
B(B),
C(C)
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct B {
pub bar: usize
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct C {
pub bar2: usize
}
Here A can have one of two values: A::B which contains a value of type B (in a way similar to single-member tuple structs) or A::C which contains a value of type C. A::B and B should not be confused: the former is essentially a function while the latter is a type.
The basest way to get values out of enums is pattern matching:
fn foo(a: A) {
match a {
A::B(b) => println!("Got a B: {:?}", b),
A::C(c) => println!("Got a C: {:?}", c)
}
}
Since Rust enums are completely standard types you can also add utility methods to them, that is exactly how e.g. Option and Result work e.g.
impl A {
fn b(&self) -> Option<&B> {
if let A::B(b) = self { Some(b) } else { None }
}
fn c(&self) -> Option<&C> {
if let A::C(c) = self { Some(c) } else { None }
}
}
fn bar(a: A) {
if a.b().is_some() {
println!("Got a B!");
} else {
println!("Got a C :(");
}
}
Now since you are deriving Serialize and Deserialize with this I assume you're also interfacing with an external system e.g. typescript or whatever.
In that case you will almost certainly have to customise the serialisation scheme of the enum: serde's default is external tagging which in my experience is never what you're looking for, because it's really not a scheme other languages tend to use for their (formal or informal) unions.
Internal tagging and untagged are much more common, with the odd adjacent tagging once in a (rare) while.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With