I have a couple of structs (StructX
and StructY
), and another struct that has all the common reference properties of the previous ones (StructCommon
).
I also have a function for each of StructX
and StructY
that returns a StructCommon
, but my issue is that I had to write two functions for it.
pub struct StructX<'a> {
a: &'a str,
b: &'a str,
x: &'a str,
}
pub struct StructY<'a> {
a: &'a str,
b: &'a str,
y: &'a str,
}
pub struct StructCommon<'a> {
a: &'a str,
b: &'a str,
}
impl<'a> StructCommon<'a> {
pub fn from_x<T>(serialized: &StructX) -> StructCommon<'a>
{
StructCommon {
a: serialized.a,
b: serialized.b,
}
}
pub fn from_y<T>(serialized: &StructY) -> StructCommon<'a>
{
StructCommon {
a: serialized.a,
b: serialized.b,
}
}
// Pseudo-Rust proposed solution example:
// pub fn from_either<T>(serialized: &StructX | &StructY) -> StructCommon<'a>
// {
// StructCommon {
// a: serialized.a,
// b: serialized.b,
// }
// }
}
How can I - if possible - deduplicate the from_x()
and from_y()
methods so I would only have to write the logic for extracting the common properties only once**?**
I have written an imaginary pseudo-code solution example method commented out called from_either()
.
CodePudding user response:
There is another answer focusing on your specific question, but I propose an alternative solution of having StructX
and StructY
containing a StructCommon
instead of having fields that happen to have the same name and type as those in StructCommmon
. This reduces the boilerplate of converting by just returning the internal structure:
pub struct StructX<'a> {
common: StructCommon<'a>,
x: &'a str,
}
pub struct StructCommon<'a> {
a: &'a str,
b: &'a str,
}
impl<'a> Into<StructCommon<'a>> for StructX<'a> {
fn into(self) -> StructCommon<'a> {
self.common
}
}
This is still some boilerplate, but much less and doesn't need to change when you change the common fields.
CodePudding user response:
I don't think you can directly express what you want using generics in Rust unless you write a trait with methods like get_a()
and get_b()
and use that for your generic implementation of from_either()
. That really doesn't reduce your boilerplate though.
However, procedural macros looks like a good fit for what you're trying to do. For example, you could create a derive macro that implements Into<StructCommon>
for StructX
and StructY
, and the macro can write the boilerplate code for you.