The last several posts have introduced a number of abstractions, namely HList, Generic, LabelledGeneric, as well as
sculpt(). Although each of those have impressive party tricks of their own, I’d like to share how you can use them to write a reuseable, generic function that handles converting between structs with mis-matched fields and thus have different
Unlike the last post, this one will be relatively light on recursion and mind-bending type-level stuff; it’s time to sit back and enjoy the fruits of our labour.
Adding Frunk to your project
It might be easier to follow along if you add Frunk to your project and play around with it. Frunk is published to Crates.io, so to add it your list of dependencies, simply put this in your
Alternatively, take a look at the published Rustdocs.
Boilerplate-free conversions between Structs
Suppose we have a bunch of structs that are similar-ish in terms of their data but ultimately, not necessarily
exactly the same. This means we can’t just use the normal
convert_from method to convert between them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
In our example,
InternalApiUser structs have fields that are subsets of the fields in
UserFromDb, and not in the same order either. The scenario is that
UserFromDb is a struct that we get from reading our persistence layer, and the other 2 are types that we use in our application for business logic.
Assuming a flow where we want to be able to go from
UserFromDb to either
InternalApiUser, the idea is that we don’t want be holding on to sensitive data like
pw_hash when we don’t need to, thus lowering the risk of accidentally leaking said data (e.g. serialising it by accident, or by rendering it in debug messages, etc).
While we could go about writing
Froms by hand for each of these, and for every other time a similar situation arises, that’s quite a lot of boilerplate to write and maintain. Thankfully, we can make use of Frunk’s
Sculptor to write a single, reuseable generic function.
Note, for a review of:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Not bad. The body of the function is literally 3 lines long :) Now we can do this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
In actuality, Frunk already ships with this function so you can use it out of the box.
Often times, you’ll hear that heterogeneous lists enable developers to write reuseable generic functions because they abstract over arity and types, and it might not be obvious exactly what that means on a practical level. The example shown in this post just scratches the surface of what is made possible through
LabelledGeneric, and there are definitely more creative usages out there, such as building of boilerplate-free (e.g. JSON) codecs (hint: look to Haskell and Scala libs for more).
As usual, please give it a spin and chime in with any questions, corrections, and suggestions !