Multiple structs sharing the same field

I'm learning Rust and I'm creating a very simple app that interacts with a server. Some requests to that server take a form of a JSON payload that require a signature field. This field is added alongside the data like so:

{
  fieldA:"..",
  fieldB: 12,
  signature: "signature for {fieldA,fieldB}"
}

Since I have several of those I'm trying to figure out how generalize it so that I don't have to implement this for every signable payload. I was playing with traits and impls but I think this is still beyond my current understanding of Rust capabilities and type system. I understand that there is no inheritance in Rust, but I assume some magic trick can be done with the type system anyway, maybe a macro? Please advise :slight_smile:

I'm assuming you have an api like:

struct A {
  field_a: String,
  signature: String,
}

struct B {
  field_b: i32,
  signature: String,
}

one way to "share" fields, is to abstract that field into a new struct, and make the specification generic:

struct A {
  field_a: String,
}

struct B {
  field_b: i32,
}

struct Signable<T> {
  signature: String,
  data: T,
}

usually, what you would achieve with inheritance, you can replace for nested structs, where the "super" struct contains the "sub" struct

4 Likes

Not to suggest the previous answer isn’t exactly the desired design (I like it), however in the event there is shared behavior with struct A and B in addition to signature, another option exists.

Each could host a signature struct. To unify the types without resorting to a parametrized type, you could use an enum. Each variant be your version A, B, C etc… while not as generic, actually might provide more flexibility for what each A, B, C… host. Common capacity to respond to messages are specified for the enum using match. The error messages tend to be better this way. Finally, it avoids having to use traits for this purpose… save that “across type” capacity for something that is sufficiently more generic.

1 Like

The problem with nested structs is that the signature field in the end must be sent alongside data, not structured above. I guess a workaround to this issue might be some kind of data manipulation with serde Serializer?

Serde certainly supports displaying your structs in a different, e.g. less nested, manner; e.g. in simple cases via something like: Struct flattening · Serde

2 Likes

Yep, this is the headline usecase for flattening.